Skip to content

Commit

Permalink
Feature/652-readd-cv-search (#664)
Browse files Browse the repository at this point in the history
* Modify old search controller to not send json and add view with non-functional searchbar & routes for this new cv search controller

* Add message if there are no results and make searchbar functional

* Style search results to make them look like in the old version of skills

* Make search results display name and found in value and change oninput to onchange

* Reload serach-results via turboframe and change onchange to oninput

* Create stimulus controller to add a short timeout before submitting, use this controller in the cv-search search-field and update stimulus manifest

* Add translations for cv search and implement translation of results in view

* Filter results from cv-search that have nil values as found_in and convert translation keys in cv search index view to snake case

* Change translation key from camel to snake case in de.yml

* Add link to cv search to header

* Make clicking on search result preserve query params and implement highlighting of search results

* Remove unnecessary stimulus controller action and write same functionality directly in view

* Shorten filter method that filters out nil values for found_in in people_search controller

* Make cv search form only submit if value length > 3

* Write cv search specs, add new missing translations and make search result link not trigger turbo-frame

* Move logic that excludes results for searches with length < 3 to view

* Add spec that asserts that results are only displayed with a search text length > 3

* Replace hardcoded route with path helper in header entry of cv search

* Instead of not showing results for queries with length < 3 just return empty array in controller

* Nest hover styles into normal styles

* Move logic that decides wether or not to do cv search from controller to concern

* Move logic that translates the found_in value and the one that creates a person link with search query from cv search view to a new helper

* Reduce timeout in cv search from 400ms to 100ms

* Populate value from query-params in cv search field on reload

* Resolve rubocop offence

* Move should search method from concern to controller
  • Loading branch information
RandomTannenbaum authored Apr 23, 2024
1 parent 3827898 commit a695968
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 18 deletions.
23 changes: 21 additions & 2 deletions app/assets/stylesheets/styles.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
$skills-blue: #3b7bbe;
$skills-text-gray: #8e8e8e;
$skills-gray: #f5f5f5;
$skills-green: #69b978;
$skills-green-hover: #4e903c;
$skills-search-result-blue: #238bca;
$skills-banner-text-blue: #1e5a96;

@import "bootstrap";
Expand Down Expand Up @@ -83,14 +86,30 @@ pzsh-topbar {

.bg-skills-blue {
background-color: $skills-blue;

&:hover {
background-color: #3268a1;
}
}

.bg-skills-gray {
background-color: $skills-gray;
}

.bg-skills-blue:hover {
background-color: #3268a1;
.bg-skills-green {
background-color: $skills-green;

&:hover {
background-color: $skills-green-hover;
}
}

.bg-skills-search-result-blue {
background-color: $skills-search-result-blue;

&:hover {
background-color: $skills-green-hover;
}
}

.fixed-table {
Expand Down
21 changes: 21 additions & 0 deletions app/controllers/cv_search_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class CvSearchController < ApplicationController
def index
@cv_search_results = should_search ? [] : search_results
end

private

def search_results
PeopleSearch.new(query).entries
end

def query
params[:q]
end

def should_search
query.nil? || query.length < 3
end
end
1 change: 1 addition & 0 deletions app/domain/people_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class PeopleSearch
def initialize(search_term)
@search_term = search_term
@entries = search_result
@entries = @entries.filter { |entry| entry[:found_in] }
end

private
Expand Down
11 changes: 11 additions & 0 deletions app/helpers/cv_search_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module CvSearchHelper
def translate_found_in(result)
I18n.t("cv_search.#{result[:found_in].split('#')[0].underscore}")
end

def person_path_with_query(result)
"#{person_path(result[:person][:id])}?q=#{params[:q]}"
end
end
10 changes: 10 additions & 0 deletions app/javascript/controllers/highlight_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
connect() {
const params = new URLSearchParams(window.location.search);
if(params.has("q")) {
window.find(params.get("q"))
}
}
}
28 changes: 15 additions & 13 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@

import { application } from "./application"

import DatePickerController from "./date_picker_controller"
application.register("date-picker", DatePickerController)

import DropdownController from "./dropdown_controller"
application.register("dropdown", DropdownController)

import DynamicFieldsController from "./dynamic_fields_controller"
application.register("dynamic-fields", DynamicFieldsController)

import HighlightController from "./highlight_controller"
application.register("highlight", HighlightController)

import ImageUploadController from "./image_upload_controller"
application.register("image-upload", ImageUploadController)

Expand All @@ -19,21 +25,17 @@ application.register("lang-selection", LangSelectionController)
import NationalityTwoController from "./nationality_two_controller"
application.register("nationality-two", NationalityTwoController)

import ProfileTabController from "./profile_tab_controller"
application.register("profile-tab", ProfileTabController)

import RemoteModalController from "./remote_modal_controller"
application.register("remote-modal", RemoteModalController)

import SkillsFilterController from "./skills_filter_controller"
application.register("skills-filter", SkillsFilterController)

import DatePickerController from "./date_picker_controller"
application.register("date-picker", DatePickerController)
import SearchController from "./search_controller"
application.register("search", SearchController)

import DropdownLinksController from "./dropdown_controller"
application.register("dropdown", DropdownLinksController)

import ProfileTabController from "./profile_tab_controller"
application.register("profile-tab", ProfileTabController)

import SkillsLevelController from "./skill_level_controller"
application.register("skills-level", SkillsLevelController)
import SkillLevelController from "./skill_level_controller"
application.register("skill-level", SkillLevelController)

import SkillsFilterController from "./skills_filter_controller"
application.register("skills-filter", SkillsFilterController)
20 changes: 20 additions & 0 deletions app/javascript/controllers/search_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {

connect() {
const params = new URLSearchParams(window.location.search);
if(params.has("q")) {
document.getElementById("cv_search_field").value = params.get("q");
}
}

timeout;
submitWithTimeout(e) {
const form = e.target.parentElement;
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
form.requestSubmit();
}, 100)
}
}
16 changes: 16 additions & 0 deletions app/views/cv_search/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%div.mt-2
%form{data: {"turbo-frame": "search-results", "turbo-action": "advance"}, "data-controller": "search"}
%input{class: 'form-control w-75', placeholder: 'CVs durchsuchen...', name: 'q', "data-action": "search#submitWithTimeout", id: "cv_search_field"}
%div.profile-header.mw-100.border-bottom.mt-2.mb-2
Suchresultate
%turbo-frame{id: "search-results"}
- if @cv_search_results.blank?
Keine Resultate
- else
- @cv_search_results.each do |result|
%div.w-50.d-flex
= link_to result[:person][:name], person_path(result[:person][:id]), {class: "bg-skills-green w-50 text-decoration-none text-white ps-1 p-2 rounded-1", "data-turbo": "false"}
%div.w-50.d-flex.justify-content-end.align-items-center
%div.me-1 gefunden in:
= link_to translate_found_in(result), person_path_with_query(result), {class: "bg-skills-search-result-blue w-50 text-decoration-none text-white ps-1 p-2 rounded-1 text-center", "data-turbo": "false"}
%br
4 changes: 2 additions & 2 deletions app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
- if auth_user_signed_in?
=link_to "Logout", destroy_auth_user_session_path, data: { "turbo-method": :delete}
- elsif devise_mapping.omniauthable?
=button_to "Login", omniauth_authorize_path(resource_name, resource_class.omniauth_providers.first), {data: { "turbo": false}, class: "btn btn-link"}
=button_to "Login", omniauth_authorize_path(resource_name, resource_class.omniauth_providers.first), {data: { "turbo": false }, class: "btn btn-link"}
%div.puzzle-header
%div.d-flex.h-100
%ul.navbar.h-100
Expand All @@ -43,7 +43,7 @@
%li.bg-skills-blue.h-100.d-flex.align-items-center
%a.nav-link.cursor-pointer.ps-2.pe-2{href: people_skills_path} Skill Suche
%li.bg-skills-blue.h-100.d-flex.align-items-center
%a.nav-link.cursor-pointer.ps-2.pe-2= "CV Suche"
%a.nav-link.cursor-pointer.ps-2.pe-2{href: cv_search_index_path} CV Suche
%li.bg-skills-blue.h-100.d-flex.align-items-center
%a.nav-link.cursor-pointer.ps-2.pe-2{href: skills_path} Skillset
%div.container-fluid
Expand Down
2 changes: 1 addition & 1 deletion app/views/people/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%div.mt-2
=render partial:"people/search", :locals => {person: @person}
%div{"data-controller": "profile-tab"}
%div{"data-controller": "profile-tab highlight"}
%ul.nav.nav-tabs.d-flex.flex-row.mt-2
%div.w-50.d-flex.flex-row
=link_to person_path(@person), class: "btn d-flex align-items-center justify-content-center text-primary p-0",
Expand Down
11 changes: 11 additions & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,14 @@ de:
till_today: Bis Heute
with_enddate: Mit Enddatum

cv_search:
advanced_trainings: Weiterbildungen
educations: Ausbildungen
activities: Stationen
projects: Projekte
name: Name
location: Wohnort
title: Abschluss
competence_notes: Kompetenzen
roles: Funktionen
department: Organisationseinheit
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

resources :people_skills

resources :cv_search

resources :people do
resources :advanced_trainings
resources :educations
Expand Down
64 changes: 64 additions & 0 deletions spec/features/cv_search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require 'rails_helper'


describe 'Advanced Trainings', type: :feature, js:true do
let(:person) { people(:bob) }

before(:each) do
sign_in auth_users(:admin)
visit("/cv_search")
end

describe 'Search' do
it 'should find correct results' do
fill_in 'cv_search_field', with: person.name
check_search_results(I18n.t("cv_search.name"))
fill_in 'cv_search_field', with: person.projects.first.technology
check_search_results(I18n.t("cv_search.projects"))
fill_in 'cv_search_field', with: person.title
check_search_results(I18n.t("cv_search.title"))
fill_in 'cv_search_field', with: person.roles.first.name
check_search_results(I18n.t("cv_search.roles"))
fill_in 'cv_search_field', with: person.department.name
check_search_results(I18n.t("cv_search.department"))
fill_in 'cv_search_field', with: person.competence_notes.split.first
check_search_results(I18n.t("cv_search.competence_notes"))
fill_in 'cv_search_field', with: person.advanced_trainings.first.description
check_search_results(I18n.t("cv_search.advanced_trainings"))
fill_in 'cv_search_field', with: person.educations.first.location
check_search_results(I18n.t("cv_search.educations"))
fill_in 'cv_search_field', with: person.activities.first.description
check_search_results(I18n.t("cv_search.activities"))
fill_in 'cv_search_field', with: person.projects.first.description
check_search_results(I18n.t("cv_search.projects"))
end

it 'should open person when clicking result' do
fill_in 'cv_search_field', with: person.projects.first.technology
check_search_results(I18n.t("cv_search.projects"))
click_link(person.name)
expect(page).to have_current_path(person_path(person))

visit("/cv_search")
education_location = person.educations.first.location
fill_in 'cv_search_field', with: education_location
check_search_results(I18n.t("cv_search.educations"))
click_link(I18n.t("cv_search.educations"))
expect(page).to have_current_path("#{person_path(person)}?q=#{education_location}")
end

it 'should only display results when length of search-text is > 3' do
fill_in 'cv_search_field', with: person.name.slice(0, 2)
expect(page).not_to have_content(person.name)
fill_in 'cv_search_field', with: person.name.slice(0, 3)
expect(page).to have_content(person.name)
end
end
end

def check_search_results(field_name)
within('turbo-frame#search-results') {
expect(page).to have_content(person.name)
expect(page).to have_content(field_name)
}
end

0 comments on commit a695968

Please sign in to comment.