diff --git a/app/assets/images/language-levels/a1.svg b/app/assets/images/language-levels/a1.svg
new file mode 100644
index 000000000..c151d5b83
--- /dev/null
+++ b/app/assets/images/language-levels/a1.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/a2.svg b/app/assets/images/language-levels/a2.svg
new file mode 100644
index 000000000..d97fafd33
--- /dev/null
+++ b/app/assets/images/language-levels/a2.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/b1.svg b/app/assets/images/language-levels/b1.svg
new file mode 100644
index 000000000..312fb0cfb
--- /dev/null
+++ b/app/assets/images/language-levels/b1.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/b2.svg b/app/assets/images/language-levels/b2.svg
new file mode 100644
index 000000000..0a7a87f34
--- /dev/null
+++ b/app/assets/images/language-levels/b2.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/c1.svg b/app/assets/images/language-levels/c1.svg
new file mode 100644
index 000000000..aa38db56e
--- /dev/null
+++ b/app/assets/images/language-levels/c1.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/c2.svg b/app/assets/images/language-levels/c2.svg
new file mode 100644
index 000000000..54650360b
--- /dev/null
+++ b/app/assets/images/language-levels/c2.svg
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/icon_certificate.svg b/app/assets/images/language-levels/icon_certificate.svg
new file mode 100644
index 000000000..b5025625c
--- /dev/null
+++ b/app/assets/images/language-levels/icon_certificate.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/keine.svg b/app/assets/images/language-levels/keine.svg
new file mode 100644
index 000000000..8f5c70785
--- /dev/null
+++ b/app/assets/images/language-levels/keine.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/app/assets/images/language-levels/muttersprache.svg b/app/assets/images/language-levels/muttersprache.svg
new file mode 100644
index 000000000..a9460a04d
--- /dev/null
+++ b/app/assets/images/language-levels/muttersprache.svg
@@ -0,0 +1,21 @@
+
+
\ No newline at end of file
diff --git a/app/assets/stylesheets/styles.scss b/app/assets/stylesheets/styles.scss
index 815cc64df..d704d1438 100644
--- a/app/assets/stylesheets/styles.scss
+++ b/app/assets/stylesheets/styles.scss
@@ -109,6 +109,9 @@ pzsh-topbar {
background-color: #69b978
}
+.w-min-content {
+ width: min-content;
+}
.rate {
float: left;
diff --git a/app/controllers/concerns/people_controller_concerns.rb b/app/controllers/concerns/people_controller_concerns.rb
new file mode 100644
index 000000000..bb6fbafcc
--- /dev/null
+++ b/app/controllers/concerns/people_controller_concerns.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module PeopleControllerConcerns
+ private
+
+ def set_nationality2
+ if params.include?(:has_nationality2) && false?(params[:has_nationality2][:checked])
+ params[:person][:nationality2] = nil
+ end
+ end
+end
diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb
index 142c273d7..d4638fd87 100644
--- a/app/controllers/people_controller.rb
+++ b/app/controllers/people_controller.rb
@@ -3,12 +3,15 @@
class PeopleController < CrudController
include ExportController
include ParamConverters
+ include PeopleControllerConcerns
self.permitted_attrs = [:birthdate, :location, :marital_status, :updated_by, :name, :nationality,
:nationality2, :title, :competence_notes, :company_id, :email,
:department_id, :shortname, :picture, :picture_cache,
- { person_roles_attributes: [:role_id, :person_role_level_id,
- :percent, :id, :_destroy] }]
+ { person_roles_attributes:
+ [:role_id, :person_role_level_id, :percent, :id, :_destroy] },
+ { language_skills_attributes:
+ [:language, :level, :certificate, :id, :_destroy] }]
def show
return export if format_odt?
@@ -19,7 +22,7 @@ def show
end
def update
- params[:person][:nationality2] = nil if false?(params[:has_nationality2]&.[](:checked))
+ set_nationality2
super
end
diff --git a/app/helpers/role_form_helper.rb b/app/helpers/dynamic_form_helper.rb
similarity index 82%
rename from app/helpers/role_form_helper.rb
rename to app/helpers/dynamic_form_helper.rb
index 1b06d48b2..a78bb7d79 100644
--- a/app/helpers/role_form_helper.rb
+++ b/app/helpers/dynamic_form_helper.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-module RoleFormHelper
+module DynamicFormHelper
# This method creates a link with `data-id` `data-fields` attributes. These attributes are used
# to create new instances of the nested fields through Javascript.
- def link_to_add_role(name, form, association)
+ def link_to_add_field(name, form, association)
# Takes an object and creates a new instance of its associated model
new_role = form.object.send(association).klass.new
# Saves the unique ID of the object into a variable.
@@ -13,7 +13,7 @@ def link_to_add_role(name, form, association)
# child_index` is used to ensure the key of the associated array is unique, and that it matched
# the value in the `data-id` attribute.
fields = form.fields_for(association, new_role, child_index: id) do |builder|
- render("#{association.to_s.singularize}_fields", person_role: builder)
+ render("#{association.to_s.singularize}_fields", f: builder)
end
@@ -23,7 +23,8 @@ def link_to_add_role(name, form, association)
# We use `gsub("\n", "")` to remove anywhite space from the rendered partial.
# The `id:` value needs to match the value used in `child_index: id`.
link_to(name, '#',
- { class: 'add_fields', 'data-action' => 'person-roles#addField',
+ { class: 'add_fields', 'data-action' =>
+ 'dynamic-fields#addField lang-selection#setNewLangOption',
data: { id: id, fields: fields.gsub("\n", '') } })
end
end
diff --git a/app/helpers/person_helper.rb b/app/helpers/person_helper.rb
index 9b38823ad..fe8a3e6a9 100644
--- a/app/helpers/person_helper.rb
+++ b/app/helpers/person_helper.rb
@@ -37,4 +37,27 @@ def group_person_skills_by_category(person)
PeopleSkill.core_competence.where(person_id: person.id)
.group_by { |ps| ps.skill.category.parent }
end
+
+ def common_languages_translated
+ I18nData.languages('DE').collect do |language|
+ if LanguageList::LanguageInfo.find(language[0])&.common?
+ [language.first, "#{language.last} (#{language.first})"]
+ end
+ end.compact.sort_by(&:last)
+ end
+
+ def sort_languages(languages)
+ mandatory_langs, optional_langs = languages.partition do |language|
+ uneditable_language?(language.language)
+ end
+ mandatory_langs.sort_by(&:language) + optional_langs.sort_by(&:language)
+ end
+
+ def uneditable_language?(lang)
+ %w[DE EN FR].include?(lang)
+ end
+
+ def language_skill_levels
+ %w[Keine A1 A2 B1 B2 C1 C2 Muttersprache]
+ end
end
diff --git a/app/javascript/controllers/person_roles_controller.js b/app/javascript/controllers/dynamic_fields_controller.js
similarity index 100%
rename from app/javascript/controllers/person_roles_controller.js
rename to app/javascript/controllers/dynamic_fields_controller.js
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index 3b51ebc59..d08858d9b 100644
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -7,15 +7,18 @@ import { application } from "./application"
import DropdownController from "./dropdown_controller"
application.register("dropdown", DropdownController)
+import DynamicFieldsController from "./dynamic_fields_controller"
+application.register("dynamic-fields", DynamicFieldsController)
+
import ImageUploadController from "./image_upload_controller"
application.register("image-upload", ImageUploadController)
+import LangSelectionController from "./lang_selection_controller"
+application.register("lang-selection", LangSelectionController)
+
import NationalityTwoController from "./nationality_two_controller"
application.register("nationality-two", NationalityTwoController)
-import PersonRolesController from "./person_roles_controller"
-application.register("person-roles", PersonRolesController)
-
import RemoteModalController from "./remote_modal_controller"
application.register("remote-modal", RemoteModalController)
diff --git a/app/javascript/controllers/lang_selection_controller.js b/app/javascript/controllers/lang_selection_controller.js
new file mode 100644
index 000000000..2432c2a24
--- /dev/null
+++ b/app/javascript/controllers/lang_selection_controller.js
@@ -0,0 +1,42 @@
+import { Controller } from "@hotwired/stimulus"
+
+// Connects to data-controller="lang-selection"
+export default class extends Controller {
+ connect() {
+ this.setOptionState();
+ }
+ setOptionState() {
+ const languageSelects= document.getElementsByClassName("language-select");
+ const selectedLanguages = getSelectedLanguages();
+ for(const languageSelect of languageSelects) {
+ for(const option of languageSelect.options) {
+ //Deactivate option if it is not the current option of the dropdown but is selected in another dropdown
+ option.disabled = (selectedLanguages.includes(option.value)) && (languageSelect.selectedOptions[0].value !== option.value);
+ }
+ }
+ }
+
+ setNewLangOption() {
+ const selectedLanguages = getSelectedLanguages();
+ const language_selects = Array.from(document.getElementsByClassName("language-select"));
+ const language_select = language_selects[language_selects.length - 1]
+ //Remove newly added language since we dont want to skip that
+ selectedLanguages.pop();
+ while(selectedLanguages.includes(language_select.selectedOptions[0].value)) {
+ language_select.selectedIndex++;
+ }
+ this.setOptionState();
+ }
+}
+
+function getSelectedLanguages() {
+ let selectedLanguages = [];
+
+ const languageSelects= document.getElementsByClassName("language-select");
+ for(const languageSelect of languageSelects) {
+ if(!["1", "true"].includes(languageSelect.closest(".nested-fields").querySelector('input[type="hidden"]').value)) {
+ selectedLanguages.push(languageSelect.selectedOptions[0].value)
+ }
+ }
+ return selectedLanguages;
+}
\ No newline at end of file
diff --git a/app/models/person.rb b/app/models/person.rb
index 410db5c80..65eb5dac8 100644
--- a/app/models/person.rb
+++ b/app/models/person.rb
@@ -38,6 +38,7 @@ class Person < ApplicationRecord
has_many :expertise_topic_skill_values, dependent: :destroy
has_many :expertise_topics, through: :expertise_topic_skill_values
has_many :language_skills, dependent: :delete_all
+ accepts_nested_attributes_for :language_skills, allow_destroy: true
has_many :person_roles, dependent: :destroy
accepts_nested_attributes_for :person_roles, allow_destroy: true
has_many :people_skills, dependent: :destroy
diff --git a/app/views/people/_form.html.haml b/app/views/people/_form.html.haml
index e3ede064e..628ffa2a6 100644
--- a/app/views/people/_form.html.haml
+++ b/app/views/people/_form.html.haml
@@ -10,25 +10,25 @@
%div.visually-hidden{"data-controller"=>"image-upload"}= form.file_field :picture, { accept: "image/", "data-action" => "image-upload#changeImage", id: "avatar-uploader" }
= form.hidden_field :picture_cache
%div.pe-5.col-xl-3.col-12
- %table
+ %table.w-100
%tbody
%th.fw-normal Name
%tr
%td= form.text_field :name, class: "mw-100 form-control"
%th.fw-normal Email
%tr
- %td= form.text_field :email, class: "mw-100, form-control"
+ %td= form.text_field :email, class: "mw-100 form-control"
%th.fw-normal Abschluss
%tr
- %td= form.text_field :title, class: "mw-100, form-control"
+ %td= form.text_field :title, class: "mw-100 form-control"
%th.fw-normal Funktionen
%div
= form.fields_for :person_roles do |person_role|
%tr
- %td= render "person_role_fields", person_role: person_role
+ %td= render "person_role_fields", f: person_role
%tr
- %td{"data-controller"=>"person-roles"}
- = link_to_add_role "Neue Funktion", form, :person_roles
+ %td{"data-controller"=>"dynamic-fields"}
+ = link_to_add_field "Neue Funktion", form, :person_roles
%th.fw-normal Organisationseinheit
%tr
%td= form.collection_select :department_id, Department.order(:name), :id, :name, {}, class: "form-select mw-100"
@@ -40,7 +40,7 @@
%td= form.text_field :location, class: "form-control mw-100"
%div.pe-5.col-xl-3.col-12
- %table
+ %table.w-100
%tbody
%th.fw-normal Geburtsdatum
%tr
@@ -60,11 +60,14 @@
%th.fw-normal Kürzel
%tr
%td= form.text_field :shortname, class: "mw-100 form-control"
- %div.col-xl-3.col-12.mw-100
+ %div.col-xl-3.col-12{"data-controller"=>"lang-selection"}
%div.fw-normal Sprachen
- %div.border.border-dark-subtle.mt-1.p-2.rounded
- - @person.language_skills.each do |language|
- %div.mb-1= "#{language.language}: #{language.level} - #{language.certificate}"
+ %div.border.border-dark-subtle.mt-1.p-2.rounded.w-100
+ = form.fields_for :language_skills, sort_languages(@person.language_skills) do |language_skill|
+ = render "language_skill_fields", f: language_skill
+ %div{"data-controller"=>"dynamic-fields"}
+ = link_to_add_field "Add Language", form, :language_skills
+
%div.mt-3
= form.submit :Speichern, { class: "btn btn-primary me-3 bg-skills-blue", id: "save-button" }
= link_to "Abbrechen", person_path, { id: "cancel-button" }
\ No newline at end of file
diff --git a/app/views/people/_language_skill_fields.html.haml b/app/views/people/_language_skill_fields.html.haml
new file mode 100644
index 000000000..b0a5205cb
--- /dev/null
+++ b/app/views/people/_language_skill_fields.html.haml
@@ -0,0 +1,12 @@
+%div.mb-3.pb-3.border-bottom.border-black.nested-fields
+ = f.hidden_field :_destroy
+ %div= f.collection_select :language, common_languages_translated, :first, :last, {}, { class: "form-select mw-100 language-select", disabled: uneditable_language?(f.object.language), "data-action" => "lang-selection#setOptionState" }
+ %div.d-flex
+ %div.w-25.me-2
+ %div Level
+ %div= f.collection_select :level, language_skill_levels, :itself, :itself, {}, class: "form-select mw-100 language-level-select"
+ %div.w-75
+ %div Zertifikat
+ %div= f.text_field :certificate, class: "mw-100 form-control language-certificate-input"
+ - unless uneditable_language?(f.object.language)
+ %div{"data-controller"=>"dynamic-fields"}= link_to "Remove", "#", { class: "remove_fields", 'data-action' => 'dynamic-fields#removeField lang-selection#setOptionState' }
\ No newline at end of file
diff --git a/app/views/people/_person_role_fields.html.haml b/app/views/people/_person_role_fields.html.haml
index 9b4b24cca..149bc546d 100644
--- a/app/views/people/_person_role_fields.html.haml
+++ b/app/views/people/_person_role_fields.html.haml
@@ -1,10 +1,10 @@
%div.border.border-dark-subtle.rounded.p-1.fw-light.nested-fields
- = person_role.hidden_field :_destroy
+ = f.hidden_field :_destroy
Rolle
- = person_role.collection_select :role_id, Role.order(:name), :id, :name, {}, class: "form-select w-100 role-select"
+ = f.collection_select :role_id, Role.order(:name), :id, :name, {}, class: "form-select w-100 role-select"
%div
Stufe
%div.d-flex.fw-light
- = person_role.collection_select :person_role_level_id, PersonRoleLevel.order(:level), :id, :level, {}, class: "form-select w-50 me-1 role-level-select"
- = person_role.number_field :percent, in: 0..200, step: 1, class: "form-control w-50 person-role-percent"
- %div{"data-controller"=>"person-roles"}= link_to "Remove", "#", { class: "remove_fields", 'data-action' => 'person-roles#removeField' }
\ No newline at end of file
+ = f.collection_select :person_role_level_id, PersonRoleLevel.order(:level), :id, :level, {}, class: "form-select w-50 me-1 role-level-select"
+ = f.number_field :percent, in: 0..200, step: 1, class: "form-control w-50 person-role-percent"
+ %div{"data-controller"=>"dynamic-fields"}= link_to "Remove", "#", { class: "remove_fields", 'data-action' => 'dynamic-fields#removeField' }
\ No newline at end of file
diff --git a/app/views/people/_profile.html.haml b/app/views/people/_profile.html.haml
index 8b765db15..9d1b99fae 100644
--- a/app/views/people/_profile.html.haml
+++ b/app/views/people/_profile.html.haml
@@ -54,7 +54,13 @@
%div.col-xl-3.col-12
%div.fw-normal.text-gray Sprachen
- %div.border.border-dark-subtle.mt-1.p-2.rounded
- - @person.language_skills.each do |language|
- %div.mb-1= "#{language.language}: #{language.level} - #{language.certificate}"
+ %div.border.border-dark-subtle.mt-1.p-2.rounded.w-min-content
+ %table
+ %tbody
+ - sort_languages(@person.language_skills).each do |language|
+ %tr
+ %td.p-2.pe-3.text-gray= language.language
+ %td.p-2.pe-3= image_tag("language-levels/#{language.level.downcase}.svg", alt: "Language level indicator")
+ - unless language.certificate.blank?
+ %td.p-2= image_tag("language-levels/icon_certificate.svg", alt: "Language certificate icon", title: language.certificate)
= link_to "Show all", people_path, {"data-turbo"=>false}
\ No newline at end of file
diff --git a/spec/exporters/odt/cv_spec.rb b/spec/exporters/odt/cv_spec.rb
index 34d46d7d8..93a14b3a2 100644
--- a/spec/exporters/odt/cv_spec.rb
+++ b/spec/exporters/odt/cv_spec.rb
@@ -55,7 +55,7 @@
it 'formats competence notes' do
notes = Odt::Cv.new(people(:bob), {'anon' => 'false'}).send(:competence_notes_list)[:competence]
- expect(notes).to eq('Java\n Ruby')
+ expect(notes).to eq("Java\nRuby")
end
end
diff --git a/spec/features/core_competences_spec.rb b/spec/features/core_competences_spec.rb
index 6ce6fa90c..a094c6a63 100644
--- a/spec/features/core_competences_spec.rb
+++ b/spec/features/core_competences_spec.rb
@@ -15,7 +15,7 @@
it 'should display competence notes and edit link correctly' do
visit person_path(people(:alice))
- expect(page).to have_text('LaTex\n Puppet\n Bash')
+ expect(page).to have_text("LaTex Puppet Bash", normalize_ws: true)
expect(page).to have_selector('#edit-link')
end
@@ -36,12 +36,13 @@
fill_in 'person_competence_notes', with: 'Hello World here'
page.find('#cancel').click
- expect(page).to have_text('LaTex\n Puppet\n Bash')
+ expect(page).to have_text("LaTex Puppet Bash", normalize_ws: true)
end
it 'should display skill with same parent category in same row with divider' do
visit person_path(people(:alice))
expect(page).to have_selector('.circle-divider')
- expect(page).to have_selector('.core-competence', count: 1, text: "Software-Engineering\nRails\nember")
+ expect(page).to have_selector('.core-competence', count: 1,
+ text: "Software-Engineering Rails ember", normalize_ws: true)
end
end
diff --git a/spec/features/people_spec.rb b/spec/features/people_spec.rb
index 23292e025..10397f687 100644
--- a/spec/features/people_spec.rb
+++ b/spec/features/people_spec.rb
@@ -61,6 +61,21 @@ def fill_out_person_form
select ISO3166::Country["US"].translations[I18n.locale], from: 'person_nationality2'
select I18n.t('marital_statuses.married'), from: 'person_marital_status'
fill_in 'person_shortname', with: 'bb'
+
+ page.all(".add_fields").last.click
+ language_select = page.all('.language-select').last
+ language_level_select = page.all('.language-level-select').last
+ language_certificate_input = page.all('.language-certificate-input').last
+ select 'FI', from: language_select[:id]
+ select 'B2', from: language_level_select[:id]
+ fill_in language_certificate_input[:id], with: 'Some Certificate'
+ end
+
+ def add_language(language)
+ #Create new language.
+ page.all(".add_fields").last.click
+ #Select language from dropdown in newly created language.
+ select language, from: page.all('.language-select').last[:id]
end
describe 'Edit person', type: :feature, js: true do
@@ -102,6 +117,20 @@ def fill_out_person_form
bob.nationality2.nil? ? (expect(page).not_to have_select('person_nationality2')) : (expect(page).to have_select('person_nationality2', selected: ISO3166::Country[bob.nationality2].translations[I18n.locale]))
expect(page).to have_select('person_marital_status', selected: I18n.t("marital_statuses.#{bob.marital_status}"))
expect(page).to have_field('person_shortname', with: bob.shortname)
+
+ language_skills = bob.language_skills
+ language_selects = page.all('.language-select')
+ language_level_selects = page.all('.language-level-select')
+ language_certificate_inputs = page.all('.language-certificate-input')
+ language_selects.each_with_index do |language_select, i|
+ expect(language_select.value).to eql(language_skills[i].language)
+ end
+ language_level_selects.each_with_index do |language_level_select, i|
+ expect(language_level_select.value).to eql(language_skills[i].level)
+ end
+ language_certificate_inputs.each_with_index do |language_certificate_input, i|
+ expect(language_certificate_input.value).to eql(language_skills[i].certificate)
+ end
end
it 'should edit and save changes' do
@@ -130,6 +159,10 @@ def fill_out_person_form
expect(edited_person.nationality2).to eql('US')
expect(edited_person.marital_status).to eql('married')
expect(edited_person.shortname).to eql('bb')
+ edited_language_skill = edited_person.language_skills.last
+ expect(edited_language_skill.language).to eql('FI')
+ expect(edited_language_skill.level).to eql('B2')
+ expect(edited_language_skill.certificate).to eql('Some Certificate')
end
it 'should edit and cancel without saving' do
@@ -140,5 +173,43 @@ def fill_out_person_form
page.find('#cancel-button').click
expect(person.attributes).to eql(Person.first.attributes)
end
+
+ it('should correctly disable languages if they are selected, changed, created or deleted') {
+ bob = people(:bob)
+ visit person_path(bob)
+ page.find('#edit-button').click
+
+ add_language('JA')
+ add_language('ZH')
+
+ lang_selects = page.all('.language-select')
+ #ZH
+ lang_select = lang_selects[-1]
+ #JA
+ lang_select2 = lang_selects[-2]
+
+ #Check if currently selected language is still enabled
+ expect(lang_select.find('option', text: 'ZH')).not_to be_disabled
+ #Check if some other language is enabled
+ expect(lang_select.find('option', text: 'UR')).not_to be_disabled
+ #Check if language selected in another dropdown is disabled
+ expect(lang_select.find('option', text: 'JA')).to be_disabled
+
+ expect(lang_select2.find('option', text: 'JA')).not_to be_disabled
+ expect(lang_select.find('option', text: 'UR')).not_to be_disabled
+ expect(lang_select2.find('option', text: 'ZH')).to be_disabled
+
+ #Change language selected in dropdown
+ select 'KO', from: lang_select[:id]
+ #Old language selected in dropdown should not be disabled anymore
+ expect(lang_select2.find('option', text: 'ZH')).not_to be_disabled
+ #New language selected should be disabled
+ expect(lang_select2.find('option', text: 'KO')).to be_disabled
+
+ #Delete language
+ page.all('.remove_fields')[-1].click
+ #Language should now be re-enabled
+ expect(lang_select2.find('option', text: 'KO')).not_to be_disabled
+ }
end
end
diff --git a/spec/fixtures/people.yml b/spec/fixtures/people.yml
index ecbdf317c..dff9eb518 100644
--- a/spec/fixtures/people.yml
+++ b/spec/fixtures/people.yml
@@ -33,7 +33,9 @@ bob:
nationality2: SE
roles: [software-engineer]
title: BSc in Cleaning
- competence_notes: Java\n Ruby
+ competence_notes: |
+ Java
+ Ruby
company: firma
email: bob@example.com
department: sys
@@ -47,7 +49,10 @@ alice:
nationality: AU
roles: [system-engineer]
title: MSc in writing
- competence_notes: LaTex\n Puppet\n Bash
+ competence_notes: |
+ LaTex
+ Puppet
+ Bash
company: partner
email: alice@example.com
department: sys
@@ -61,7 +66,10 @@ ken:
nationality: AU
roles: [system-engineer]
title: MA in sending silly memes
- competence_notes: LaTex\n Puppet\n Bash
+ competence_notes: |
+ LaTex
+ Puppet
+ Bash
company: partner
email: kenthemaster@testi.com
department: ux
@@ -74,7 +82,9 @@ charlie:
roles: [system-engineer]
company: partner
title: MSc in Networking
- competence_notes: C\n Bash
+ competence_notes: |
+ C
+ Bash
email: charlie@example.com
department: sys
wally:
@@ -86,7 +96,13 @@ wally:
roles: [software-engineer]
company: partner
title: Full-Stack Developer
- competence_notes: C\n Bash\n Java\n Ruby\n LaTex\n Puppet
+ competence_notes: |
+ C
+ Bash
+ Java
+ Ruby
+ LaTex
+ Puppet
email: wally@example.com
department: sys
hope: