From 3fd4f02b752db3c64466b5be7795ff1c058c1826 Mon Sep 17 00:00:00 2001 From: rodley82 Date: Tue, 24 Feb 2026 13:07:44 +1300 Subject: [PATCH] now using json resume standard structure --- app/admin/users_admin.rb | 125 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 3 deletions(-) diff --git a/app/admin/users_admin.rb b/app/admin/users_admin.rb index d8960d0..186a12c 100644 --- a/app/admin/users_admin.rb +++ b/app/admin/users_admin.rb @@ -44,10 +44,129 @@ Trestle.resource(:users) do end def generate_json + generate_json_resume + end + + def generate_json_resume user = admin.find_instance(params) - ac = ActionController::Base.new() - json = ac.render_to_string(layout: false, template: "users/show", locals: { "@user": user } ) - render json: json, layout: false + + split_list = lambda do |value| + value.to_s.split(/[;,]/).map { |item| item.strip }.reject(&:blank?) + end + + parse_period = lambda do |period| + years = period.to_s.scan(/\b(19\d{2}|20\d{2})\b/).flatten + return [nil, nil] if years.empty? + [years[0], years[1]] + end + + normalize_url = lambda do |value| + return nil if value.blank? + value.match?(/\Ahttps?:\/\//) ? value : "https://#{value}" + end + + profile_from = lambda do |value, network, base_url| + return nil if value.blank? + + if value.include?("/") || value.include?(".") + url = normalize_url.call(value) + username = url.to_s.split("/").last&.delete_prefix("@") + else + username = value.delete_prefix("@") + url = base_url.present? ? "#{base_url}/#{username}" : nil + end + + profile = { "network" => network } + profile["username"] = username if username.present? + profile["url"] = url if url.present? + profile + end + + basics = { + "name" => user.name, + "label" => user.title, + "email" => user.email, + "phone" => user.phone, + "summary" => user.objective + }.compact + + if user.address.present? + basics["location"] = { "address" => user.address } + end + + primary_url = user.other_page_url.presence || user.linkedin.presence || user.github.presence + basics["url"] = normalize_url.call(primary_url) if primary_url.present? + + profiles = [] + profiles << profile_from.call(user.linkedin, "LinkedIn", "https://www.linkedin.com/in") + profiles << profile_from.call(user.github, "GitHub", "https://github.com") + profiles << profile_from.call(user.other_page_url, "Website", nil) + profiles.compact! + basics["profiles"] = profiles if profiles.any? + + work = user.work_experiences.active.map do |work_entry| + start_date, end_date = parse_period.call(work_entry.period) + highlights = split_list.call(work_entry.items_csv) + technologies = split_list.call(work_entry.technologies) + highlights << "Technologies: #{technologies.join(', ')}" if technologies.any? + + summary = work_entry.achivements.presence + summary = work_entry.period.presence if summary.blank? && start_date.blank? && end_date.blank? + + entry = { + "name" => work_entry.employer, + "position" => work_entry.title + }.compact + entry["summary"] = summary if summary.present? + entry["highlights"] = highlights if highlights.any? + entry["startDate"] = start_date if start_date.present? + entry["endDate"] = end_date if end_date.present? + if entry["startDate"].blank? && entry["endDate"].blank? && work_entry.reference_date.present? + entry["endDate"] = work_entry.reference_date.iso8601 + end + entry + end + + education = user.education_entries.active.map do |education_entry| + start_date, end_date = parse_period.call(education_entry.period) + + study_type = education_entry.title + area = nil + if study_type.present? && study_type.match?(/\s+in\s+/i) + study_type, area = study_type.split(/\s+in\s+/i, 2) + end + + courses = split_list.call(education_entry.items_csv) + + entry = { "institution" => education_entry.institution }.compact + entry["studyType"] = study_type if study_type.present? + entry["area"] = area if area.present? + entry["courses"] = courses if courses.any? + entry["startDate"] = start_date if start_date.present? + entry["endDate"] = end_date if end_date.present? + if entry["startDate"].blank? && entry["endDate"].blank? && education_entry.reference_date.present? + entry["endDate"] = education_entry.reference_date.iso8601 + end + entry + end + + skills = user.skills.active.map do |skill| + keywords = split_list.call(skill.detail) + entry = { "name" => skill.title }.compact + if keywords.any? + entry["keywords"] = keywords + elsif skill.detail.present? + entry["level"] = skill.detail + end + entry + end + + resume = { "basics" => basics } + resume["work"] = work if work.any? + resume["education"] = education if education.any? + resume["skills"] = skills if skills.any? + + render json: resume, layout: false end def generate_tex(template: "resume")