From 4084ad2d3bb48971650dbdeff3871869d65e8d29 Mon Sep 17 00:00:00 2001 From: actions-bot Date: Sun, 7 Dec 2025 12:07:32 +0000 Subject: [PATCH 1/3] Updated node modules based on npm audit fix --- package-lock.json | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd0683b09..06cb181ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3131,9 +3131,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001757", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", - "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", "funding": [ { "type": "opencollective", @@ -4992,14 +4992,14 @@ } }, "node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "license": "ISC", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "license": "BlueOak-1.0.0", "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -5026,10 +5026,10 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "license": "ISC", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/brace-expansion": "^5.0.0" }, @@ -5210,9 +5210,9 @@ "license": "MIT" }, "node_modules/hds-core": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/hds-core/-/hds-core-4.8.0.tgz", - "integrity": "sha512-Bdbo0SiUwLC4D1pgZtr1puORZR2h5Y6TstGE7QJ2xHWbZFn/UwTL4q2u4fGY6JH117y4hbzsJ1SWlLaSJlTMfA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/hds-core/-/hds-core-4.8.1.tgz", + "integrity": "sha512-7szkf/T6oWaaT4FIdl5KMrln+gScUjsccCQJaRxAHyZlxK7y1UUKSX9g9/vyj/euvrRTNb/Y8Dn7zJPmoCxaug==", "license": "MIT", "engines": { "node": "^22.13.1" @@ -5225,9 +5225,9 @@ "license": "MIT" }, "node_modules/hds-react": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/hds-react/-/hds-react-4.8.0.tgz", - "integrity": "sha512-zYFlOCpKYMF+jOQz39Fl4iwTaRi6yVh1OKh605OnFcfdv3jzYPF7MBgoO9Joiv6mJeVFkrheX02fzcQZgyG/fQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/hds-react/-/hds-react-4.8.1.tgz", + "integrity": "sha512-Er7ZLMsdsmY/GEPPMvz5k5c1dxXfoydcQaoUHZdiSX2cpocTr6j59WLs/4KpGweFwkTUI/G2AVyym6ye3OsLdQ==", "license": "MIT", "dependencies": { "@apollo/client": "^3.10.1", @@ -5246,7 +5246,7 @@ "date-fns": "2.16.1", "downshift": "6.0.6", "graphql": "^16.8.1", - "hds-core": "4.8.0", + "hds-core": "4.8.1", "jwt-decode": "^3.1.2", "kashe": "1.0.4", "lodash": "^4.17.21", @@ -5810,9 +5810,10 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, From c058db98ad5739792bc0bc636c91778ef34399cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kalij=C3=A4rvi?= Date: Thu, 11 Dec 2025 13:25:40 +0200 Subject: [PATCH 2/3] Added dist. --- dist/js/job-search.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/js/job-search.min.js b/dist/js/job-search.min.js index eba74cac5..809396277 100644 --- a/dist/js/job-search.min.js +++ b/dist/js/job-search.min.js @@ -86,4 +86,4 @@ ${JSON.stringify(wL)} ${JSON.stringify(o)} ${u} ${e} -`},"usePromotedQuery"),o9=Dte;var Mte=i(e=>{let{size:t,sortOptions:r}=yn,{promoted:n}=Ke(Fo),o=Number.isNaN(Number(e.page))?1:Number(e.page),s=[{bool:{must_not:{term:{[Me.PROMOTED]:!0}}}}],u=[];if(e.keyword&&e.keyword.length>0&&s.push({bool:{should:[{match_phrase_prefix:{[Me.RECRUITMENT_ID]:e.keyword.toString()}},{combined_fields:{query:e.keyword.toString().toLowerCase(),fields:[`${Me.TITLE}^2`,`${Me.ORGANIZATION}^1.5`,Me.ORGANIZATION_NAME,Me.EMPLOYMENT]}},{wildcard:{[`${Me.TITLE}.keyword`]:`*${e.keyword.toString().toLowerCase()}*`}},{wildcard:{[Me.TITLE]:`*${e.keyword.toString().toLowerCase()}*`}}]}}),e?.task_areas?.length){let E=Array.isArray(e.task_areas)?e.task_areas:[e.task_areas];s.push({terms:{[Me.TASK_AREA_EXTERNAL_ID]:E}})}e?.employment?.length&&s.push({bool:{should:[{terms:{[Me.EMPLOYMENT_ID]:e.employment}},{terms:{[Me.EMPLOYMENT_TYPE_ID]:e.employment}}],minimum_should_match:1}}),e.continuous&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.CONTINUOUS}}),e.internship&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.TRAINING}}),e.summer_jobs&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.SUMMER_JOBS}}),e.youth_summer_jobs&&(u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.YOUTH_SUMMER_JOBS}}),u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.COOL_SUMMER_PROJECT}}));let c={bool:{filter:[hp]}};if(e.language&&c.bool.filter.push({term:{[Me.LANGUAGE]:e.language.toString()}}),e?.area_filter){let E=Array.isArray(e.area_filter)?e.area_filter:[e.area_filter],y=[];E.forEach(_=>{y.push(...i_.find(b=>b.key===_)?.postalCodes||[])}),y.length&&c.bool.filter.push({terms:{[Me.POSTAL_CODE]:y}})}Object.keys(s).length&&(c.bool.must=s),u.length&&(c.bool.should=u,c.bool.minimum_should_match=1);let f={[Me.UNPUBLISH_ON]:{order:"asc"}},p={[Me.PUBLICATION_STARTS]:{order:"desc"}},m=i(()=>e?.sort===r.closing?f:(e?.sort===r.newestFirst,p),"getSort")(),v=i(()=>{if(!n.length)return[t,t*(o-1)];let E=t*(o-1)=t)return[0,0];if(!_){let T=Math.ceil(n.length/t),C=o-1-T;return[t,t*C+(t-b)]}return[t-b,0]},"getSizeFrom"),[x,S]=v();return JSON.stringify({aggs:{[Me.NUMBER_OF_JOBS]:{sum:{field:Me.NUMBER_OF_JOBS,missing:1}},total_count:{cardinality:{field:`${Me.RECRUITMENT_ID}.keyword`}}},collapse:{field:`${Me.RECRUITMENT_ID}.keyword`,inner_hits:{name:"translations",size:3}},from:S,query:c,sort:[m,"_score"],size:x})},"useQueryString"),J_=Mte;var Bte=i(e=>{let[t,r]=e.responses,n=Number(t.aggregations?.total_count?.value),o=Number(r.aggregations?.total_count?.value),s=(Number.isNaN(n)?0:n)+(Number.isNaN(o)?0:o);if(s<=0)return{results:null,jobs:null,total:s};let u=t.aggregations?.[Me.NUMBER_OF_JOBS]?.value,c=r.aggregations?.[Me.NUMBER_OF_JOBS]?.value,f=(Number.isNaN(u)?0:u)+(Number.isNaN(c)?0:c);return{results:[...t.hits.hits,...r.hits.hits],jobs:f,total:s}},"handlePromotedResults"),Fte=i(e=>{if(!e?.hits?.hits.length)return{results:null,jobs:null,total:0};let t=e.hits.hits,r=e.aggregations.total_count.value||e.hits.total.value,n=e?.aggregations?.[Me.NUMBER_OF_JOBS]?.value;return{results:t,jobs:n,total:r}},"handleSimpleResults"),Ute=i(e=>{let{promoted:t}=Ke(Fo),r=J_(e),n=o9(r,e);return{promoted:!!t,query:t?n:r,handleResults:t?Bte:Fte}},"useResultsQuery"),i9=Ute;var S9=H(w9());var X_=H(ue());var Lt=H(Se()),gre=lt(!1),_re=i(()=>{let e=Ke(yr),t=J_(e),[r,n]=Rr(bre),[o,s]=Rr(vre),[u,c]=Rr(c_),[f,p]=Rr(xre),[h,m]=Rr(yre),[v,x]=Rr(gre),S=S9.Buffer.from(t).toString("base64"),E="-",y=window.location.pathname,_=window.location.search,b=y+_,T=(0,X_.createRef)(),C={elastic_query:S,query:b,email:o,search_description:E,lang:window.drupalSettings.path.currentLanguage||"fi"},L=i(async He=>{if(He.preventDefault(),!r){p(Drupal.t("The choice is mandatory: Terms of service",{},{context:"Search monitor error terms"}));return}if(!o){p(Drupal.t("This field is mandatory: Email address",{},{context:"Search monitor error email"}));return}if(!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(o)){p(Drupal.t("The email address you entered is not in the right format.",{},{context:"Search monitor error email"}));return}let Qe=document.getElementById("job-search-form__search-monitor__submit-button");Qe&&Qe.setAttribute("disabled","true");let Nt="";try{let Wt=await fetch("/session/token",{method:"GET"});if(!Wt.ok){p(`Error getting session token: ${Wt.statusText}`),Qe&&Qe.removeAttribute("disabled");return}Nt=await Wt.text()}catch(Wt){p(`Error getting session token: ${Wt}`),Qe&&Qe.removeAttribute("disabled");return}let Je=JSON.stringify(C),{host:dr,pathname:tt}=window.location,Jr=`${tt.split("/").slice(0,-1).join("/")}/hakuvahti/subscribe`;dr.includes("docker.so")&&(Jr="/hakuvahti/subscribe");let qn=await fetch(Jr,{method:"POST",headers:{"Content-Type":"application/json",token:Nt},body:Je});if(!qn.ok){console.warn(qn.statusText),p(Drupal.t("Saving search failed. Please try again.",{},{context:"Search monitor error submitting"})),Qe&&Qe.removeAttribute("disabled"),x(!0);return}c(!0),p(""),x(!0),Qe&&Qe.removeAttribute("disabled")},"onSubmit");p_(T,v),(0,X_.useEffect)(()=>{v&&x(!1)},[v,x]);let R=Drupal.t("Receive search results by email",{},{context:"Search monitor header"}),U=Drupal.t("Open the order form",{},{context:"Search monitor open label"}),A=Drupal.t("Close the order form",{},{context:"Search monitor close label"}),P=Drupal.t("Saved search",{},{context:"Search monitor content title"}),F=Drupal.t("To receive job alerts, carry out the search desired and then save your search. This will allow you to receive email notifications about any new matches.",{},{context:"Search monitor content"}),z=Drupal.t("You can save as many searches as you like. You can delete the saved search via the link in the email messages.",{},{context:"Search monitor content"}),J=Drupal.t("Email address",{},{context:"Search monitor email label"}),X=Drupal.t("Save your search",{},{context:"Search monitor submit button label"}),$=Drupal.t("Your search has been saved",{},{context:"Search monitor thank you header"}),K=Drupal.t("You will receive a confirmation link by email. You can activate the saved search via the link.",{},{context:"Search monitor thank you message"}),te=Drupal.t("Please check these selections",{},{context:"Search monitor error label"}),ae=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_checkbox_label,ce=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_text,pe=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_url,Ct=Drupal.t("The link opens in a new tab",{},{context:"Explanation for users that the link opens in a new tab instead of the expected current tab"});return(0,Lt.jsxs)("form",{onSubmit:L,className:"job-search-form__search-monitor",children:[!u&&(0,Lt.jsxs)(Lt.Fragment,{children:[(0,Lt.jsx)("h3",{className:"job-search-form__search-monitor__heading",children:R}),(0,Lt.jsx)(Oo,{"aria-controls":"job-search-form__search-monitor__content","aria-expanded":h,iconStart:h?(0,Lt.jsx)($2,{}):(0,Lt.jsx)(Kl,{}),onClick:He=>{He.preventDefault(),m(!h)},style:{"--border-color-focus":"var(--hdbt-color-black)","--background-color":"transparent","--background-color-hover":"trasparent","--outline-color-focus":"var(--hdbt-color-black)",marginTop:"var(--spacing-2-xs)"},theme:ec.Black,type:"button",variant:Ao.Supplementary,children:h?A:U}),(0,Lt.jsxs)("div",{id:"job-search-form__search-monitor__content",className:"job-search-form__search-monitor__content","aria-hidden":!h,children:[(0,Lt.jsx)("h4",{className:"job-search-form__search-monitor__content__heading",children:P}),(0,Lt.jsx)("p",{children:F}),(0,Lt.jsx)("p",{children:z}),f&&(0,Lt.jsx)(op,{className:"job-search-form__search-monitor__error",label:te,ref:T,size:Ki.Medium,type:"error",notificationAriaLabel:Drupal.t("Notification",{},{context:"Search monitor error message type for screen reader"}),children:f}),(0,Lt.jsx)(wu,{className:"job-search-form__search-monitor__email",id:"job-search-form__search_monitor__email",label:J,name:"job-search-form__search_monitor__email",onChange:He=>s(He.target.value),required:!0,style:{...t_,marginTop:"var(--spacing-m)"},type:"email",value:o}),(0,Lt.jsx)("p",{children:(0,Lt.jsxs)("a",{href:pe,target:"_blank",rel:"noreferrer",className:"job-search-form__search-monitor__terms-link",children:[ce," (",Ct,")"]})}),(0,Lt.jsx)(di,{checked:r,className:"job-search-form__search-monitor__terms",id:"job-search-form__search_monitor__terms",label:ae,name:"job-search-form__search_monitor__terms",onChange:He=>n(He.target.checked),required:!0,style:Au}),(0,Lt.jsx)(Oo,{className:"hdbt-search--react__submit-button job-search-form__search-monitor__submit-button",id:"job-search-form__search-monitor__submit-button",style:{marginBottom:"0",marginTop:"var(--spacing-l)"},type:"submit",children:X})]})]}),u&&(0,Lt.jsxs)(Lt.Fragment,{children:[(0,Lt.jsx)("h3",{className:"job-search-form__search-monitor__heading",ref:T,children:$}),(0,Lt.jsx)("p",{children:K})]})]})},"SearchMonitorContainer"),vre=lt(""),bre=lt(!1),yre=lt(!1),xre=lt(""),E9=_re;var Vt=H(Se()),wre=i(()=>{let{size:e}=yn,t=Ke(yr),r=Ke(IL),n=br(CL),{error:o}=Ke(Fo),s=(0,T9.createRef)(),{query:u,promoted:c,handleResults:f}=i9(t),{data:p,error:h,isLoading:m,isValidating:v}=n9({keepPreviousData:!0,query:u,multi:c}),S=!!(!!Object.keys(t).length&&!m&&!v);p_(s,S);let E=i((_,b)=>{_.preventDefault(),n(b.toString())},"updatePage"),y=i(()=>{if(m||v)return(0,Vt.jsx)(yc,{count:e});if(h||o||p?.error)return(0,Vt.jsx)(GL,{error:h||o||p.error,className:"react-search__results",ref:s});let{results:_,jobs:b,total:T}=f(p||{});if(T<=0)return(0,Vt.jsx)(VL,{wrapperClass:"hdbt-search--react__results--container",ref:s});let C=Math.ceil(T/e);return(0,Vt.jsxs)(Vt.Fragment,{children:[(0,Vt.jsx)(h_,{resultText:(0,Vt.jsx)(Vt.Fragment,{children:Drupal.formatPlural(b,"1 open position","@count open positions",{},{context:"Job search results statline"})}),optionalResultsText:(0,Vt.jsx)(Vt.Fragment,{children:Drupal.formatPlural(T,"1 job listing","@count job listings",{},{context:"Job search results statline"})}),actions:(0,Vt.jsx)(NP,{}),actionsClass:"hdbt-search--react__results--sort",ref:s}),(0,Vt.jsx)(RP,{hits:_}),C>1&&(0,Vt.jsx)($L,{currentPage:r,pages:5,totalPages:C,updatePage:E})]})},"getResults");return(0,Vt.jsxs)(Vt.Fragment,{children:[drupalSettings?.helfi_react_search?.hakuvahti_url_set&&(0,Vt.jsx)(E9,{}),(0,Vt.jsx)("div",{className:"job-search__results",children:(0,Vt.jsx)(JL,{loading:m||v,children:y()})})]})},"ResultsContainer"),k9=wre;var qu=H(Se()),Sre=i(()=>(0,qu.jsx)("div",{className:"recruitment-search",children:(0,qu.jsxs)(C9.Suspense,{fallback:(0,qu.jsx)(yc,{count:yn.size}),children:[(0,qu.jsx)(UL,{}),!drupalSettings?.helfi_rekry_job_search?.results_page_path&&(0,qu.jsx)(k9,{})]})}),"SearchContainer"),I9=Sre;var e3=H(Se());MA();var Ere="helfi-rekry-job-search",A9=document.getElementById(Ere);A9&&R9.default.render((0,e3.jsx)(O9.default.StrictMode,{children:(0,e3.jsx)(I9,{})}),A9);})(); +`},"usePromotedQuery"),o9=Dte;var Mte=i(e=>{let{size:t,sortOptions:r}=yn,{promoted:n}=Ke(Fo),o=Number.isNaN(Number(e.page))?1:Number(e.page),s=[{bool:{must_not:{term:{[Me.PROMOTED]:!0}}}}],u=[];e.keyword&&e.keyword.length>0&&s.push({bool:{should:[{match_phrase_prefix:{[Me.RECRUITMENT_ID]:e.keyword.toString()}},{combined_fields:{query:e.keyword.toString().toLowerCase(),fields:[`${Me.TITLE}^2`,`${Me.ORGANIZATION}^1.5`,Me.ORGANIZATION_NAME,Me.EMPLOYMENT]}},{wildcard:{[`${Me.TITLE}.keyword`]:`*${e.keyword.toString().toLowerCase()}*`}},{wildcard:{[Me.TITLE]:`*${e.keyword.toString().toLowerCase()}*`}}]}}),e?.task_areas?.length&&s.push({terms:{[Me.TASK_AREA_EXTERNAL_ID]:e.task_areas}}),e?.employment?.length&&s.push({bool:{should:[{terms:{[Me.EMPLOYMENT_ID]:e.employment}},{terms:{[Me.EMPLOYMENT_TYPE_ID]:e.employment}}],minimum_should_match:1}}),e.continuous&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.CONTINUOUS}}),e.internship&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.TRAINING}}),e.summer_jobs&&u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.SUMMER_JOBS}}),e.youth_summer_jobs&&(u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.YOUTH_SUMMER_JOBS}}),u.push({term:{[Me.EMPLOYMENT_SEARCH_ID]:mt.COOL_SUMMER_PROJECT}}));let c={bool:{filter:[hp]}};if(e.language&&c.bool.filter.push({term:{[Me.LANGUAGE]:e.language.toString()}}),e?.area_filter?.length){let E=[];e.area_filter.forEach(y=>{E.push(...i_.find(_=>_.key===y)?.postalCodes||[])}),c.bool.filter.push({terms:{[Me.POSTAL_CODE]:E}})}Object.keys(s).length&&(c.bool.must=s),u.length&&(c.bool.should=u,c.bool.minimum_should_match=1);let f={[Me.UNPUBLISH_ON]:{order:"asc"}},p={[Me.PUBLICATION_STARTS]:{order:"desc"}},m=i(()=>e?.sort===r.closing?f:(e?.sort===r.newestFirst,p),"getSort")(),v=i(()=>{if(!n.length)return[t,t*(o-1)];let E=t*(o-1)=t)return[0,0];if(!_){let T=Math.ceil(n.length/t),C=o-1-T;return[t,t*C+(t-b)]}return[t-b,0]},"getSizeFrom"),[x,S]=v();return JSON.stringify({aggs:{[Me.NUMBER_OF_JOBS]:{sum:{field:Me.NUMBER_OF_JOBS,missing:1}},total_count:{cardinality:{field:`${Me.RECRUITMENT_ID}.keyword`}}},collapse:{field:`${Me.RECRUITMENT_ID}.keyword`,inner_hits:{name:"translations",size:3}},from:S,query:c,sort:[m,"_score"],size:x})},"useQueryString"),J_=Mte;var Bte=i(e=>{let[t,r]=e.responses,n=Number(t.aggregations?.total_count?.value),o=Number(r.aggregations?.total_count?.value),s=(Number.isNaN(n)?0:n)+(Number.isNaN(o)?0:o);if(s<=0)return{results:null,jobs:null,total:s};let u=t.aggregations?.[Me.NUMBER_OF_JOBS]?.value,c=r.aggregations?.[Me.NUMBER_OF_JOBS]?.value,f=(Number.isNaN(u)?0:u)+(Number.isNaN(c)?0:c);return{results:[...t.hits.hits,...r.hits.hits],jobs:f,total:s}},"handlePromotedResults"),Fte=i(e=>{if(!e?.hits?.hits.length)return{results:null,jobs:null,total:0};let t=e.hits.hits,r=e.aggregations.total_count.value||e.hits.total.value,n=e?.aggregations?.[Me.NUMBER_OF_JOBS]?.value;return{results:t,jobs:n,total:r}},"handleSimpleResults"),Ute=i(e=>{let{promoted:t}=Ke(Fo),r=J_(e),n=o9(r,e);return{promoted:!!t,query:t?n:r,handleResults:t?Bte:Fte}},"useResultsQuery"),i9=Ute;var S9=H(w9());var X_=H(ue());var Lt=H(Se()),gre=lt(!1),_re=i(()=>{let e=Ke(yr),t=J_(e),[r,n]=Rr(bre),[o,s]=Rr(vre),[u,c]=Rr(c_),[f,p]=Rr(xre),[h,m]=Rr(yre),[v,x]=Rr(gre),S=S9.Buffer.from(t).toString("base64"),E="-",y=window.location.pathname,_=window.location.search,b=y+_,T=(0,X_.createRef)(),C={elastic_query:S,query:b,email:o,search_description:E,lang:window.drupalSettings.path.currentLanguage||"fi"},L=i(async He=>{if(He.preventDefault(),!r){p(Drupal.t("The choice is mandatory: Terms of service",{},{context:"Search monitor error terms"}));return}if(!o){p(Drupal.t("This field is mandatory: Email address",{},{context:"Search monitor error email"}));return}if(!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(o)){p(Drupal.t("The email address you entered is not in the right format.",{},{context:"Search monitor error email"}));return}let Qe=document.getElementById("job-search-form__search-monitor__submit-button");Qe&&Qe.setAttribute("disabled","true");let Nt="";try{let Wt=await fetch("/session/token",{method:"GET"});if(!Wt.ok){p(`Error getting session token: ${Wt.statusText}`),Qe&&Qe.removeAttribute("disabled");return}Nt=await Wt.text()}catch(Wt){p(`Error getting session token: ${Wt}`),Qe&&Qe.removeAttribute("disabled");return}let Je=JSON.stringify(C),{host:dr,pathname:tt}=window.location,Jr=`${tt.split("/").slice(0,-1).join("/")}/hakuvahti/subscribe`;dr.includes("docker.so")&&(Jr="/hakuvahti/subscribe");let qn=await fetch(Jr,{method:"POST",headers:{"Content-Type":"application/json",token:Nt},body:Je});if(!qn.ok){console.warn(qn.statusText),p(Drupal.t("Saving search failed. Please try again.",{},{context:"Search monitor error submitting"})),Qe&&Qe.removeAttribute("disabled"),x(!0);return}c(!0),p(""),x(!0),Qe&&Qe.removeAttribute("disabled")},"onSubmit");p_(T,v),(0,X_.useEffect)(()=>{v&&x(!1)},[v,x]);let R=Drupal.t("Receive search results by email",{},{context:"Search monitor header"}),U=Drupal.t("Open the order form",{},{context:"Search monitor open label"}),A=Drupal.t("Close the order form",{},{context:"Search monitor close label"}),P=Drupal.t("Saved search",{},{context:"Search monitor content title"}),F=Drupal.t("To receive job alerts, carry out the search desired and then save your search. This will allow you to receive email notifications about any new matches.",{},{context:"Search monitor content"}),z=Drupal.t("You can save as many searches as you like. You can delete the saved search via the link in the email messages.",{},{context:"Search monitor content"}),J=Drupal.t("Email address",{},{context:"Search monitor email label"}),X=Drupal.t("Save your search",{},{context:"Search monitor submit button label"}),$=Drupal.t("Your search has been saved",{},{context:"Search monitor thank you header"}),K=Drupal.t("You will receive a confirmation link by email. You can activate the saved search via the link.",{},{context:"Search monitor thank you message"}),te=Drupal.t("Please check these selections",{},{context:"Search monitor error label"}),ae=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_checkbox_label,ce=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_text,pe=window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_url,Ct=Drupal.t("The link opens in a new tab",{},{context:"Explanation for users that the link opens in a new tab instead of the expected current tab"});return(0,Lt.jsxs)("form",{onSubmit:L,className:"job-search-form__search-monitor",children:[!u&&(0,Lt.jsxs)(Lt.Fragment,{children:[(0,Lt.jsx)("h3",{className:"job-search-form__search-monitor__heading",children:R}),(0,Lt.jsx)(Oo,{"aria-controls":"job-search-form__search-monitor__content","aria-expanded":h,iconStart:h?(0,Lt.jsx)($2,{}):(0,Lt.jsx)(Kl,{}),onClick:He=>{He.preventDefault(),m(!h)},style:{"--border-color-focus":"var(--hdbt-color-black)","--background-color":"transparent","--background-color-hover":"trasparent","--outline-color-focus":"var(--hdbt-color-black)",marginTop:"var(--spacing-2-xs)"},theme:ec.Black,type:"button",variant:Ao.Supplementary,children:h?A:U}),(0,Lt.jsxs)("div",{id:"job-search-form__search-monitor__content",className:"job-search-form__search-monitor__content","aria-hidden":!h,children:[(0,Lt.jsx)("h4",{className:"job-search-form__search-monitor__content__heading",children:P}),(0,Lt.jsx)("p",{children:F}),(0,Lt.jsx)("p",{children:z}),f&&(0,Lt.jsx)(op,{className:"job-search-form__search-monitor__error",label:te,ref:T,size:Ki.Medium,type:"error",notificationAriaLabel:Drupal.t("Notification",{},{context:"Search monitor error message type for screen reader"}),children:f}),(0,Lt.jsx)(wu,{className:"job-search-form__search-monitor__email",id:"job-search-form__search_monitor__email",label:J,name:"job-search-form__search_monitor__email",onChange:He=>s(He.target.value),required:!0,style:{...t_,marginTop:"var(--spacing-m)"},type:"email",value:o}),(0,Lt.jsx)("p",{children:(0,Lt.jsxs)("a",{href:pe,target:"_blank",rel:"noreferrer",className:"job-search-form__search-monitor__terms-link",children:[ce," (",Ct,")"]})}),(0,Lt.jsx)(di,{checked:r,className:"job-search-form__search-monitor__terms",id:"job-search-form__search_monitor__terms",label:ae,name:"job-search-form__search_monitor__terms",onChange:He=>n(He.target.checked),required:!0,style:Au}),(0,Lt.jsx)(Oo,{className:"hdbt-search--react__submit-button job-search-form__search-monitor__submit-button",id:"job-search-form__search-monitor__submit-button",style:{marginBottom:"0",marginTop:"var(--spacing-l)"},type:"submit",children:X})]})]}),u&&(0,Lt.jsxs)(Lt.Fragment,{children:[(0,Lt.jsx)("h3",{className:"job-search-form__search-monitor__heading",ref:T,children:$}),(0,Lt.jsx)("p",{children:K})]})]})},"SearchMonitorContainer"),vre=lt(""),bre=lt(!1),yre=lt(!1),xre=lt(""),E9=_re;var Vt=H(Se()),wre=i(()=>{let{size:e}=yn,t=Ke(yr),r=Ke(IL),n=br(CL),{error:o}=Ke(Fo),s=(0,T9.createRef)(),{query:u,promoted:c,handleResults:f}=i9(t),{data:p,error:h,isLoading:m,isValidating:v}=n9({keepPreviousData:!0,query:u,multi:c}),S=!!(!!Object.keys(t).length&&!m&&!v);p_(s,S);let E=i((_,b)=>{_.preventDefault(),n(b.toString())},"updatePage"),y=i(()=>{if(m||v)return(0,Vt.jsx)(yc,{count:e});if(h||o||p?.error)return(0,Vt.jsx)(GL,{error:h||o||p.error,className:"react-search__results",ref:s});let{results:_,jobs:b,total:T}=f(p||{});if(T<=0)return(0,Vt.jsx)(VL,{wrapperClass:"hdbt-search--react__results--container",ref:s});let C=Math.ceil(T/e);return(0,Vt.jsxs)(Vt.Fragment,{children:[(0,Vt.jsx)(h_,{resultText:(0,Vt.jsx)(Vt.Fragment,{children:Drupal.formatPlural(b,"1 open position","@count open positions",{},{context:"Job search results statline"})}),optionalResultsText:(0,Vt.jsx)(Vt.Fragment,{children:Drupal.formatPlural(T,"1 job listing","@count job listings",{},{context:"Job search results statline"})}),actions:(0,Vt.jsx)(NP,{}),actionsClass:"hdbt-search--react__results--sort",ref:s}),(0,Vt.jsx)(RP,{hits:_}),C>1&&(0,Vt.jsx)($L,{currentPage:r,pages:5,totalPages:C,updatePage:E})]})},"getResults");return(0,Vt.jsxs)(Vt.Fragment,{children:[drupalSettings?.helfi_react_search?.hakuvahti_url_set&&(0,Vt.jsx)(E9,{}),(0,Vt.jsx)("div",{className:"job-search__results",children:(0,Vt.jsx)(JL,{loading:m||v,children:y()})})]})},"ResultsContainer"),k9=wre;var qu=H(Se()),Sre=i(()=>(0,qu.jsx)("div",{className:"recruitment-search",children:(0,qu.jsxs)(C9.Suspense,{fallback:(0,qu.jsx)(yc,{count:yn.size}),children:[(0,qu.jsx)(UL,{}),!drupalSettings?.helfi_rekry_job_search?.results_page_path&&(0,qu.jsx)(k9,{})]})}),"SearchContainer"),I9=Sre;var e3=H(Se());MA();var Ere="helfi-rekry-job-search",A9=document.getElementById(Ere);A9&&R9.default.render((0,e3.jsx)(O9.default.StrictMode,{children:(0,e3.jsx)(I9,{})}),A9);})(); From f8a3647b379eaf77d5badb7dae2880520a04ceef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Kalij=C3=A4rvi?= Date: Thu, 11 Dec 2025 13:26:40 +0200 Subject: [PATCH 3/3] Use new formatter settings: Expand = auto, Linewidth = 120. --- src/js/accordion/accordion.js | 14 +- src/js/accordion/accordionItem.js | 26 +- src/js/accordion/accordionState.js | 12 +- src/js/accordion/events.js | 12 +- src/js/accordion/helfiAccordion.js | 72 +--- src/js/chatTrigger.js | 17 +- src/js/closableAnnouncements.js | 26 +- src/js/closableSurveys.js | 49 +-- src/js/desktopMenuToggle.js | 39 +-- src/js/embeddedContentCookieCompliance.js | 325 +++++++----------- src/js/hideAnnouncements.js | 6 +- src/js/languageToast.js | 26 +- src/js/matomo.js | 25 +- src/js/nav-global/menu.js | 102 ++---- src/js/nav-toggle/navToggleDropdown.js | 39 +-- src/js/navToggle.js | 37 +- src/js/positionDropdown.js | 3 +- .../components/results/ResultCard.tsx | 50 +-- .../components/results/ResultsSort.tsx | 14 +- .../containers/FormContainer.tsx | 115 ++----- .../containers/ResultsContainer.tsx | 12 +- .../containers/SelectionsContainer.tsx | 24 +- .../enum/IndexFields.ts | 3 +- .../enum/Settings.ts | 3 +- .../enum/SortOptions.ts | 18 +- .../helpers/Params.ts | 5 +- .../hooks/useAggregations.tsx | 38 +- .../hooks/useLanguageQuery.ts | 11 +- .../hooks/useQueryString.tsx | 123 ++----- .../query/queries.ts | 76 +--- .../district-and-project-search/store.tsx | 8 +- .../types/BooleanQuery.ts | 12 +- .../components/ResultCard.tsx | 18 +- .../components/ResultsList.tsx | 24 +- .../containers/FormContainer.tsx | 37 +- .../containers/ResultsContainer.tsx | 6 +- .../helpers/ProximityQuery.ts | 11 +- .../hooks/UseProximityQuery.ts | 28 +- .../apps/health-station-search/store.tsx | 29 +- .../types/SearchParams.ts | 7 +- .../components/results/ResultCard.tsx | 44 +-- .../components/results/ResultsList.tsx | 6 +- .../components/results/ResultsSort.tsx | 24 +- .../job-search/containers/FormContainer.tsx | 167 ++------- .../containers/ResultsContainer.tsx | 30 +- .../job-search/containers/SearchContainer.tsx | 4 +- .../containers/SearchMonitorContainer.tsx | 105 ++---- .../containers/SelectionsContainer.tsx | 50 +-- src/js/react/apps/job-search/enum/Global.ts | 6 +- .../react/apps/job-search/enum/PostalCodes.ts | 70 +--- src/js/react/apps/job-search/helpers/Areas.ts | 50 +-- .../react/apps/job-search/helpers/Language.ts | 9 +- .../react/apps/job-search/helpers/Params.ts | 11 +- .../job-search/hooks/usePromotedQuery.tsx | 4 +- .../apps/job-search/hooks/useQueryString.tsx | 74 +--- .../apps/job-search/hooks/useResultsQuery.ts | 24 +- src/js/react/apps/job-search/query/queries.ts | 51 +-- src/js/react/apps/job-search/store.tsx | 188 ++++------ .../react/apps/job-search/types/OptionType.ts | 7 +- .../linkedevents/components/DateSelect.tsx | 6 +- .../components/EventTypeFilter.tsx | 13 +- .../components/FullLocationFilter.tsx | 68 +--- .../components/FullTopicsFilter.tsx | 72 +--- .../components/LanguageFilter.tsx | 20 +- .../components/LocationFilter.tsx | 22 +- .../linkedevents/components/Pagination.tsx | 9 +- .../linkedevents/components/ResultCard.tsx | 48 +-- .../linkedevents/components/SeeAllButton.tsx | 12 +- .../linkedevents/components/SubmitButton.tsx | 6 +- .../components/TargetGroupFilter.tsx | 16 +- .../linkedevents/components/TopicsFilter.tsx | 27 +- .../linkedevents/containers/FormContainer.tsx | 102 +----- .../containers/ResultsContainer.tsx | 40 +-- .../containers/SearchContainer.tsx | 39 +-- .../containers/SelectionsContainer.tsx | 86 +---- .../apps/linkedevents/enum/LanguageOptions.ts | 8 +- .../apps/linkedevents/enum/TargetGroups.ts | 26 +- .../helpers/TargetGroupsToParams.ts | 4 +- src/js/react/apps/linkedevents/store.ts | 71 ++-- src/js/react/apps/linkedevents/types/Event.ts | 14 +- .../components/ResultCard.tsx | 18 +- .../components/ResultsList.tsx | 29 +- .../containers/FormContainer.tsx | 37 +- .../containers/ResultsContainer.tsx | 6 +- .../helpers/ProximityQuery.ts | 11 +- .../hooks/UseProximityQuery.ts | 28 +- .../index.tsx | 5 +- .../store.tsx | 29 +- .../types/SearchParams.ts | 7 +- .../apps/news-archive/components/Filter.tsx | 35 +- .../news-archive/components/RssFeedLink.tsx | 22 +- .../news-archive/components/SearchInput.tsx | 10 +- .../components/results/ResultCard.tsx | 9 +- .../news-archive/containers/FormContainer.tsx | 66 +--- .../containers/ResultsContainer.tsx | 21 +- .../containers/SelectionsContainer.tsx | 58 +--- .../news-archive/helpers/NewsSearchParams.ts | 9 +- .../apps/news-archive/hooks/useIndexQuery.tsx | 11 +- .../news-archive/hooks/useInitialQuery.tsx | 14 +- .../news-archive/hooks/useLanguageQuery.ts | 11 +- .../news-archive/hooks/useQueryString.tsx | 14 +- src/js/react/apps/news-archive/store.ts | 3 +- .../news-archive/types/AggregationItem.ts | 6 +- .../apps/news-archive/types/URLParams.ts | 8 +- .../components/ResultCard.tsx | 36 +- .../components/ResultsList.tsx | 10 +- .../containers/FormContainer.tsx | 55 +-- .../helpers/GetQueryString.ts | 4 +- .../helpers/GetScheduleCard.ts | 6 +- .../apps/ploughing-schedule/hooks/UseQuery.ts | 8 +- .../react/apps/ploughing-schedule/store.tsx | 11 +- .../apps/ploughing-schedule/types/Street.ts | 6 +- .../school-search/components/ResultCard.tsx | 46 +-- .../school-search/components/ResultsList.tsx | 21 +- .../containers/FeatureFormContainer.tsx | 211 ++---------- .../containers/FeatureResultsContainer.tsx | 6 +- .../containers/ProximityFormContainer.tsx | 38 +- .../containers/ProximityResultsContainer.tsx | 6 +- .../containers/SearchContainer.tsx | 35 +- .../containers/SelectionsContainer.tsx | 124 ++----- .../enum/LanguageEducationMap.ts | 312 +++-------------- .../school-search/helpers/FeatureQuery.ts | 42 +-- .../school-search/helpers/ProximityQuery.ts | 16 +- .../school-search/hooks/UseFeatureQuery.ts | 6 +- .../school-search/hooks/UseProximityQuery.ts | 20 +- src/js/react/apps/school-search/index.tsx | 6 +- src/js/react/apps/school-search/store.tsx | 73 ++-- src/js/react/common/AddressNotFound.tsx | 38 +- src/js/react/common/AddressSearch.tsx | 59 +--- src/js/react/common/Card.tsx | 97 +----- src/js/react/common/CardImage.tsx | 4 +- src/js/react/common/CardPicture.tsx | 14 +- src/js/react/common/Collapsible.tsx | 32 +- .../common/CookieComplianceStatement.tsx | 37 +- src/js/react/common/DateRangeSelect.tsx | 70 +--- src/js/react/common/ExternalLink.tsx | 12 +- src/js/react/common/FilterButton.tsx | 10 +- src/js/react/common/GhostList.tsx | 14 +- src/js/react/common/LoadingOverlay.tsx | 12 +- src/js/react/common/Pagination.tsx | 95 +---- src/js/react/common/ResultWrapper.tsx | 12 +- src/js/react/common/ResultsEmpty.tsx | 14 +- src/js/react/common/ResultsError.tsx | 25 +- src/js/react/common/ResultsHeader.tsx | 7 +- src/js/react/common/ResultsMap.tsx | 14 +- src/js/react/common/ResultsWrapper.tsx | 8 +- src/js/react/common/SelectionsWrapper.tsx | 16 +- src/js/react/common/Tags.tsx | 16 +- .../react/common/constants/textInputStyle.ts | 4 +- .../common/helpers/GetCurrentLanguage.ts | 4 +- src/js/react/common/helpers/GetDateString.ts | 23 +- src/js/react/common/helpers/HDS.ts | 10 +- src/js/react/common/helpers/Params.ts | 5 +- src/js/react/common/helpers/ServiceMap.ts | 5 +- src/js/react/common/helpers/SubQueries.ts | 18 +- .../common/hooks/useAddressToCoordsQuery.ts | 20 +- src/js/react/common/hooks/useOutsideClick.tsx | 4 +- .../react/common/hooks/useScrollToResults.ts | 5 +- src/js/searchHelper.js | 4 +- src/js/sidebarMenuToggle.js | 17 +- src/js/tabs.js | 16 +- src/js/throbber.js | 3 +- src/js/types/BooleanQuery.ts | 7 +- src/js/types/Result.ts | 8 +- src/js/types/ServiceMap.ts | 7 +- src/js/types/drupal.d.ts | 8 +- src/js/types/drupalSettings.d.ts | 10 +- theme-builder/biome.json | 7 +- 168 files changed, 1221 insertions(+), 4270 deletions(-) diff --git a/src/js/accordion/accordion.js b/src/js/accordion/accordion.js index 35f037ff2..40dd6fd28 100644 --- a/src/js/accordion/accordion.js +++ b/src/js/accordion/accordion.js @@ -41,9 +41,7 @@ const getAccordionType = (classes) => { * The MutationObserver instance that invoked the callback. */ const callback = (_mutations, observer) => { - const items = document.querySelectorAll( - `.${HelfiAccordion.accordionWrapper}`, - ); + const items = document.querySelectorAll(`.${HelfiAccordion.accordionWrapper}`); // Initialize any new accordions that haven’t yet been processed. if (items.length > window.helfiAccordions.length) { @@ -59,16 +57,10 @@ const callback = (_mutations, observer) => { * type “default”, unless it’s explicitly “hardcoded”. * This ensures that the first accordion gets full toggle-all functionality. */ - const actualType = - index === 0 && type !== 'hardcoded' ? 'default' : type; + const actualType = index === 0 && type !== 'hardcoded' ? 'default' : type; // Create the accordion instance. - const accordion = new HelfiAccordion( - accordionElement, - state, - hash, - actualType, - ); + const accordion = new HelfiAccordion(accordionElement, state, hash, actualType); window.helfiAccordions.push(accordion); /** diff --git a/src/js/accordion/accordionItem.js b/src/js/accordion/accordionItem.js index 123024f0d..e4b54ac1e 100644 --- a/src/js/accordion/accordionItem.js +++ b/src/js/accordion/accordionItem.js @@ -69,18 +69,14 @@ export default class AccordionItem { setAriaOpen = () => { AccordionItem.ariaExpandedElements.forEach((className) => { - this.element - .getElementsByClassName(className)[0] - .setAttribute('aria-expanded', this.isOpen); + this.element.getElementsByClassName(className)[0].setAttribute('aria-expanded', this.isOpen); }); }; // Show/hide the accordion content with the hidden-attribute. setHidden = (noAnimation) => { const accordionElement = this.element.closest('.accordion'); - const accordionItemContent = this.element.getElementsByClassName( - AccordionItem.contentElement, - )[0]; + const accordionItemContent = this.element.getElementsByClassName(AccordionItem.contentElement)[0]; // No animation version of show/hide functionality. if (noAnimation) { @@ -106,12 +102,7 @@ export default class AccordionItem { if (!this.isOpen) { // Get the show/hide animation duration from the css. const accordionAnimationDuration = - parseInt( - getComputedStyle(accordionElement).getPropertyValue( - '--js-accordion-open-time', - ), - 10, - ) || 200; + parseInt(getComputedStyle(accordionElement).getPropertyValue('--js-accordion-open-time'), 10) || 200; // Delay the attribute change until the animation has been completed. setTimeout(() => { @@ -122,13 +113,10 @@ export default class AccordionItem { } }; - changeFocus = () => - this.element.querySelector(`.${AccordionItem.toggleElement}`).focus(); + changeFocus = () => this.element.querySelector(`.${AccordionItem.toggleElement}`).focus(); addEventListeners = () => { - const toggleElement = this.element.getElementsByClassName( - AccordionItem.toggleElement, - )[0]; + const toggleElement = this.element.getElementsByClassName(AccordionItem.toggleElement)[0]; toggleElement.addEventListener('mouseup', this.toggle); toggleElement.addEventListener('keypress', this.toggle); @@ -137,9 +125,7 @@ export default class AccordionItem { // button inside an accordion so we should select the last one // since it is the correct one that we want to bind the event // listeners. - const closeElements = this.element.getElementsByClassName( - AccordionItem.closeElement, - ); + const closeElements = this.element.getElementsByClassName(AccordionItem.closeElement); const closeElement = closeElements[closeElements.length - 1]; closeElement.addEventListener('mouseup', this.close); closeElement.addEventListener('keypress', this.close); diff --git a/src/js/accordion/accordionState.js b/src/js/accordion/accordionState.js index e25abbbc9..597e87e47 100644 --- a/src/js/accordion/accordionState.js +++ b/src/js/accordion/accordionState.js @@ -6,9 +6,7 @@ export default class AccordionState { this.storageManager = new LocalStorageManager('helfi-settings'); this.site = window.drupalSettings.helfi_instance_name || ''; this.page = window.drupalSettings.path.currentPath; - this.siteAccordionStates = - JSON.parse(this.storageManager.getValue(this.getAccordionStorageKey())) || - {}; + this.siteAccordionStates = JSON.parse(this.storageManager.getValue(this.getAccordionStorageKey())) || {}; this.pageAccordionStates = this.siteAccordionStates[this.page] || {}; // Initialize the cookie check. This check is for Siteimprove so that it can @@ -20,18 +18,14 @@ export default class AccordionState { saveAccordionItemState = (accordionItemId, isOpen) => { if (!this.site) return false; - if (!this.siteAccordionStates[this.page]) - this.siteAccordionStates[this.page] = {}; + if (!this.siteAccordionStates[this.page]) this.siteAccordionStates[this.page] = {}; // Save only the open accordion items to the local storage. if (isOpen === false) { delete this.siteAccordionStates[this.page][accordionItemId]; } else { this.siteAccordionStates[this.page][accordionItemId] = isOpen; } - this.storageManager.setValue( - this.getAccordionStorageKey(), - JSON.stringify(this.siteAccordionStates), - ); + this.storageManager.setValue(this.getAccordionStorageKey(), JSON.stringify(this.siteAccordionStates)); }; loadAccordionItemState = (accordionItemId) => { diff --git a/src/js/accordion/events.js b/src/js/accordion/events.js index d2bcba5c5..37bcc0dd7 100644 --- a/src/js/accordion/events.js +++ b/src/js/accordion/events.js @@ -16,9 +16,7 @@ export default class Events { let accordionItemFound = false; window.helfiAccordions.forEach((accordion) => { - const accordionItem = accordion.getAccordionItemById( - hash.replace('#', ''), - ); + const accordionItem = accordion.getAccordionItemById(hash.replace('#', '')); if (accordionItem) { accordionItemFound = true; accordionItem.handleLinkAnchor(hash); @@ -31,14 +29,10 @@ export default class Events { if (!anchorElement) { return; } - const accordionItemToOpen = anchorElement.closest( - `.${AccordionItem.accordionItemElement}`, - ); + const accordionItemToOpen = anchorElement.closest(`.${AccordionItem.accordionItemElement}`); if (accordionItemToOpen) { window.helfiAccordions.forEach((accordion) => { - const idToSearch = accordionItemToOpen.querySelector( - '.helfi-accordion__header', - ).id; + const idToSearch = accordionItemToOpen.querySelector('.helfi-accordion__header').id; const accordionItem = accordion.getAccordionItemById(idToSearch); if (accordionItem) { accordionItem.handleLinkAnchor(); diff --git a/src/js/accordion/helfiAccordion.js b/src/js/accordion/helfiAccordion.js index 90f67ebfb..ef2bbfc99 100644 --- a/src/js/accordion/helfiAccordion.js +++ b/src/js/accordion/helfiAccordion.js @@ -39,21 +39,12 @@ export default class HelfiAccordion { * Initialize accordion items and optional “hidden until found” support. */ initializeAccordion = () => { - const accordionItems = this.accordion.getElementsByClassName( - AccordionItem.accordionItemElement, - ); + const accordionItems = this.accordion.getElementsByClassName(AccordionItem.accordionItemElement); this.isSingleItemAccordion = accordionItems.length === 1; // Create AccordionItem instances for each item in this accordion. Array.from(accordionItems).forEach((element) => { - this.accordionItems.push( - new AccordionItem( - element, - this.localState, - this.urlHash, - this.updateToggleButtonLabel, - ), - ); + this.accordionItems.push(new AccordionItem(element, this.localState, this.urlHash, this.updateToggleButtonLabel)); }); // Initialize hidden="until-found" functionality if it is supported. @@ -68,9 +59,7 @@ export default class HelfiAccordion { enableHiddenUntilFound = () => { this.accordionItems.forEach((accordionItem) => { accordionItem.element.classList.add('accordion-item--hidden-until-found'); - const accordionItemContent = accordionItem.element.querySelector( - '.accordion-item__content', - ); + const accordionItemContent = accordionItem.element.querySelector('.accordion-item__content'); // If item is defined in the state as open, don't close it. if (!accordionItem.isOpen) { @@ -81,10 +70,7 @@ export default class HelfiAccordion { // highlight is found on the url parameters. accordionItem.element.addEventListener('beforematch', () => { // Disable animations on the accordion on these events. - accordionItem.element.style.setProperty( - '--js-accordion-open-time', - '0s', - ); + accordionItem.element.style.setProperty('--js-accordion-open-time', '0s'); // Force a reflow to ensure the style change takes effect. void accordionItem.element.offsetHeight; @@ -94,9 +80,7 @@ export default class HelfiAccordion { // Enable the animations again after the accordion has been opened. setTimeout(() => { - accordionItem.element.style.removeProperty( - '--js-accordion-open-time', - ); + accordionItem.element.style.removeProperty('--js-accordion-open-time'); }, 10); }); }); @@ -111,9 +95,7 @@ export default class HelfiAccordion { return; } - const toggleAllElement = this.accordion.getElementsByClassName( - HelfiAccordion.toggleAllElement, - )[0]; + const toggleAllElement = this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]; toggleAllElement.addEventListener('mouseup', this.toggleItems); toggleAllElement.addEventListener('keypress', this.toggleItems); }; @@ -124,13 +106,9 @@ export default class HelfiAccordion { showToggleButton = () => { if (HelfiAccordion.isHeaderless(this.type) || this.isSingleItemAccordion) { - this.accordion - .getElementsByClassName(HelfiAccordion.toggleAllElement)[0] - ?.classList.add('is-hidden'); + this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]?.classList.add('is-hidden'); } else { - this.accordion - .getElementsByClassName(HelfiAccordion.toggleAllElement)[0] - ?.classList.remove('is-hidden'); + this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]?.classList.remove('is-hidden'); } }; @@ -138,32 +116,24 @@ export default class HelfiAccordion { * Update the toggle-all button label based on current accordion state. */ updateToggleButtonLabel = () => { - const toggleAllElement = this.accordion.getElementsByClassName( - HelfiAccordion.toggleAllElement, - )[0]; + const toggleAllElement = this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]; if (!toggleAllElement) return; const span = toggleAllElement.querySelector('span'); if (!span) return; if (this.areAllItemsOpen()) { - span.textContent = - Translations.close_all?.[this.currentLanguage] ?? - Translations.close_all.en; + span.textContent = Translations.close_all?.[this.currentLanguage] ?? Translations.close_all.en; } else { - span.textContent = - Translations.open_all?.[this.currentLanguage] ?? - Translations.open_all.en; + span.textContent = Translations.open_all?.[this.currentLanguage] ?? Translations.open_all.en; } this.toggleAllLabelUpdate(); }; - getAccordionItemById = (id) => - this.accordionItems.find((accordionItem) => accordionItem.id === id); + getAccordionItemById = (id) => this.accordionItems.find((accordionItem) => accordionItem.id === id); - toggleItems = () => - this.areAllItemsOpen() ? this.closeAll() : this.openAll(); + toggleItems = () => (this.areAllItemsOpen() ? this.closeAll() : this.openAll()); /** * Opens all accordion items (including child accordions, if any). @@ -189,9 +159,7 @@ export default class HelfiAccordion { this.toggleAllLabelUpdate(); // Move focus back to the toggle-all button for accessibility. - const toggleAllElement = this.accordion.getElementsByClassName( - HelfiAccordion.toggleAllElement, - )[0]; + const toggleAllElement = this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]; toggleAllElement.focus(); }; @@ -199,9 +167,7 @@ export default class HelfiAccordion { * Updates the toggle-all button’s open/closed CSS classes. */ toggleAllLabelUpdate = () => { - const toggleAllElement = this.accordion.getElementsByClassName( - HelfiAccordion.toggleAllElement, - )[0]; + const toggleAllElement = this.accordion.getElementsByClassName(HelfiAccordion.toggleAllElement)[0]; if (toggleAllElement && this.areAllItemsOpen()) { toggleAllElement.classList.remove(HelfiAccordion.toggleAllClosed); @@ -212,13 +178,9 @@ export default class HelfiAccordion { } }; - areAllItemsOpen = () => - this.accordionItems?.every((item) => item.isOpen) && - this.areChildItemsOpen(); + areAllItemsOpen = () => this.accordionItems?.every((item) => item.isOpen) && this.areChildItemsOpen(); - areChildItemsOpen = () => - this.childAccordion?.areAllItemsOpen() ?? - this.accordionItems?.every((item) => item.isOpen); + areChildItemsOpen = () => this.childAccordion?.areAllItemsOpen() ?? this.accordionItems?.every((item) => item.isOpen); static isHeaderless = (type) => HelfiAccordion.headerlessTypes.includes(type); diff --git a/src/js/chatTrigger.js b/src/js/chatTrigger.js index 455a1fec7..18b1f9b70 100644 --- a/src/js/chatTrigger.js +++ b/src/js/chatTrigger.js @@ -1,11 +1,7 @@ // This script replaces chat trigger placeholder elements with buttons that open the chat. (function chatTriggerWrapper() { const triggerTranslations = { - fallback: { - fi: 'Chatti ei ole saatavilla.', - sv: 'Chatten är inte tillgänglig.', - en: 'The chat is not available.', - }, + fallback: { fi: 'Chatti ei ole saatavilla.', sv: 'Chatten är inte tillgänglig.', en: 'The chat is not available.' }, openChat: { fi: 'Avaa chat', sv: 'Öppna chatten', en: 'Open the chat' }, }; @@ -30,10 +26,7 @@ resolve(elem); } }); - observer.observe(document.documentElement, { - childList: true, - subtree: true, - }); + observer.observe(document.documentElement, { childList: true, subtree: true }); } }); } @@ -55,16 +48,14 @@ // The trigger is present but the chat is not available, show fallback until chat is available. if (!document.querySelector(targetSelector)) { - const content = - triggerTranslations.fallback[lang] || triggerTranslations.fallback.en; + const content = triggerTranslations.fallback[lang] || triggerTranslations.fallback.en; placeholder.textContent = content; } // Wait for the target element to appear in the DOM and replace the trigger with a button that opens the chat. waitForElement(targetSelector).then(() => { const triggerButton = document.createElement('button'); - triggerButton.textContent = - triggerTranslations.openChat[lang] || triggerTranslations.openChat.en; + triggerButton.textContent = triggerTranslations.openChat[lang] || triggerTranslations.openChat.en; triggerButton.dataset.hdsComponent = 'button'; triggerButton.dataset.hdsVariant = 'secondary'; triggerButton.dataset.clickSelector = targetSelector; diff --git a/src/js/closableAnnouncements.js b/src/js/closableAnnouncements.js index 1ec58733b..8248db689 100644 --- a/src/js/closableAnnouncements.js +++ b/src/js/closableAnnouncements.js @@ -23,22 +23,17 @@ import LocalStorageManager from './localStorageManager'; announcement.style = `--js-announcement-height: ${announcement.offsetHeight}px`; window.setTimeout(() => { let focused = false; - const allAnnouncements = document.querySelectorAll( - '.announcement:not(.js-announcement--hide)', - ); + const allAnnouncements = document.querySelectorAll('.announcement:not(.js-announcement--hide)'); announcement.classList.add(ANNOUCEMENT_HIDE); // Moving focus to correct place after closing the announcement. // NOTICE: This is very dependent on the html-structure of the header and its components. // Go through all announcements and use the uuid to determine which focusable announcement is before // the closed announcement. for (let i = 0, max = allAnnouncements.length; i < max; i++) { - if ( - allAnnouncements[i].dataset.uuid === announcement.dataset.uuid && - i > 0 - ) { - const focusableAnnouncement = allAnnouncements[ - i - 1 - ].querySelectorAll('.announcement__close, .announcement__link a'); + if (allAnnouncements[i].dataset.uuid === announcement.dataset.uuid && i > 0) { + const focusableAnnouncement = allAnnouncements[i - 1].querySelectorAll( + '.announcement__close, .announcement__link a', + ); focusableAnnouncement[focusableAnnouncement.length - 1].focus(); focused = true; break; @@ -47,18 +42,13 @@ import LocalStorageManager from './localStorageManager'; // If there is no more announcements to focus to we need to figure out if we are viewing the page with mobile // or desktop navigation. We check if the header-bottom menu is visible to determine this. if (focused === false) { - const desktopMenu = document.querySelector( - '.header-bottom .desktop-menu > .menu', - ); - const desktopMenuHidden = - window.getComputedStyle(desktopMenu).display === 'none'; + const desktopMenu = document.querySelector('.header-bottom .desktop-menu > .menu'); + const desktopMenuHidden = window.getComputedStyle(desktopMenu).display === 'none'; // Depending on the visible menu we move the focus straight to nav-toggle buttons or the menu links if no // breadcrumb is set. if (desktopMenuHidden === true) { // Move the focus on mobile: - const focusableElements = document.querySelectorAll( - '.nav-toggle__button, .breadcrumb a:last-of-type', - ); + const focusableElements = document.querySelectorAll('.nav-toggle__button, .breadcrumb a:last-of-type'); focusableElements[focusableElements.length - 1].focus(); } else { // Move the focus on desktop: diff --git a/src/js/closableSurveys.js b/src/js/closableSurveys.js index b05936172..011501d51 100644 --- a/src/js/closableSurveys.js +++ b/src/js/closableSurveys.js @@ -8,15 +8,10 @@ import LocalStorageManager from './localStorageManager'; // If not move it as last element inside the body element so that the header (h1, h2, etc.) structure will be // correct. const blockSurveys = document.getElementById('block-surveys'); - const offCanvas = document.getElementById( - 'dialog-off-canvas-main-canvas', - ); + const offCanvas = document.getElementById('dialog-off-canvas-main-canvas'); if (blockSurveys) { if (offCanvas) { - offCanvas.parentNode.insertBefore( - blockSurveys, - offCanvas.nextSibling, - ); + offCanvas.parentNode.insertBefore(blockSurveys, offCanvas.nextSibling); } else { document.body.insertBefore(blockSurveys, document.body.lastChild); } @@ -27,9 +22,7 @@ import LocalStorageManager from './localStorageManager'; const root = document.documentElement; const surveyDelay = 2000; - const surveyButtons = document.querySelectorAll( - '.dialog__actions .dialog__action-button', - ); + const surveyButtons = document.querySelectorAll('.dialog__actions .dialog__action-button'); const surveyKey = 'hidden-helfi-surveys'; const storageManager = new LocalStorageManager('helfi-settings'); let surveysToHide = null; @@ -41,9 +34,7 @@ import LocalStorageManager from './localStorageManager'; try { // @todo Use the storageManager instead. - surveysToHide = JSON.parse( - window.localStorage.getItem('helfi-settings'), - ); + surveysToHide = JSON.parse(window.localStorage.getItem('helfi-settings')); } catch (e) { console.error('Error parsing local storage data:', e); } @@ -78,9 +69,7 @@ import LocalStorageManager from './localStorageManager'; // Check if the cookie banner exists and focus the appropriate button const cookieBanner = document.querySelector('.hds-cc__target'); const shadowRoot = cookieBanner?.shadowRoot; - const cookieButton = shadowRoot?.querySelector( - '.hds-cc__all-cookies-button', - ); + const cookieButton = shadowRoot?.querySelector('.hds-cc__all-cookies-button'); if (cookieBanner && cookieButton) { cookieButton.focus(); @@ -88,40 +77,24 @@ import LocalStorageManager from './localStorageManager'; } function toggleOtherContentVisibility() { - const mainContent = document.querySelector( - '.dialog-off-canvas-main-canvas', - ); + const mainContent = document.querySelector('.dialog-off-canvas-main-canvas'); const cookieBanner = document.querySelector('.hds-cc__target'); const skipToMain = document.querySelector('.skip-link--skip-to-main'); - const surveyContainer = document.getElementById( - 'helfi-survey__container', - ); - - if ( - mainContent && - !mainContent.hasAttribute('inert') && - surveyContainer - ) { + const surveyContainer = document.getElementById('helfi-survey__container'); + + if (mainContent && !mainContent.hasAttribute('inert') && surveyContainer) { mainContent.setAttribute('inert', ''); } else { mainContent?.removeAttribute('inert'); } - if ( - skipToMain && - !skipToMain.hasAttribute('inert') && - surveyContainer - ) { + if (skipToMain && !skipToMain.hasAttribute('inert') && surveyContainer) { skipToMain.setAttribute('inert', ''); } else { skipToMain?.removeAttribute('inert'); } - if ( - cookieBanner && - !cookieBanner.hasAttribute('inert') && - surveyContainer - ) { + if (cookieBanner && !cookieBanner.hasAttribute('inert') && surveyContainer) { cookieBanner.setAttribute('inert', ''); } else { cookieBanner?.removeAttribute('inert'); diff --git a/src/js/desktopMenuToggle.js b/src/js/desktopMenuToggle.js index beece5a1a..eb1f645cf 100644 --- a/src/js/desktopMenuToggle.js +++ b/src/js/desktopMenuToggle.js @@ -11,10 +11,7 @@ const clearStyles = (element) => { }; const updateFirstChildAriaExpanded = (item) => { - const state = - item.classList.contains(OPEN_CLASS) || item.classList.contains(HOVER_CLASS) - ? 'true' - : 'false'; + const state = item.classList.contains(OPEN_CLASS) || item.classList.contains(HOVER_CLASS) ? 'true' : 'false'; const firstChild = item.querySelector(':first-child .menu__toggle-button'); if (firstChild) { firstChild.setAttribute('aria-expanded', state); @@ -22,9 +19,7 @@ const updateFirstChildAriaExpanded = (item) => { }; const closeOpenItems = (element) => { - const allOpenItems = document.querySelectorAll( - `.desktop-menu .${OPEN_CLASS}`, - ); + const allOpenItems = document.querySelectorAll(`.desktop-menu .${OPEN_CLASS}`); // Check that the item we are about to close is not the // element-variable given to the function. @@ -59,9 +54,7 @@ const mouseOver = (event) => { closeOpenItems(item); item.classList.add(HOVER_CLASS); updateFirstChildAriaExpanded(item); - positionDropdown(item.querySelector('.menu__toggle-button'), item, { - gutter: 12, - }); + positionDropdown(item.querySelector('.menu__toggle-button'), item, { gutter: 12 }); }; const mouseLeave = (event) => { @@ -123,9 +116,7 @@ const closeOnFocusOut = (item) => { document.addEventListener('keydown', handleEscKey); window.addEventListener('click', (event) => { - const mainNav = document.querySelector( - '[data-hdbt-selector="main-navigation"]', - ); + const mainNav = document.querySelector('[data-hdbt-selector="main-navigation"]'); if (mainNav?.contains(event.target)) { let clickedElement = event.target; @@ -135,9 +126,7 @@ const closeOnFocusOut = (item) => { } if (clickedElement.classList.contains('menu__toggle-button')) { - const clickedElementParent = clickedElement.parentElement.closest( - '.menu__item--children', - ); + const clickedElementParent = clickedElement.parentElement.closest('.menu__item--children'); const clickedElementSiblings = getSiblings(clickedElementParent); closeOnFocusOut(clickedElementParent); @@ -166,11 +155,9 @@ const closeOnFocusOut = (item) => { }); // Show toggle button if js is enabled. - document - .querySelectorAll('.header-bottom .menu__toggle-button') - .forEach((button) => { - button.classList.add('js-show-menu__toggle-button'); - }); + document.querySelectorAll('.header-bottom .menu__toggle-button').forEach((button) => { + button.classList.add('js-show-menu__toggle-button'); + }); // Use Drupal's once() to ensure this runs only once per element. const itemsWithVisibleChildren = once( @@ -180,9 +167,7 @@ const closeOnFocusOut = (item) => { ); itemsWithVisibleChildren.forEach((item) => { - const firstLevelItem = item.querySelector( - '.menu--level-0 > .menu__item--item-below > .menu__link-wrapper > a', - ); + const firstLevelItem = item.querySelector('.menu--level-0 > .menu__item--item-below > .menu__link-wrapper > a'); const firstLevelItemButton = item.querySelector( '.menu--level-0 > .menu__item--item-below > .menu__link-wrapper > .menu__toggle-button', ); @@ -194,11 +179,7 @@ const closeOnFocusOut = (item) => { } if (firstLevelItemButton) { - firstLevelItemButton.addEventListener( - 'mouseover', - mouseLeaveButton, - false, - ); + firstLevelItemButton.addEventListener('mouseover', mouseLeaveButton, false); } item.addEventListener('mouseleave', mouseLeave, false); diff --git a/src/js/embeddedContentCookieCompliance.js b/src/js/embeddedContentCookieCompliance.js index f2f817005..f77830aa3 100644 --- a/src/js/embeddedContentCookieCompliance.js +++ b/src/js/embeddedContentCookieCompliance.js @@ -17,205 +17,136 @@ }; const loadEmbeddedContent = () => { - Object.entries(drupalSettings?.embedded_media_attributes || {}).forEach( - ([id, attributes]) => { - if (!categoriesAgreed(attributes?.cookieConsentGroups)) { - return; + Object.entries(drupalSettings?.embedded_media_attributes || {}).forEach(([id, attributes]) => { + if (!categoriesAgreed(attributes?.cookieConsentGroups)) { + return; + } + + const mediaContainers = $(`.embedded-content-cookie-compliance.media-${id}`); + + // Each of the media type is grouped to their own + // mediaContainers so we need to iterate through them. + mediaContainers.each(function processMediaContainer(index) { + const mediaContainer = $(this); + + const iframeElement = document.createElement('iframe'); + iframeElement.classList.add('media-oembed-content'); + iframeElement.src = attributes.src; + iframeElement.title = attributes.title; + + if (attributes.allow) { + iframeElement.allow = attributes.allow; + } + + if (attributes.height) { + iframeElement.height = attributes.height; + } + if (attributes.width) { + iframeElement.width = attributes.width; } - const mediaContainers = $( - `.embedded-content-cookie-compliance.media-${id}`, - ); - - // Each of the media type is grouped to their own - // mediaContainers so we need to iterate through them. - mediaContainers.each(function processMediaContainer(index) { - const mediaContainer = $(this); - - const iframeElement = document.createElement('iframe'); - iframeElement.classList.add('media-oembed-content'); - iframeElement.src = attributes.src; - iframeElement.title = attributes.title; - - if (attributes.allow) { - iframeElement.allow = attributes.allow; - } - - if (attributes.height) { - iframeElement.height = attributes.height; - } - if (attributes.width) { - iframeElement.width = attributes.width; - } - - const containerElement = document.createElement('div'); - containerElement.appendChild(iframeElement); - - // Extract the media name from the wrapping component title or in - // case of video, from the remote video - video title. - // Fallback to empty if no title is set. - let mediaName = ''; - switch (attributes.type) { - case 'video': - mediaName = - mediaContainer - .parent() - .siblings('.remote-video__video-title') - .text() - .trim() || ''; - break; - default: - mediaName = - mediaContainer - .closest(`.component__content.${attributes.type}`) - .siblings('.component__title') - .text() - .trim() || ''; - break; - } - - // Initialize skip links elements. - const skipLinkBefore = document.createElement('a'); - const skipLinkAfter = document.createElement('a'); - - // Construct skip links if their IDs are set. - if (attributes.skipLinkBeforeId && attributes.skipLinkAfterId) { - skipLinkBefore.classList.add('focusable', 'skip-link'); - skipLinkBefore.href = `#${attributes.skipLinkAfterId}-${index}`; - skipLinkBefore.id = `${attributes.skipLinkBeforeId}-${index}`; - - skipLinkAfter.classList.add('focusable', 'skip-link'); - skipLinkAfter.href = `#${attributes.skipLinkBeforeId}-${index}`; - skipLinkAfter.id = `${attributes.skipLinkAfterId}-${index}`; - } - - switch (attributes.type) { - case 'video': - containerElement.classList.add( - `responsive-${attributes.type}-container`, - ); - skipLinkAfter.classList.add('skip-link--video--after'); - skipLinkBefore.classList.add('skip-link--video--before'); - - // Adjust the skip link text based on whether the mediaName is found. - skipLinkAfter.text = Drupal.t( - 'Continue above the @video video', - { '@video': mediaName }, - { context: 'Skip links' }, - ); - skipLinkBefore.text = Drupal.t( - 'Continue below the @video video', - { '@video': mediaName }, - { context: 'Skip links' }, - ); - mediaContainer.replaceWith( - skipLinkBefore, - containerElement, - skipLinkAfter, - ); - break; - - case 'chart': - containerElement.classList.add( - `responsive-${attributes.type}-container`, - ); - skipLinkAfter.classList.add('skip-link--chart--after'); - skipLinkBefore.classList.add('skip-link--chart--before'); - - // Adjust the skip link text based on whether the mediaName is found. - skipLinkAfter.text = mediaName - ? Drupal.t( - 'Continue above the @chart chart', - { '@chart': mediaName }, - { context: 'Skip links' }, - ) - : Drupal.t( - 'Continue above the chart', - {}, - { context: 'Skip links' }, - ); - skipLinkBefore.text = mediaName - ? Drupal.t( - 'Continue below the @chart chart', - { '@chart': mediaName }, - { context: 'Skip links' }, - ) - : Drupal.t( - 'Continue below the chart', - {}, - { context: 'Skip links' }, - ); - - mediaContainer.replaceWith( - skipLinkBefore, - containerElement, - skipLinkAfter, - ); - break; - - case 'journey_planner': - containerElement.classList.add('journey-planner-container'); - skipLinkAfter.classList.add('skip-link--planner--after'); - skipLinkBefore.classList.add('skip-link--planner--before'); - skipLinkAfter.text = Drupal.t( - 'Continue above the journey planner', - {}, - { context: 'Skip links' }, - ); - skipLinkBefore.text = Drupal.t( - 'Continue below the journey planner', - {}, - { context: 'Skip links' }, - ); - mediaContainer.replaceWith( - skipLinkBefore, - containerElement, - skipLinkAfter, - ); - break; - - case 'map': - containerElement.classList.add('responsive-map-container'); - skipLinkAfter.classList.add('skip-link--map--after'); - skipLinkBefore.classList.add('skip-link--map--before'); - - // Adjust the skip link text based on whether the mediaName is found. - skipLinkAfter.text = mediaName - ? Drupal.t( - 'Continue above the @map map', - { '@map': mediaName }, - { context: 'Skip links' }, - ) - : Drupal.t( - 'Continue above the map', - {}, - { context: 'Skip links' }, - ); - skipLinkBefore.text = mediaName - ? Drupal.t( - 'Continue below the @map map', - { '@map': mediaName }, - { context: 'Skip links' }, - ) - : Drupal.t( - 'Continue below the map', - {}, - { context: 'Skip links' }, - ); - - mediaContainer.replaceWith( - skipLinkBefore, - containerElement, - skipLinkAfter, - ); - break; - - default: - break; - } - }); - }, - ); + const containerElement = document.createElement('div'); + containerElement.appendChild(iframeElement); + + // Extract the media name from the wrapping component title or in + // case of video, from the remote video - video title. + // Fallback to empty if no title is set. + let mediaName = ''; + switch (attributes.type) { + case 'video': + mediaName = mediaContainer.parent().siblings('.remote-video__video-title').text().trim() || ''; + break; + default: + mediaName = + mediaContainer + .closest(`.component__content.${attributes.type}`) + .siblings('.component__title') + .text() + .trim() || ''; + break; + } + + // Initialize skip links elements. + const skipLinkBefore = document.createElement('a'); + const skipLinkAfter = document.createElement('a'); + + // Construct skip links if their IDs are set. + if (attributes.skipLinkBeforeId && attributes.skipLinkAfterId) { + skipLinkBefore.classList.add('focusable', 'skip-link'); + skipLinkBefore.href = `#${attributes.skipLinkAfterId}-${index}`; + skipLinkBefore.id = `${attributes.skipLinkBeforeId}-${index}`; + + skipLinkAfter.classList.add('focusable', 'skip-link'); + skipLinkAfter.href = `#${attributes.skipLinkBeforeId}-${index}`; + skipLinkAfter.id = `${attributes.skipLinkAfterId}-${index}`; + } + + switch (attributes.type) { + case 'video': + containerElement.classList.add(`responsive-${attributes.type}-container`); + skipLinkAfter.classList.add('skip-link--video--after'); + skipLinkBefore.classList.add('skip-link--video--before'); + + // Adjust the skip link text based on whether the mediaName is found. + skipLinkAfter.text = Drupal.t( + 'Continue above the @video video', + { '@video': mediaName }, + { context: 'Skip links' }, + ); + skipLinkBefore.text = Drupal.t( + 'Continue below the @video video', + { '@video': mediaName }, + { context: 'Skip links' }, + ); + mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter); + break; + + case 'chart': + containerElement.classList.add(`responsive-${attributes.type}-container`); + skipLinkAfter.classList.add('skip-link--chart--after'); + skipLinkBefore.classList.add('skip-link--chart--before'); + + // Adjust the skip link text based on whether the mediaName is found. + skipLinkAfter.text = mediaName + ? Drupal.t('Continue above the @chart chart', { '@chart': mediaName }, { context: 'Skip links' }) + : Drupal.t('Continue above the chart', {}, { context: 'Skip links' }); + skipLinkBefore.text = mediaName + ? Drupal.t('Continue below the @chart chart', { '@chart': mediaName }, { context: 'Skip links' }) + : Drupal.t('Continue below the chart', {}, { context: 'Skip links' }); + + mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter); + break; + + case 'journey_planner': + containerElement.classList.add('journey-planner-container'); + skipLinkAfter.classList.add('skip-link--planner--after'); + skipLinkBefore.classList.add('skip-link--planner--before'); + skipLinkAfter.text = Drupal.t('Continue above the journey planner', {}, { context: 'Skip links' }); + skipLinkBefore.text = Drupal.t('Continue below the journey planner', {}, { context: 'Skip links' }); + mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter); + break; + + case 'map': + containerElement.classList.add('responsive-map-container'); + skipLinkAfter.classList.add('skip-link--map--after'); + skipLinkBefore.classList.add('skip-link--map--before'); + + // Adjust the skip link text based on whether the mediaName is found. + skipLinkAfter.text = mediaName + ? Drupal.t('Continue above the @map map', { '@map': mediaName }, { context: 'Skip links' }) + : Drupal.t('Continue above the map', {}, { context: 'Skip links' }); + skipLinkBefore.text = mediaName + ? Drupal.t('Continue below the @map map', { '@map': mediaName }, { context: 'Skip links' }) + : Drupal.t('Continue below the map', {}, { context: 'Skip links' }); + + mediaContainer.replaceWith(skipLinkBefore, containerElement, skipLinkAfter); + break; + + default: + break; + } + }); + }); }; // Remove noscript element. diff --git a/src/js/hideAnnouncements.js b/src/js/hideAnnouncements.js index 5e7404d6d..c4c64cf39 100644 --- a/src/js/hideAnnouncements.js +++ b/src/js/hideAnnouncements.js @@ -2,11 +2,7 @@ const uuidsToHide = JSON.parse(window.localStorage.getItem('helfi-settings')); const elements = document.querySelectorAll('.js-announcement'); - if ( - !uuidsToHide || - !('hidden-helfi-announcements' in uuidsToHide) || - !elements - ) { + if (!uuidsToHide || !('hidden-helfi-announcements' in uuidsToHide) || !elements) { return; } diff --git a/src/js/languageToast.js b/src/js/languageToast.js index d48b63ef3..466fec4af 100644 --- a/src/js/languageToast.js +++ b/src/js/languageToast.js @@ -18,10 +18,7 @@ import { positionDropdown } from './positionDropdown'; const buttonParent = button.parentElement; const toast = buttonParent?.nextElementSibling; - if ( - !toast || - !toast.classList.contains('nav-toggle-dropdown--language-toast') - ) { + if (!toast || !toast.classList.contains('nav-toggle-dropdown--language-toast')) { return; } @@ -34,19 +31,14 @@ import { positionDropdown } from './positionDropdown'; // Ensure only one resize listener is added globally. if (!window.__toastResizeBound) { window.addEventListener('resize', () => { - document - .querySelectorAll('.nav-toggle__button.has-toast') - .forEach((button) => { - const buttonParent = button.parentElement; - const toast = buttonParent?.nextElementSibling; - - if ( - toast && - !toast.classList.contains('nav-toggle-dropdown--closed') - ) { - positionDropdown(button, button, { isToast: true }); - } - }); + document.querySelectorAll('.nav-toggle__button.has-toast').forEach((button) => { + const buttonParent = button.parentElement; + const toast = buttonParent?.nextElementSibling; + + if (toast && !toast.classList.contains('nav-toggle-dropdown--closed')) { + positionDropdown(button, button, { isToast: true }); + } + }); }); window.__toastResizeBound = true; diff --git a/src/js/matomo.js b/src/js/matomo.js index e9e505b3e..d2cce07d4 100644 --- a/src/js/matomo.js +++ b/src/js/matomo.js @@ -8,22 +8,14 @@ function getBrowserSize() { function loadMatomoAnalytics() { const { helfi_environment: environment } = drupalSettings; - if ( - !( - Drupal.cookieConsent.getConsentStatus(['statistics']) && - drupalSettings.matomo_site_id - ) - ) { + if (!(Drupal.cookieConsent.getConsentStatus(['statistics']) && drupalSettings.matomo_site_id)) { return; } const getViewportWidth = () => window.innerWidth; const getViewportHeight = () => window.innerHeight; const getLanguage = () => document.querySelector('html')?.lang || 'unknown'; - const getPublishedTime = () => - document.querySelector('meta[property="article:published_time"]') - ?.content || ''; - const getUpdatedTime = () => - document.querySelector('meta[property="og:updated_time"]')?.content || ''; + const getPublishedTime = () => document.querySelector('meta[property="article:published_time"]')?.content || ''; + const getUpdatedTime = () => document.querySelector('meta[property="og:updated_time"]')?.content || ''; const getNewsTaxonomyTermIds = () => drupalSettings.news_taxonomy_term_ids; // biome-ignore lint/suspicious/noAssignInExpressions: _paq assignment is intentional. const _paq = (window._paq = window._paq || []); @@ -216,11 +208,7 @@ function getBrowserSize() { // Duplicate tracking of other sites to front page as well. if (!isFrontPage) { - _paq.push([ - 'addTracker', - `${u}tracker.php`, - drupalSettings.matomo_site_id, - ]); + _paq.push(['addTracker', `${u}tracker.php`, drupalSettings.matomo_site_id]); } // If the site is Etusivu-instance and there are newsTaxonomyTermIds set, sent them to custom dimension. @@ -240,10 +228,7 @@ function getBrowserSize() { s.parentNode.insertBefore(g, s); // Testing manual heatmap recording to one heatmap. - _paq.push([ - 'HeatmapSessionRecording.addConfig', - { heatmap: { id: 864, sample_rate: '100.0' } }, - ]); + _paq.push(['HeatmapSessionRecording.addConfig', { heatmap: { id: 864, sample_rate: '100.0' } }]); _paq.push(['HeatmapSessionRecording::enableDebugMode']); })(); diff --git a/src/js/nav-global/menu.js b/src/js/nav-global/menu.js index e5a457417..4e6557086 100644 --- a/src/js/nav-global/menu.js +++ b/src/js/nav-global/menu.js @@ -1,26 +1,11 @@ import cls from 'classnames'; import Mustache from 'mustache'; -const frontpageTranslation = Drupal.t( - 'Frontpage', - {}, - { context: 'Global navigation mobile menu top level' }, -); -const openSubMenuTranslation = Drupal.t( - 'Open submenu:', - {}, - { context: 'Mobile navigation menu prefix' }, -); -const openParentMenuTranslation = Drupal.t( - 'Open parent menu:', - {}, - { context: 'Mobile navigation menu prefix' }, -); - -Array.prototype.findRecursive = function findRecursivelyFromArray( - predicate, - childrenPropertyName, -) { +const frontpageTranslation = Drupal.t('Frontpage', {}, { context: 'Global navigation mobile menu top level' }); +const openSubMenuTranslation = Drupal.t('Open submenu:', {}, { context: 'Mobile navigation menu prefix' }); +const openParentMenuTranslation = Drupal.t('Open parent menu:', {}, { context: 'Mobile navigation menu prefix' }); + +Array.prototype.findRecursive = function findRecursivelyFromArray(predicate, childrenPropertyName) { if (!childrenPropertyName) { throw new Error('findRecursive requires parameter `childrenPropertyName`'); } @@ -123,10 +108,7 @@ function externalLinkIcon() { return false; } - return ( - externalLinkIcon.ICONS[this.attributes['data-protocol']] || - externalLinkIcon.ICONS.external - ); + return externalLinkIcon.ICONS[this.attributes['data-protocol']] || externalLinkIcon.ICONS.external; } externalLinkIcon.ICONS = { @@ -272,13 +254,8 @@ const MobilePanel = { sortPanelsByPath() { const panels = []; const allItems = this.data; - const currentItem = allItems.findRecursive( - (item) => isCurrentPath.call(item), - 'sub_tree', - ); - let parentIndex = currentItem?.sub_tree?.length - ? currentItem.id - : currentItem?.parentId; + const currentItem = allItems.findRecursive((item) => isCurrentPath.call(item), 'sub_tree'); + let parentIndex = currentItem?.sub_tree?.length ? currentItem.id : currentItem?.parentId; while (parentIndex) { const found = allItems.findRecursive( @@ -322,8 +299,7 @@ const MobilePanel = { hasLang, externalLinkIcon, // Show title of previously clicked item in Back-button (or Frontpage) - back: - i > 0 ? (this.content.at(i - 1)?.name ?? frontpageTranslation) : false, + back: i > 0 ? (this.content.at(i - 1)?.name ?? frontpageTranslation) : false, openSubMenuTranslation, openParentMenuTranslation, /** * @@ -343,8 +319,7 @@ const MobilePanel = { (state === 'up' && i >= this.currentIndex) || (state === 'down' && i > this.currentIndex + 1), 'mmenu__panel--visible-left': - (state === 'up' && i < this.currentIndex - 1) || - (state === 'down' && i <= this.currentIndex), + (state === 'up' && i < this.currentIndex - 1) || (state === 'down' && i <= this.currentIndex), }), })); }, @@ -356,18 +331,13 @@ const MobilePanel = { * Find the item corresponding to given id in item arrow click event. * It's items will be the new current panel. Old panel swipes left. */ - const next = this.content - .at(this.currentIndex) - .sub_tree.find(({ id }) => id === parentId); + const next = this.content.at(this.currentIndex).sub_tree.find(({ id }) => id === parentId); if (!next) { throw new Error(`ID mismatch in menu items${parentId}`); } - this.currentIndex = - this.currentIndex + 1 < this.size - ? this.currentIndex + 1 - : this.currentIndex; + this.currentIndex = this.currentIndex + 1 < this.size ? this.currentIndex + 1 : this.currentIndex; this.content[this.currentIndex] = next; this.render('up'); }, @@ -375,8 +345,7 @@ const MobilePanel = { if (this.currentIndex === 0) { return; } - this.currentIndex = - this.currentIndex - 1 >= 0 ? this.currentIndex - 1 : this.currentIndex; + this.currentIndex = this.currentIndex - 1 >= 0 ? this.currentIndex - 1 : this.currentIndex; this.render('down'); }, render(state) { @@ -394,31 +363,19 @@ const MobilePanel = { const panels = [...root.querySelectorAll('.mmenu__panel')]; const current = panels.at(this.currentIndex); - if ( - root.parentElement.scrollTop > this.scroll_threshold && - this.currentIndex > 0 - ) { - current - .querySelector('.mmenu__back') - .scrollIntoView({ block: 'start', behaviour: 'smooth' }); + if (root.parentElement.scrollTop > this.scroll_threshold && this.currentIndex > 0) { + current.querySelector('.mmenu__back').scrollIntoView({ block: 'start', behaviour: 'smooth' }); } setTimeout(() => { - current.classList.remove( - 'mmenu__panel--visible-right', - 'mmenu__panel--visible-left', - ); + current.classList.remove('mmenu__panel--visible-right', 'mmenu__panel--visible-left'); switch (state) { case 'up': - panels - .at(this.currentIndex - 1) - .classList.add('mmenu__panel--visible-left'); + panels.at(this.currentIndex - 1).classList.add('mmenu__panel--visible-left'); break; case 'down': - panels - .at(this.currentIndex + 1) - .classList.add('mmenu__panel--visible-right'); + panels.at(this.currentIndex + 1).classList.add('mmenu__panel--visible-right'); break; default: @@ -455,10 +412,7 @@ const MobilePanel = { return item; }); - const currentItem = allItems.findRecursive( - (item) => isCurrentPath.call(item), - 'sub_tree', - ); + const currentItem = allItems.findRecursive((item) => isCurrentPath.call(item), 'sub_tree'); if (currentItem) { currentItem.active = true; @@ -523,19 +477,13 @@ const MobilePanel = { if (classList?.contains(this.selectors.forward)) { this.up(id); - } else if ( - classList?.contains(this.selectors.back) || - parentElement?.classList?.contains(this.selectors.back) - ) { + } else if (classList?.contains(this.selectors.back) || parentElement?.classList?.contains(this.selectors.back)) { this.down(); } }); }, isOpen() { - return ( - window.location.hash === '#menu' || - this.toggleButton.getAttribute('aria-expanded') === 'true' - ); + return window.location.hash === '#menu' || this.toggleButton.getAttribute('aria-expanded') === 'true'; }, disableFallback() { this.menu.dataset.js = true; // Switch to use js-enhanced version instead of pure css version @@ -577,9 +525,7 @@ const MobilePanel = { * Compiled templates need to have reliable access to header and menu elements cloned from Server DOM. */ if (this.running) { - console.warn( - 'MobilePanel already initiated. Is it include more than once?', - ); + console.warn('MobilePanel already initiated. Is it include more than once?'); return; } this.onOpen = onOpen; @@ -591,9 +537,7 @@ const MobilePanel = { if (!this.toggleButton) { throw new Error('No toggle button for JS menu.'); } - this.dropdownInstance = document.querySelector( - `.${this.selectors.dropdown}`, - ); + this.dropdownInstance = document.querySelector(`.${this.selectors.dropdown}`); if (!this.dropdownInstance) { throw new Error('No dropdown element for JS menu.'); } diff --git a/src/js/nav-toggle/navToggleDropdown.js b/src/js/nav-toggle/navToggleDropdown.js index fc656d0c3..4dc9118a0 100644 --- a/src/js/nav-toggle/navToggleDropdown.js +++ b/src/js/nav-toggle/navToggleDropdown.js @@ -15,10 +15,7 @@ class NavToggleDropdown { } isOpen() { - return ( - window.location.hash === this.HASH_ID || - this.targetNode.dataset.target === 'true' - ); + return window.location.hash === this.HASH_ID || this.targetNode.dataset.target === 'true'; } // The simpleClose function is for events such as closing all the @@ -52,10 +49,7 @@ class NavToggleDropdown { // If the last clicked button is inside the dropdown, find another button outside of it if (this.dropdownInstance?.contains(buttonToFocus)) { - buttonToFocus = - this.buttonInstances.find( - (button) => !this.dropdownInstance.contains(button), - ) || null; + buttonToFocus = this.buttonInstances.find((button) => !this.dropdownInstance.contains(button)) || null; } // Move focus if a valid button is found @@ -107,42 +101,27 @@ class NavToggleDropdown { }); } - init({ - name, - buttonSelector, - dropdownSelector = null, - targetSelector, - onOpen, - onClose, - }) { + init({ name, buttonSelector, dropdownSelector = null, targetSelector, onOpen, onClose }) { this.name = name; this.buttonSelector = buttonSelector; - this.buttonInstances = Array.from( - document.querySelectorAll(this.buttonSelector), - ); // Get all matching buttons + this.buttonInstances = Array.from(document.querySelectorAll(this.buttonSelector)); // Get all matching buttons if (this.buttonInstances.length === 0) { this.running = false; if (this.debug) { - console.warn( - `${name} buttons missing. Looking for ${this.buttonSelector}`, - ); + console.warn(`${name} buttons missing. Looking for ${this.buttonSelector}`); } return; } if (this.running) { if (this.debug) { - console.warn( - `${name} already initiated. Is it included more than once?`, - ); + console.warn(`${name} already initiated. Is it included more than once?`); } return; } this.dropdownSelector = dropdownSelector; - this.dropdownInstance = this.dropdownSelector - ? document.querySelector(this.dropdownSelector) - : null; + this.dropdownInstance = this.dropdownSelector ? document.querySelector(this.dropdownSelector) : null; this.dropdownInstance?.classList.add('nav-toggle-dropdown--closed'); this.HASH_ID = targetSelector; this.onOpen = onOpen; @@ -151,9 +130,7 @@ class NavToggleDropdown { // Ensure the target node exists this.targetNode = document.querySelector(this.HASH_ID); if (!this.targetNode) { - throw new Error( - `${name} target node missing. Looking for ${this.HASH_ID}`, - ); + throw new Error(`${name} target node missing. Looking for ${this.HASH_ID}`); } this.targetNode.dataset.js = true; diff --git a/src/js/navToggle.js b/src/js/navToggle.js index 3e8835b94..01835c5ee 100644 --- a/src/js/navToggle.js +++ b/src/js/navToggle.js @@ -48,8 +48,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; // Checks if an element has scrollable overflow in either direction. const isScrollable = (element) => - element.scrollWidth > element.clientWidth || - element.scrollHeight > element.clientHeight; + element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight; const isMobile = () => window.matchMedia('(max-width: 992px)').matches; @@ -59,10 +58,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; // Close all open menus on click outside. const closeFromOutside = ({ target }) => { - if ( - target.closest('.desktop-menu, .header-top') || - !target.closest('.header') - ) { + if (target.closest('.desktop-menu, .header-top') || !target.closest('.header')) { // Close all open menus. keys.forEach((key) => { AllElements[key].simpleClose(); @@ -128,12 +124,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; // until element is focusable. if (key === 'SearchDropdown') { window.setTimeout( - () => - document - .querySelector( - '.header-search-wrapper input[type="search"]', - ) - ?.focus(), + () => document.querySelector('.header-search-wrapper input[type="search"]')?.focus(), 10, ); } @@ -147,11 +138,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; } if (menuWrapper) { - closeOnFocusOut( - menuWrapper, - () => dropdownInstance.simpleClose(), - key, - ); + closeOnFocusOut(menuWrapper, () => dropdownInstance.simpleClose(), key); } context.addEventListener('click', closeFromOutside); }, @@ -166,9 +153,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; keys.forEach((key) => { AllElements[key].close(); }); - const wrapper = document.getElementById( - 'nav-toggle-dropdown--menu', - ); + const wrapper = document.getElementById('nav-toggle-dropdown--menu'); if (wrapper) { closeOnFocusOut(wrapper, () => globalMenu.close()); } @@ -184,18 +169,14 @@ import { close, open } from './nav-toggle/toggleWidgets'; // Check if any menu instance is open. const isAnyMenuOpen = () => - keys.some( - (key) => AllElements[key].dataset && AllElements[key].isOpen(), - ) || globalMenu?.isOpen(); + keys.some((key) => AllElements[key].dataset && AllElements[key].isOpen()) || globalMenu?.isOpen(); // Prevent body scrolling when menus are open. const blockBrandingScroll = (e) => { // Ignore touch events. if (e.touches?.length > 1) return true; - const scrolledPanel = e.target.closest( - '.mmenu__panel--current, .nav-toggle-dropdown__content', - ); + const scrolledPanel = e.target.closest('.mmenu__panel--current, .nav-toggle-dropdown__content'); // Prevent scrolling when menu is open. const preventBodyScrolling = @@ -219,9 +200,7 @@ import { close, open } from './nav-toggle/toggleWidgets'; const body = document.querySelector('body'); body.addEventListener('wheel', blockBrandingScroll, { passive: false }); body.addEventListener('scroll', blockBrandingScroll, { passive: false }); - body.addEventListener('touchmove', blockBrandingScroll, { - passive: false, - }); + body.addEventListener('touchmove', blockBrandingScroll, { passive: false }); window.navToggleInitialized = true; }, }; diff --git a/src/js/positionDropdown.js b/src/js/positionDropdown.js index efe9fe74e..555248d37 100644 --- a/src/js/positionDropdown.js +++ b/src/js/positionDropdown.js @@ -27,8 +27,7 @@ const positionDropdown = (button, relativeElement, options = {}) => { // If the dropdown is a toast handle the css variables. if (isToast) { - const toastArrowRight = - viewportWidth - buttonRect.right - gutter + buttonWidth / 2; + const toastArrowRight = viewportWidth - buttonRect.right - gutter + buttonWidth / 2; dropDown.style.setProperty('--toast-arrow-left', 'auto'); dropDown.style.setProperty('--toast-arrow-right', `${toastArrowRight}px`); dropDown.style.setProperty('--toast-arrow-transform', '50%'); diff --git a/src/js/react/apps/district-and-project-search/components/results/ResultCard.tsx b/src/js/react/apps/district-and-project-search/components/results/ResultCard.tsx index 2c3ab0410..8f5b9d918 100644 --- a/src/js/react/apps/district-and-project-search/components/results/ResultCard.tsx +++ b/src/js/react/apps/district-and-project-search/components/results/ResultCard.tsx @@ -21,23 +21,12 @@ const ResultCard = ({ field_project_theme_name, field_district_subdistricts_title_for_ui, }: Result) => { - const linkUrl = field_project_external_website - ? field_project_external_website[0] - : `${url}`; - let imageUrl = project_image_absolute_url - ? project_image_absolute_url[0] - : ''; - imageUrl = district_image_absolute_url - ? district_image_absolute_url[0] - : imageUrl; - let imageAlt = - field_project_image_alt && field_project_image_alt?.[0] !== '""' - ? field_project_image_alt[0] - : ''; + const linkUrl = field_project_external_website ? field_project_external_website[0] : `${url}`; + let imageUrl = project_image_absolute_url ? project_image_absolute_url[0] : ''; + imageUrl = district_image_absolute_url ? district_image_absolute_url[0] : imageUrl; + let imageAlt = field_project_image_alt && field_project_image_alt?.[0] !== '""' ? field_project_image_alt[0] : ''; imageAlt = - field_district_image_alt && field_district_image_alt?.[0] !== '""' - ? field_district_image_alt[0] - : imageAlt; + field_district_image_alt && field_district_image_alt?.[0] !== '""' ? field_district_image_alt[0] : imageAlt; const getImage = () => { if (!imageUrl || !imageUrl.length || !imageUrl[0]) { @@ -68,10 +57,7 @@ const ResultCard = ({ const getVisibleTime = (dateString: string): string => { const dateObject = new Date(dateString); // en-US because the date is displayed month/year. - return dateObject.toLocaleString('en-US', { - month: '2-digit', - year: 'numeric', - }); + return dateObject.toLocaleString('en-US', { month: '2-digit', year: 'numeric' }); }; const getHtmlTime = (dateString: string): string => { @@ -94,22 +80,14 @@ const ResultCard = ({ <> {project_plan_schedule && ( - {Drupal.t( - 'planning', - {}, - { context: 'District and project search' }, - )} + {Drupal.t('planning', {}, { context: 'District and project search' })} {getTimeItem(project_plan_schedule)} )} {project_plan_schedule && project_execution_schedule && ' '} {project_execution_schedule && ( - {Drupal.t( - 'execution', - {}, - { context: 'District and project search' }, - )} + {Drupal.t('execution', {}, { context: 'District and project search' })} {getTimeItem(project_execution_schedule)} )} @@ -119,15 +97,11 @@ const ResultCard = ({ let location: string | undefined; if (field_project_district_title_for_ui) { - location = field_project_district_title_for_ui - .map((item) => item) - .join(', '); + location = field_project_district_title_for_ui.map((item) => item).join(', '); } if (field_district_subdistricts_title_for_ui) { - location = field_district_subdistricts_title_for_ui - .map((item) => item) - .join(', '); + location = field_district_subdistricts_title_for_ui.map((item) => item).join(', '); } return ( @@ -139,9 +113,7 @@ const ResultCard = ({ cardUrlExternal={!!field_project_external_website} cardCategoryTag={cardCategoryTag} location={location} - theme={field_project_theme_name - ?.map((item) => capitalize(item)) - .join(', ')} + theme={field_project_theme_name?.map((item) => capitalize(item)).join(', ')} daterange={schedule && schedule} /> ); diff --git a/src/js/react/apps/district-and-project-search/components/results/ResultsSort.tsx b/src/js/react/apps/district-and-project-search/components/results/ResultsSort.tsx index 6efc5808b..6f2dea224 100644 --- a/src/js/react/apps/district-and-project-search/components/results/ResultsSort.tsx +++ b/src/js/react/apps/district-and-project-search/components/results/ResultsSort.tsx @@ -14,9 +14,7 @@ const ResultsSort = () => { useEffect(() => { if (urlParams.sort) { - const matchedSort = sortOptions.find( - (option: OptionType) => option.value === urlParams.sort, - ); + const matchedSort = sortOptions.find((option: OptionType) => option.value === urlParams.sort); if (matchedSort) { setSort(matchedSort); @@ -36,14 +34,8 @@ const ResultsSort = () => { theme={defaultSelectTheme} style={{ minWidth: '280px' }} texts={{ - label: Drupal.t( - 'Sort search results', - {}, - { context: 'District and project search form label' }, - ), - language: getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ), + label: Drupal.t('Sort search results', {}, { context: 'District and project search form label' }), + language: getCurrentLanguage(window.drupalSettings.path.currentLanguage), }} value={[sort]} /> diff --git a/src/js/react/apps/district-and-project-search/containers/FormContainer.tsx b/src/js/react/apps/district-and-project-search/containers/FormContainer.tsx index b95466dc3..be5725df9 100644 --- a/src/js/react/apps/district-and-project-search/containers/FormContainer.tsx +++ b/src/js/react/apps/district-and-project-search/containers/FormContainer.tsx @@ -1,12 +1,4 @@ -import { - Accordion, - AccordionSize, - Button, - defaultFilter, - IconLocation, - Select, - TextInput, -} from 'hds-react'; +import { Accordion, AccordionSize, Button, defaultFilter, IconLocation, Select, TextInput } from 'hds-react'; import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import { useEffect } from 'react'; import { defaultMultiSelectTheme } from '@/react/common/constants/selectTheme'; @@ -50,18 +42,10 @@ const FormContainer = () => { // biome-ignore lint/correctness/useExhaustiveDependencies: @todo UHF-12501 useEffect(() => { setTitle(urlParams?.title?.toString() || ''); - setDistrictFilter( - transformDropdownsValues(urlParams?.districts, districtOptions), - ); - setThemeFilter( - transformDropdownsValues(urlParams?.project_theme, themeOptions), - ); - setPhaseFilter( - transformDropdownsValues(urlParams?.project_phase, phaseOptions), - ); - setTypeFilter( - transformDropdownsValues(urlParams?.project_type, typeOptions), - ); + setDistrictFilter(transformDropdownsValues(urlParams?.districts, districtOptions)); + setThemeFilter(transformDropdownsValues(urlParams?.project_theme, themeOptions)); + setPhaseFilter(transformDropdownsValues(urlParams?.project_phase, phaseOptions)); + setTypeFilter(transformDropdownsValues(urlParams?.project_type, typeOptions)); }, []); const handleSubmit = (event: React.FormEvent) => { @@ -69,30 +53,16 @@ const FormContainer = () => { setUrlParams({ title, - districts: districtSelection.map( - (selection: OptionType) => selection.value, - ), - project_theme: themeSelection.map( - (selection: OptionType) => selection.value, - ), - project_phase: phaseSelection.map( - (selection: OptionType) => selection.value, - ), - project_type: typeSelection.map( - (selection: OptionType) => selection.value, - ), + districts: districtSelection.map((selection: OptionType) => selection.value), + project_theme: themeSelection.map((selection: OptionType) => selection.value), + project_phase: phaseSelection.map((selection: OptionType) => selection.value), + project_type: typeSelection.map((selection: OptionType) => selection.value), }); }; - const handleTitleChange = ({ - target: { value }, - }: { - target: { value: string }; - }) => setTitle(value); + const handleTitleChange = ({ target: { value } }: { target: { value: string } }) => setTitle(value); const accordionInitiallyOpen = !!Object.keys(urlParams).find( - (param) => - Object.keys(ComponentMap).includes(param) && - urlParams?.[param as keyof URLParams]?.length, + (param) => Object.keys(ComponentMap).includes(param) && urlParams?.[param as keyof URLParams]?.length, ); const residentialAreaLabel: string = Drupal.t( 'Residential area', @@ -109,14 +79,8 @@ const FormContainer = () => { {}, { context: 'District and project search form label' }, ); - const projectTypeLabel: string = Drupal.t( - 'Project type', - {}, - { context: 'District and project search form label' }, - ); - const currentLanguage = getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ); + const projectTypeLabel: string = Drupal.t('Project type', {}, { context: 'District and project search form label' }); + const currentLanguage = getCurrentLanguage(window.drupalSettings.path.currentLanguage); return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 @@ -131,18 +95,10 @@ const FormContainer = () => { { context: 'District and project search form label' }, )} onChange={handleTitleChange} - placeholder={Drupal.t( - 'For example, Pasila', - {}, - { context: 'District and project search form label' }, - )} + placeholder={Drupal.t('For example, Pasila', {}, { context: 'District and project search form label' })} type='search' value={title} - clearButtonAriaLabel={Drupal.t( - 'Clear', - {}, - { context: 'React search' }, - )} + clearButtonAriaLabel={Drupal.t('Clear', {}, { context: 'React search' })} style={defaultTextInputStyle} /> { ), label: projectThemeLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All themes', - {}, - { context: 'District and project search form label' }, - ), + placeholder: Drupal.t('All themes', {}, { context: 'District and project search form label' }), }} theme={defaultMultiSelectTheme} value={themeSelection} @@ -249,11 +190,7 @@ const FormContainer = () => { ), label: projectStageLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All stages', - {}, - { context: 'District and project search form label' }, - ), + placeholder: Drupal.t('All stages', {}, { context: 'District and project search form label' }), }} theme={defaultMultiSelectTheme} value={phaseSelection} @@ -280,11 +217,7 @@ const FormContainer = () => { ), label: projectTypeLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All types', - {}, - { context: 'District and project search form label' }, - ), + placeholder: Drupal.t('All types', {}, { context: 'District and project search form label' }), }} theme={defaultMultiSelectTheme} value={typeSelection} @@ -296,11 +229,7 @@ const FormContainer = () => { className='hdbt-search--react__submit-button district-project-search-form__submit-button' type='submit' > - {Drupal.t( - 'Search', - {}, - { context: 'React search: submit button label' }, - )} + {Drupal.t('Search', {}, { context: 'React search: submit button label' })} diff --git a/src/js/react/apps/district-and-project-search/containers/ResultsContainer.tsx b/src/js/react/apps/district-and-project-search/containers/ResultsContainer.tsx index e03cd4feb..98013d2d6 100644 --- a/src/js/react/apps/district-and-project-search/containers/ResultsContainer.tsx +++ b/src/js/react/apps/district-and-project-search/containers/ResultsContainer.tsx @@ -41,22 +41,14 @@ const ResultsContainer = (): JSX.Element => { }).then((res) => res.json()); }; - const { data, error } = useSWR(queryString, fetcher, { - revalidateOnFocus: false, - }); + const { data, error } = useSWR(queryString, fetcher, { revalidateOnFocus: false }); if (!data && !error) { return ; } if (error || initializationError) { - return ( - - ); + return ; } if (!data?.hits?.hits.length) { diff --git a/src/js/react/apps/district-and-project-search/containers/SelectionsContainer.tsx b/src/js/react/apps/district-and-project-search/containers/SelectionsContainer.tsx index 9196556de..02b20d54c 100644 --- a/src/js/react/apps/district-and-project-search/containers/SelectionsContainer.tsx +++ b/src/js/react/apps/district-and-project-search/containers/SelectionsContainer.tsx @@ -49,30 +49,21 @@ const SelectionsContainer = () => { )} {showProjectThemes && ( )} {showProjectPhases && ( )} {showProjectTypes && ( @@ -101,15 +92,10 @@ const ListFilter = ({ updater, values, valueKey }: ListFilterProps) => { const removeSelection = (value: string) => { const newValue = values; - const index = newValue.findIndex( - (selection: OptionType) => selection.value === value, - ); + const index = newValue.findIndex((selection: OptionType) => selection.value === value); newValue.splice(index, 1); updater(newValue); - setUrlParams({ - ...urlParams, - [valueKey]: newValue.map((selection: OptionType) => selection.value), - }); + setUrlParams({ ...urlParams, [valueKey]: newValue.map((selection: OptionType) => selection.value) }); }; return ( diff --git a/src/js/react/apps/district-and-project-search/enum/IndexFields.ts b/src/js/react/apps/district-and-project-search/enum/IndexFields.ts index 3c774d384..822481bb3 100644 --- a/src/js/react/apps/district-and-project-search/enum/IndexFields.ts +++ b/src/js/react/apps/district-and-project-search/enum/IndexFields.ts @@ -11,8 +11,7 @@ export const IndexFields = { FIELD_PROJECT_SEARCH_METATAGS: 'field_project_search_metatags.keyword', FIELD_DISTRICT_SEARCH_METATAGS: 'field_district_search_metatags.keyword', FIELD_DISTRICT_SUBDISTRICTS_TITLE: 'field_district_subdistricts_title', - FIELD_DISTRICT_SUBDISTRICTS_TITLE_FOR_UI: - 'field_district_subdistricts_title_for_ui', + FIELD_DISTRICT_SUBDISTRICTS_TITLE_FOR_UI: 'field_district_subdistricts_title_for_ui', DISTRICTS_FOR_FILTERS_DISTRICT_TITLE: 'district_title', DISTRICTS_FOR_FILTERS_DISTRICT_TITLE_FOR_UI: 'district_title_for_ui', PROJECT_THEME_NAME: 'project_theme_name', diff --git a/src/js/react/apps/district-and-project-search/enum/Settings.ts b/src/js/react/apps/district-and-project-search/enum/Settings.ts index d503f8a1d..7560bafb2 100644 --- a/src/js/react/apps/district-and-project-search/enum/Settings.ts +++ b/src/js/react/apps/district-and-project-search/enum/Settings.ts @@ -1,6 +1,5 @@ export const Settings = { - INDEX: - 'projects,districts,districts_for_filters,project_themes,project_phases,project_types', + INDEX: 'projects,districts,districts_for_filters,project_themes,project_phases,project_types', }; export default Settings; diff --git a/src/js/react/apps/district-and-project-search/enum/SortOptions.ts b/src/js/react/apps/district-and-project-search/enum/SortOptions.ts index 200da4ffd..b67cf24c7 100644 --- a/src/js/react/apps/district-and-project-search/enum/SortOptions.ts +++ b/src/js/react/apps/district-and-project-search/enum/SortOptions.ts @@ -2,27 +2,15 @@ import type OptionType from '../types/OptionType'; const SortOptions: OptionType[] = [ { - label: Drupal.t( - 'Most relevant first', - {}, - { context: 'District and project search sort option' }, - ), + label: Drupal.t('Most relevant first', {}, { context: 'District and project search sort option' }), value: 'most_relevant', }, { - label: Drupal.t( - 'Alphabetical @AO', - { '@AO': 'A-Ö' }, - { context: 'District and project search sort option' }, - ), + label: Drupal.t('Alphabetical @AO', { '@AO': 'A-Ö' }, { context: 'District and project search sort option' }), value: 'asc', }, { - label: Drupal.t( - 'Alphabetical @OA', - { '@OA': 'Ö-A' }, - { context: 'District and project search sort option' }, - ), + label: Drupal.t('Alphabetical @OA', { '@OA': 'Ö-A' }, { context: 'District and project search sort option' }), value: 'desc', }, ]; diff --git a/src/js/react/apps/district-and-project-search/helpers/Params.ts b/src/js/react/apps/district-and-project-search/helpers/Params.ts index f806d813b..5f35e7461 100644 --- a/src/js/react/apps/district-and-project-search/helpers/Params.ts +++ b/src/js/react/apps/district-and-project-search/helpers/Params.ts @@ -1,9 +1,6 @@ import type OptionType from '../types/OptionType'; -const transformDropdownsValues = ( - paramOptions: string[] | undefined = [], - availableOptions: OptionType[] = [], -) => { +const transformDropdownsValues = (paramOptions: string[] | undefined = [], availableOptions: OptionType[] = []) => { const transformedOptions: OptionType[] = []; paramOptions.forEach((selection: string) => { diff --git a/src/js/react/apps/district-and-project-search/hooks/useAggregations.tsx b/src/js/react/apps/district-and-project-search/hooks/useAggregations.tsx index 7a23306e8..acb2f8811 100644 --- a/src/js/react/apps/district-and-project-search/hooks/useAggregations.tsx +++ b/src/js/react/apps/district-and-project-search/hooks/useAggregations.tsx @@ -4,11 +4,7 @@ import type Aggregations from '../types/Aggregations'; import type { AggregationItem, CustomAggs } from '../types/Aggregations'; import type OptionType from '../types/OptionType'; -export default function useAggregations( - aggregations: Aggregations, - indexKey: string, - filterKey: string, -) { +export default function useAggregations(aggregations: Aggregations, indexKey: string, filterKey: string) { let options: OptionType[] = []; if (aggregations?.[indexKey]?.buckets) { @@ -22,31 +18,21 @@ export default function useAggregations( }); // Combine aggs and hit count. - const aggs: CustomAggs = buckets.reduce( - (acc: any, current: AggregationItem) => { - const existingItem: any = Object.values(acc).find( - (value: any) => value.key === current.key, - ); - - if (existingItem) { - acc[current.key] = { - key: current.key, - doc_count: existingItem.doc_count + current.doc_count, - }; - return acc; - } - - acc[current.key] = current; + const aggs: CustomAggs = buckets.reduce((acc: any, current: AggregationItem) => { + const existingItem: any = Object.values(acc).find((value: any) => value.key === current.key); + + if (existingItem) { + acc[current.key] = { key: current.key, doc_count: existingItem.doc_count + current.doc_count }; return acc; - }, - [], - ); + } + + acc[current.key] = current; + return acc; + }, []); options = aggregations[filterKey].buckets.map((bucket: AggregationItem) => { let label = `${capitalize(bucket.key)} (0)`; - const match: any = Object.values(aggs).find( - (item: any) => item.key === bucket.key, - ); + const match: any = Object.values(aggs).find((item: any) => item.key === bucket.key); if (match !== undefined) { label = `${capitalize(bucket.key)} (${match.doc_count})`; diff --git a/src/js/react/apps/district-and-project-search/hooks/useLanguageQuery.ts b/src/js/react/apps/district-and-project-search/hooks/useLanguageQuery.ts index 0e01f26d8..c62ee483e 100644 --- a/src/js/react/apps/district-and-project-search/hooks/useLanguageQuery.ts +++ b/src/js/react/apps/district-and-project-search/hooks/useLanguageQuery.ts @@ -1,14 +1,5 @@ export const useLanguageQuery = () => ({ - bool: { - filter: [ - { - term: { - search_api_language: - window.drupalSettings.path.currentLanguage || 'fi', - }, - }, - ], - }, + bool: { filter: [{ term: { search_api_language: window.drupalSettings.path.currentLanguage || 'fi' } }] }, }); export default useLanguageQuery; diff --git a/src/js/react/apps/district-and-project-search/hooks/useQueryString.tsx b/src/js/react/apps/district-and-project-search/hooks/useQueryString.tsx index 87d31a3ed..f2d567b30 100644 --- a/src/js/react/apps/district-and-project-search/hooks/useQueryString.tsx +++ b/src/js/react/apps/district-and-project-search/hooks/useQueryString.tsx @@ -7,9 +7,7 @@ import type URLParams from '../types/URLParams'; const useQueryString = (urlParams: URLParams): string => { const { size } = Global; - const page = Number.isNaN(Number(urlParams.page)) - ? 1 - : Number(urlParams.page); + const page = Number.isNaN(Number(urlParams.page)) ? 1 : Number(urlParams.page); const weight: number = 2; const query: BooleanQuery = { @@ -17,21 +15,8 @@ const useQueryString = (urlParams: URLParams): string => { query: { bool: { should: [ - { - bool: { - _name: 'Match district', - should: [], - filter: { term: { _index: 'districts' } }, - }, - }, - { - bool: { - _name: 'Match Project', - should: [], - must: [], - filter: { term: { _index: 'projects' } }, - }, - }, + { bool: { _name: 'Match district', should: [], filter: { term: { _index: 'districts' } } } }, + { bool: { _name: 'Match Project', should: [], must: [], filter: { term: { _index: 'projects' } } } }, ], filter: [languageFilter, nodeFilter], }, @@ -45,26 +30,17 @@ const useQueryString = (urlParams: URLParams): string => { if ( Object.keys(urlParams).find( - (param) => - Object.keys(ComponentMap).includes(param) && - urlParams?.[param as keyof URLParams]?.length, + (param) => Object.keys(ComponentMap).includes(param) && urlParams?.[param as keyof URLParams]?.length, ) ) { const isProjectFilterSet = Object.keys(ComponentMap) - .filter( - (item: string) => - item !== 'title' && - item !== 'districts' && - item !== 'page' && - item !== 'sort', - ) + .filter((item: string) => item !== 'title' && item !== 'districts' && item !== 'page' && item !== 'sort') .find((key: string) => urlParams?.[key as keyof URLParams]?.length); const isDistrictFilterSet = urlParams?.districts?.length; const isTitleFilterSet = urlParams?.title?.length; query.function_score.min_score = - (isProjectFilterSet && isDistrictFilterSet) || - (isProjectFilterSet && isTitleFilterSet) + (isProjectFilterSet && isDistrictFilterSet) || (isProjectFilterSet && isTitleFilterSet) ? Number(300) : Number(weight + 1); @@ -73,55 +49,27 @@ const useQueryString = (urlParams: URLParams): string => { const districtWildcards: object[] = []; const projectWildcards: object[] = []; + districtWildcards.push({ wildcard: { [IndexFields.TITLE]: { value: `*${title}*`, boost: 300 } } }); districtWildcards.push({ - wildcard: { [IndexFields.TITLE]: { value: `*${title}*`, boost: 300 } }, - }); - districtWildcards.push({ - wildcard: { - [IndexFields.FIELD_DISTRICT_SUBDISTRICTS_TITLE]: { - value: `*${title}*`, - boost: 200, - }, - }, + wildcard: { [IndexFields.FIELD_DISTRICT_SUBDISTRICTS_TITLE]: { value: `*${title}*`, boost: 200 } }, }); districtWildcards.push({ - wildcard: { - [IndexFields.FIELD_DISTRICT_SEARCH_METATAGS]: { - value: `*${title}*`, - boost: 150, - }, - }, + wildcard: { [IndexFields.FIELD_DISTRICT_SEARCH_METATAGS]: { value: `*${title}*`, boost: 150 } }, }); - projectWildcards.push({ - wildcard: { - [`${IndexFields.TITLE}`]: { value: `*${title}*`, boost: 150 }, - }, - }); + projectWildcards.push({ wildcard: { [`${IndexFields.TITLE}`]: { value: `*${title}*`, boost: 150 } } }); // if project filter is also set, boost projects. projectWildcards.push({ wildcard: { - [IndexFields.FIELD_PROJECT_DISTRICT_TITLE]: { - value: `*${title}*`, - boost: isProjectFilterSet ? 3000 : 150, - }, + [IndexFields.FIELD_PROJECT_DISTRICT_TITLE]: { value: `*${title}*`, boost: isProjectFilterSet ? 3000 : 150 }, }, }); projectWildcards.push({ - wildcard: { - [IndexFields.FIELD_PROJECT_SEARCH_METATAGS]: { - value: `*${title}*`, - boost: 150, - }, - }, + wildcard: { [IndexFields.FIELD_PROJECT_SEARCH_METATAGS]: { value: `*${title}*`, boost: 150 } }, }); - query.function_score.query.bool.should[0].bool.should.push( - ...districtWildcards, - ); - query.function_score.query.bool.should[1].bool.should.push( - ...projectWildcards, - ); + query.function_score.query.bool.should[0].bool.should.push(...districtWildcards); + query.function_score.query.bool.should[1].bool.should.push(...projectWildcards); } if (urlParams?.districts?.length) { @@ -133,10 +81,7 @@ const useQueryString = (urlParams: URLParams): string => { Object.keys(districts).forEach((key: any) => { districtTerms.push({ term: { - [IndexFields.TITLE]: { - value: districts[key].toLowerCase(), - boost: isProjectFilterSet ? 150 : 1000, - }, + [IndexFields.TITLE]: { value: districts[key].toLowerCase(), boost: isProjectFilterSet ? 150 : 1000 }, }, }); // if project filter is also set, don't boost districts with subdistricts. @@ -151,10 +96,7 @@ const useQueryString = (urlParams: URLParams): string => { projectTerms.push({ term: { - [IndexFields.TITLE]: { - value: districts[key].toLowerCase(), - boost: isProjectFilterSet ? 3000 : 150, - }, + [IndexFields.TITLE]: { value: districts[key].toLowerCase(), boost: isProjectFilterSet ? 3000 : 150 }, }, }); // if project filter is also set, boost projects. @@ -168,12 +110,8 @@ const useQueryString = (urlParams: URLParams): string => { }); }); - query.function_score.query.bool.should[0].bool.should.push( - ...districtTerms, - ); - query.function_score.query.bool.should[1].bool.should.push( - ...projectTerms, - ); + query.function_score.query.bool.should[0].bool.should.push(...districtTerms); + query.function_score.query.bool.should[1].bool.should.push(...projectTerms); } if (urlParams?.project_theme?.length) { @@ -181,12 +119,7 @@ const useQueryString = (urlParams: URLParams): string => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 Object.keys(project_theme).forEach((key: any) => { query.function_score.query.bool.should[1].bool.must?.push({ - term: { - [IndexFields.FIELD_PROJECT_THEME_NAME]: { - value: project_theme[key].toLowerCase(), - boost: 10, - }, - }, + term: { [IndexFields.FIELD_PROJECT_THEME_NAME]: { value: project_theme[key].toLowerCase(), boost: 10 } }, }); }); } @@ -196,12 +129,7 @@ const useQueryString = (urlParams: URLParams): string => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 Object.keys(project_phase).forEach((key: any) => { query.function_score.query.bool.should[1].bool.must?.push({ - term: { - [IndexFields.FIELD_PROJECT_PHASE_NAME]: { - value: project_phase[key].toLowerCase(), - boost: 10, - }, - }, + term: { [IndexFields.FIELD_PROJECT_PHASE_NAME]: { value: project_phase[key].toLowerCase(), boost: 10 } }, }); }); } @@ -212,20 +140,13 @@ const useQueryString = (urlParams: URLParams): string => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 Object.keys(project_type).forEach((key: any) => { query.function_score.query.bool.should[1].bool.must?.push({ - term: { - [IndexFields.FIELD_PROJECT_TYPE_NAME]: { - value: project_type[key].toLowerCase(), - boost: 10, - }, - }, + term: { [IndexFields.FIELD_PROJECT_TYPE_NAME]: { value: project_type[key].toLowerCase(), boost: 10 } }, }); }); } } - const sort = urlParams?.sort?.length - ? sortOptions[urlParams?.sort] - : sortOptions.most_relevant; + const sort = urlParams?.sort?.length ? sortOptions[urlParams?.sort] : sortOptions.most_relevant; return JSON.stringify({ sort: [sort], size, from: size * (page - 1), query }); }; diff --git a/src/js/react/apps/district-and-project-search/query/queries.ts b/src/js/react/apps/district-and-project-search/query/queries.ts index 3b7514cd2..eeb787f6e 100644 --- a/src/js/react/apps/district-and-project-search/query/queries.ts +++ b/src/js/react/apps/district-and-project-search/query/queries.ts @@ -3,24 +3,16 @@ import IndexFields from '../enum/IndexFields'; // Filter by current language // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 export const languageFilter: any = { - term: { - [`${IndexFields.LANGUAGE}`]: - window.drupalSettings.path.currentLanguage || 'fi', - }, + term: { [`${IndexFields.LANGUAGE}`]: window.drupalSettings.path.currentLanguage || 'fi' }, }; // Filter out taxonomy terms // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 -export const nodeFilter: any = { - terms: { [IndexFields.CONTENT_TYPE]: ['project', 'district'] }, -}; +export const nodeFilter: any = { terms: { [IndexFields.CONTENT_TYPE]: ['project', 'district'] } }; // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 export const sortOptions: any = { - most_relevant: { - _score: { order: 'desc' }, - [`${IndexFields.TITLE}`]: { order: 'asc' }, - }, + most_relevant: { _score: { order: 'desc' }, [`${IndexFields.TITLE}`]: { order: 'asc' } }, asc: { [`${IndexFields.TITLE}`]: { order: 'asc' } }, desc: { [`${IndexFields.TITLE}`]: { order: 'desc' } }, }; @@ -30,77 +22,35 @@ export const AGGREGATIONS = { aggs: { // district and district title for UI [IndexFields.FIELD_PROJECT_DISTRICT_TITLE]: { - terms: { - field: `${IndexFields.FIELD_PROJECT_DISTRICT_TITLE_FOR_UI}`, - size: 500, - order: { _key: 'asc' }, - }, - }, - [IndexFields.TITLE]: { - terms: { - field: `${IndexFields.TITLE_FOR_UI}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.FIELD_PROJECT_DISTRICT_TITLE_FOR_UI}`, size: 500, order: { _key: 'asc' } }, }, + [IndexFields.TITLE]: { terms: { field: `${IndexFields.TITLE_FOR_UI}`, size: 500, order: { _key: 'asc' } } }, [IndexFields.FIELD_DISTRICT_SUBDISTRICTS_TITLE]: { - terms: { - field: `${IndexFields.FIELD_DISTRICT_SUBDISTRICTS_TITLE_FOR_UI}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.FIELD_DISTRICT_SUBDISTRICTS_TITLE_FOR_UI}`, size: 500, order: { _key: 'asc' } }, }, districts_for_filters: { - terms: { - field: `${IndexFields.DISTRICTS_FOR_FILTERS_DISTRICT_TITLE}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.DISTRICTS_FOR_FILTERS_DISTRICT_TITLE}`, size: 500, order: { _key: 'asc' } }, }, // project theme [IndexFields.FIELD_PROJECT_THEME_NAME]: { - terms: { - field: `${IndexFields.FIELD_PROJECT_THEME_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.FIELD_PROJECT_THEME_NAME}`, size: 500, order: { _key: 'asc' } }, }, project_theme_taxonomy_terms: { - terms: { - field: `${IndexFields.PROJECT_THEME_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.PROJECT_THEME_NAME}`, size: 500, order: { _key: 'asc' } }, }, // project phase [IndexFields.FIELD_PROJECT_PHASE_NAME]: { - terms: { - field: `${IndexFields.FIELD_PROJECT_PHASE_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.FIELD_PROJECT_PHASE_NAME}`, size: 500, order: { _key: 'asc' } }, }, project_phase_taxonomy_terms: { - terms: { - field: `${IndexFields.PROJECT_PHASE_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.PROJECT_PHASE_NAME}`, size: 500, order: { _key: 'asc' } }, }, // project type [IndexFields.FIELD_PROJECT_TYPE_NAME]: { - terms: { - field: `${IndexFields.FIELD_PROJECT_TYPE_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.FIELD_PROJECT_TYPE_NAME}`, size: 500, order: { _key: 'asc' } }, }, project_type_taxonomy_terms: { - terms: { - field: `${IndexFields.PROJECT_TYPE_NAME}`, - size: 500, - order: { _key: 'asc' }, - }, + terms: { field: `${IndexFields.PROJECT_TYPE_NAME}`, size: 500, order: { _key: 'asc' } }, }, }, query: { bool: { filter: [languageFilter] } }, diff --git a/src/js/react/apps/district-and-project-search/store.tsx b/src/js/react/apps/district-and-project-search/store.tsx index f6b48238f..bec50b192 100644 --- a/src/js/react/apps/district-and-project-search/store.tsx +++ b/src/js/react/apps/district-and-project-search/store.tsx @@ -27,9 +27,7 @@ const getParams = (searchParams: URLSearchParams) => { } else { const existing = params[key]; if (existing) { - params[key] = Array.isArray(existing) - ? [...existing, value] - : [existing, value]; + params[key] = Array.isArray(existing) ? [...existing, value] : [existing, value]; } else { params[key] = [value]; } @@ -41,9 +39,7 @@ const getParams = (searchParams: URLSearchParams) => { return params; }; -export const urlAtom = atom( - getParams(new URLSearchParams(window.location.search)), -); +export const urlAtom = atom(getParams(new URLSearchParams(window.location.search))); export const urlUpdateAtom = atom(null, (_get, set, values: URLParams) => { // set atom value diff --git a/src/js/react/apps/district-and-project-search/types/BooleanQuery.ts b/src/js/react/apps/district-and-project-search/types/BooleanQuery.ts index f613245dc..57c008218 100644 --- a/src/js/react/apps/district-and-project-search/types/BooleanQuery.ts +++ b/src/js/react/apps/district-and-project-search/types/BooleanQuery.ts @@ -4,12 +4,7 @@ type TermQuery = { }; type contentTypeQuery = { - bool: { - _name: string; - should: TermQuery[]; - must?: TermQuery[]; - filter: { term: { _index: string } }; - }; + bool: { _name: string; should: TermQuery[]; must?: TermQuery[]; filter: { term: { _index: string } } }; }; type BooleanQuery = { @@ -17,10 +12,7 @@ type BooleanQuery = { query: { bool: { should: contentTypeQuery[]; - filter: { - term: { search_api_language: 'fi' | 'en' | 'sv' }; - terms: { content_type: string[] }; - }[]; + filter: { term: { search_api_language: 'fi' | 'en' | 'sv' }; terms: { content_type: string[] } }[]; }; }; functions: [{ filter: { term: { content_type: string } }; weight: number }]; diff --git a/src/js/react/apps/health-station-search/components/ResultCard.tsx b/src/js/react/apps/health-station-search/components/ResultCard.tsx index ae846ba75..b45cc7e8c 100644 --- a/src/js/react/apps/health-station-search/components/ResultCard.tsx +++ b/src/js/react/apps/health-station-search/components/ResultCard.tsx @@ -23,9 +23,7 @@ const ResultCard = ({ let cardImage: CardImageType; if (imageOverride) { - cardImage = ( - - ); + cardImage = ; } else if (picture_url?.[0]) { cardImage = ; } else { @@ -38,20 +36,10 @@ const ResultCard = ({ cardTitle={title} cardUrl={url?.[0] || ''} location={address?.[0]} - locationLabel={Drupal.t( - 'Address', - {}, - { context: 'React search: location label' }, - )} + locationLabel={Drupal.t('Address', {}, { context: 'React search: location label' })} cardCategoryTag={ provided_languages.includes('sv') - ? { - tag: Drupal.t( - 'Service in Swedish', - {}, - { context: 'React search: Service in Swedish tag' }, - ), - } + ? { tag: Drupal.t('Service in Swedish', {}, { context: 'React search: Service in Swedish tag' }) } : undefined } /> diff --git a/src/js/react/apps/health-station-search/components/ResultsList.tsx b/src/js/react/apps/health-station-search/components/ResultsList.tsx index 89e85cad3..5b85c2b95 100644 --- a/src/js/react/apps/health-station-search/components/ResultsList.tsx +++ b/src/js/react/apps/health-station-search/components/ResultsList.tsx @@ -25,14 +25,7 @@ type ResultsListProps = { updatePage: Function; }; -const ResultsList = ({ - data, - error, - isLoading, - isValidating, - page, - updatePage, -}: ResultsListProps) => { +const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }: ResultsListProps) => { const [useMap, setUseMap] = useState(false); const { size } = AppSettings; const params = useAtomValue(paramsAtom); @@ -54,8 +47,7 @@ const ResultsList = ({ } const results = data.hits.hits; - const total = - address && sv_only ? data.hits.hits.length : data.hits.total.value; + const total = address && sv_only ? data.hits.hits.length : data.hits.total.value; const pages = Math.floor(total / size); const addLastPage = total > size && total % size; const showPagination = !useMap && (pages > 1 || addLastPage); @@ -95,11 +87,7 @@ const ResultsList = ({ aria-controls='hdbt-search--react__results--tabpanel' onClick={() => setUseMap(false)} > - {Drupal.t( - 'View as a list', - {}, - { context: 'React search: result display' }, - )} + {Drupal.t('View as a list', {}, { context: 'React search: result display' })} } diff --git a/src/js/react/apps/health-station-search/containers/FormContainer.tsx b/src/js/react/apps/health-station-search/containers/FormContainer.tsx index ca33a6d98..82f0b42dd 100644 --- a/src/js/react/apps/health-station-search/containers/FormContainer.tsx +++ b/src/js/react/apps/health-station-search/containers/FormContainer.tsx @@ -7,11 +7,7 @@ import type SearchParams from '../types/SearchParams'; type SubmitFormType = HTMLFormElement & { sv_only: HTMLInputElement }; -const ProximityFormContainer = ({ - initialParams, -}: { - initialParams?: SearchParams | null; -}) => { +const ProximityFormContainer = ({ initialParams }: { initialParams?: SearchParams | null }) => { const [keyword, setKeyword] = useAtom(keywordAtom); const stagedParams = useAtomValue(stagedParamsAtom); const setParams = useSetAtom(paramsAtom); @@ -33,17 +29,9 @@ const ProximityFormContainer = ({ return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
+ setKeyword(address)} onSubmit={(address: string) => setKeyword(address)} placeholder={Drupal.t( @@ -72,12 +56,7 @@ const ProximityFormContainer = ({ id='sv_only' name='sv_only' value='sv_only' - onClick={() => - setStagedParams({ - ...stagedParams, - sv_only: !stagedParams?.sv_only, - }) - } + onClick={() => setStagedParams({ ...stagedParams, sv_only: !stagedParams?.sv_only })} label={Drupal.t( 'Show the nearest service location where service is available in Swedish.', {}, @@ -88,11 +67,7 @@ const ProximityFormContainer = ({ ); diff --git a/src/js/react/apps/health-station-search/containers/ResultsContainer.tsx b/src/js/react/apps/health-station-search/containers/ResultsContainer.tsx index 4955a1f12..03548d9f2 100644 --- a/src/js/react/apps/health-station-search/containers/ResultsContainer.tsx +++ b/src/js/react/apps/health-station-search/containers/ResultsContainer.tsx @@ -14,11 +14,7 @@ const ProximityResultsContainer = () => { const { data, error, isLoading, isValidating } = UseProximityQuery(params); const { page } = params; - return ( - - ); + return ; }; export default ProximityResultsContainer; diff --git a/src/js/react/apps/health-station-search/helpers/ProximityQuery.ts b/src/js/react/apps/health-station-search/helpers/ProximityQuery.ts index ca79f4ae9..0dcfe7310 100644 --- a/src/js/react/apps/health-station-search/helpers/ProximityQuery.ts +++ b/src/js/react/apps/health-station-search/helpers/ProximityQuery.ts @@ -1,18 +1,11 @@ import type BooleanQuery from '@/types/BooleanQuery'; import AppSettings from '../enum/AppSettings'; -const getQueryString = ( - ids: number[] | null, - coordinates: number[] | null, - page: number, - svOnly?: boolean, -) => { +const getQueryString = (ids: number[] | null, coordinates: number[] | null, page: number, svOnly?: boolean) => { let { size } = AppSettings; const lang = drupalSettings.path.currentLanguage; - const query: BooleanQuery = { - bool: { filter: [{ term: { search_api_language: lang } }] }, - }; + const query: BooleanQuery = { bool: { filter: [{ term: { search_api_language: lang } }] } }; if (svOnly) { query.bool.filter?.push({ term: { provided_languages: 'sv' } }); diff --git a/src/js/react/apps/health-station-search/hooks/UseProximityQuery.ts b/src/js/react/apps/health-station-search/hooks/UseProximityQuery.ts index e95d6d8c7..900378d92 100644 --- a/src/js/react/apps/health-station-search/hooks/UseProximityQuery.ts +++ b/src/js/react/apps/health-station-search/hooks/UseProximityQuery.ts @@ -1,12 +1,7 @@ import { useAtomValue } from 'jotai'; import useSWR from 'swr'; import getNameTranslation from '@/react/common/helpers/ServiceMap'; -import { - getAddresses, - getAddressUrls, - getLocationsUrl, - parseCoordinates, -} from '@/react/common/helpers/SubQueries'; +import { getAddresses, getAddressUrls, getLocationsUrl, parseCoordinates } from '@/react/common/helpers/SubQueries'; import useTimeoutFetch from '@/react/common/hooks/useTimeoutFetch'; import AppSettings from '../enum/AppSettings'; import getQueryString from '../helpers/ProximityQuery'; @@ -34,10 +29,7 @@ const UseProximityQuery = (params: SearchParams) => { addresses = addresses.filter((_address: any) => _address.results.length); if (addresses.length) { - resolvedName = getNameTranslation( - addresses[0].results[0].name, - drupalSettings.path.currentLanguage, - ); + resolvedName = getNameTranslation(addresses[0].results[0].name, drupalSettings.path.currentLanguage); coordinates = parseCoordinates(addresses); } } @@ -48,18 +40,14 @@ const UseProximityQuery = (params: SearchParams) => { if (coordinates?.length) { const [lat, lon] = coordinates; - const locationsResponse = await fetch( - getLocationsUrl(locationsBaseUrl, lat, lon), - ); + const locationsResponse = await fetch(getLocationsUrl(locationsBaseUrl, lat, lon)); const locationsData = await locationsResponse.json(); if (!locationsData || !locationsData.results) { return null; } - ids = locationsData.results.flatMap( - (result: Result) => result.units ?? [], - ); + ids = locationsData.results.flatMap((result: Result) => result.units ?? []); } // biome-ignore lint/correctness/useHookAtTopLevel: @todo UHF-12501 @@ -78,11 +66,9 @@ const UseProximityQuery = (params: SearchParams) => { return { addressName: resolvedName, ...json }; }; - const { data, error, isLoading, isValidating } = useSWR( - `_${Object.values(params).toString()}`, - fetcher, - { revalidateOnFocus: false }, - ); + const { data, error, isLoading, isValidating } = useSWR(`_${Object.values(params).toString()}`, fetcher, { + revalidateOnFocus: false, + }); return { data, error, isLoading, isValidating }; }; diff --git a/src/js/react/apps/health-station-search/store.tsx b/src/js/react/apps/health-station-search/store.tsx index b4e727ec5..2845a1fc3 100644 --- a/src/js/react/apps/health-station-search/store.tsx +++ b/src/js/react/apps/health-station-search/store.tsx @@ -10,23 +10,18 @@ export const configurationsAtom = atom(() => { export const paramsAtom = atom({}); export const stagedParamsAtom = atom({}); -export const updateParamsAtom = atom( - null, - (_get, set, params: SearchParams) => { - const urlSearchParams: { [key: string]: string } = {}; - Object.keys(params).forEach((key: string) => { - if (key === 'query') { - return; - } +export const updateParamsAtom = atom(null, (_get, set, params: SearchParams) => { + const urlSearchParams: { [key: string]: string } = {}; + Object.keys(params).forEach((key: string) => { + if (key === 'query') { + return; + } - urlSearchParams[key as string] = String( - params[key as keyof SearchParams], - ); - }); - const query = new URLSearchParams(urlSearchParams).toString(); - set(stagedParamsAtom, { ...params, query }); - set(paramsAtom, { ...params, query }); - }, -); + urlSearchParams[key as string] = String(params[key as keyof SearchParams]); + }); + const query = new URLSearchParams(urlSearchParams).toString(); + set(stagedParamsAtom, { ...params, query }); + set(paramsAtom, { ...params, query }); +}); export const keywordAtom = atom(''); diff --git a/src/js/react/apps/health-station-search/types/SearchParams.ts b/src/js/react/apps/health-station-search/types/SearchParams.ts index 4c966d496..e153f5ef3 100644 --- a/src/js/react/apps/health-station-search/types/SearchParams.ts +++ b/src/js/react/apps/health-station-search/types/SearchParams.ts @@ -1,8 +1,3 @@ -type SearchParams = { - address?: string; - page?: number; - query?: string; - sv_only?: boolean; -}; +type SearchParams = { address?: string; page?: number; query?: string; sv_only?: boolean }; export default SearchParams; diff --git a/src/js/react/apps/job-search/components/results/ResultCard.tsx b/src/js/react/apps/job-search/components/results/ResultCard.tsx index 3c0e74cf0..44e883662 100644 --- a/src/js/react/apps/job-search/components/results/ResultCard.tsx +++ b/src/js/react/apps/job-search/components/results/ResultCard.tsx @@ -18,17 +18,13 @@ const getResultCard = ({ url, _language, }: Job) => { - const langAttribute = { - lang: _language === currentLanguage ? undefined : _language, - }; + const langAttribute = { lang: _language === currentLanguage ? undefined : _language }; const heading = title[0]; const cardTitle = ( <> {heading} - {field_jobs?.[0] > 1 && ( - {` (${field_jobs} ${Drupal.t('jobs', {}, { context: 'Job search' })})`} - )} + {field_jobs?.[0] > 1 && {` (${field_jobs} ${Drupal.t('jobs', {}, { context: 'Job search' })})`}} ); @@ -51,26 +47,16 @@ const getResultCard = ({ minute: '2-digit', }); } catch (e) { - console.warn( - `Unable to parse date for job ${field_recruitment_id?.[0]}: ${e}`, - ); + console.warn(`Unable to parse date for job ${field_recruitment_id?.[0]}: ${e}`); return undefined; } return date; }; - const orgName = - (field_organization_name && - field_organization_name.length > 0 && - field_organization_name[0]) || - ''; - const employmentTags = Array.isArray(field_employment) - ? field_employment - : []; - const typeTags = Array.isArray(field_employment_type) - ? field_employment_type - : []; + const orgName = (field_organization_name && field_organization_name.length > 0 && field_organization_name[0]) || ''; + const employmentTags = Array.isArray(field_employment) ? field_employment : []; + const typeTags = Array.isArray(field_employment_type) ? field_employment_type : []; // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 const tags: any = employmentTags.concat(typeTags).map((tag) => ({ tag })); @@ -82,17 +68,9 @@ const getResultCard = ({ cardTitle={cardTitle} cardUrl={url?.[0]} date={getDate()} - dateLabel={Drupal.t( - 'Application period ends', - {}, - { context: 'Job search' }, - )} + dateLabel={Drupal.t('Application period ends', {}, { context: 'Job search' })} daterange={field_job_duration?.[0].toString()} - dateRangeLabel={Drupal.t( - 'Employment contract', - {}, - { context: 'Job search' }, - )} + dateRangeLabel={Drupal.t('Employment contract', {}, { context: 'Job search' })} langAttribute={langAttribute} /> ); @@ -110,11 +88,7 @@ const ResultCard = ({ job, innerHits }: ResultCardProps) => { // biome-ignore lint/correctness/useHookAtTopLevel: @todo UHF-12501 const languageFilterActive = useAtomValue(urlAtom)?.language; // If no filtering by language, prefer showing current language translation - if ( - !languageFilterActive && - innerHits.length > 1 && - !_language.includes(currentLanguage) - ) { + if (!languageFilterActive && innerHits.length > 1 && !_language.includes(currentLanguage)) { for (const hit of innerHits) { if (hit._source._language.includes(currentLanguage)) { return getResultCard(hit._source); diff --git a/src/js/react/apps/job-search/components/results/ResultsList.tsx b/src/js/react/apps/job-search/components/results/ResultsList.tsx index ff2e5c40e..493504e53 100644 --- a/src/js/react/apps/job-search/components/results/ResultsList.tsx +++ b/src/js/react/apps/job-search/components/results/ResultsList.tsx @@ -7,11 +7,7 @@ type ResultsListProps = { hits: Result[] }; const ResultsList = ({ hits }: ResultsListProps) => ( <> {hits.map((hit) => ( - + ))} ); diff --git a/src/js/react/apps/job-search/components/results/ResultsSort.tsx b/src/js/react/apps/job-search/components/results/ResultsSort.tsx index 6f7e059b6..1afc8548e 100644 --- a/src/js/react/apps/job-search/components/results/ResultsSort.tsx +++ b/src/js/react/apps/job-search/components/results/ResultsSort.tsx @@ -9,14 +9,8 @@ import type OptionType from '../../types/OptionType'; const { sortOptions } = Global; const options: OptionType[] = [ - { - label: Drupal.t('Newest first', {}, { context: 'Job search' }), - value: sortOptions.newestFirst, - }, - { - label: Drupal.t('Closing date first', {}, { context: 'Job search' }), - value: sortOptions.closing, - }, + { label: Drupal.t('Newest first', {}, { context: 'Job search' }), value: sortOptions.newestFirst }, + { label: Drupal.t('Closing date first', {}, { context: 'Job search' }), value: sortOptions.closing }, ]; const ResultsSort = () => { @@ -27,9 +21,7 @@ const ResultsSort = () => { // biome-ignore lint/correctness/useExhaustiveDependencies: @todo UHF-12501 useEffect(() => { if (urlParams.sort) { - const matchedSort = options.find( - (option: OptionType) => option.value === urlParams.sort, - ); + const matchedSort = options.find((option: OptionType) => option.value === urlParams.sort); if (matchedSort) { setSort(matchedSort); @@ -46,14 +38,8 @@ const ResultsSort = () => { }} options={options} texts={{ - label: Drupal.t( - 'Sort search results', - {}, - { context: 'HELfi Rekry job search' }, - ), - language: getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ), + label: Drupal.t('Sort search results', {}, { context: 'HELfi Rekry job search' }), + language: getCurrentLanguage(window.drupalSettings.path.currentLanguage), }} value={[sort]} theme={defaultSelectTheme} diff --git a/src/js/react/apps/job-search/containers/FormContainer.tsx b/src/js/react/apps/job-search/containers/FormContainer.tsx index 5d3fc93d5..8a35932e4 100644 --- a/src/js/react/apps/job-search/containers/FormContainer.tsx +++ b/src/js/react/apps/job-search/containers/FormContainer.tsx @@ -3,19 +3,14 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import type React from 'react'; import { useEffect } from 'react'; import { defaultCheckboxStyle } from '@/react/common/constants/checkboxStyle'; -import { - defaultMultiSelectTheme, - defaultSelectTheme, -} from '@/react/common/constants/selectTheme'; +import { defaultMultiSelectTheme, defaultSelectTheme } from '@/react/common/constants/selectTheme'; import { defaultTextInputStyle } from '@/react/common/constants/textInputStyle'; import bucketToMap from '@/react/common/helpers/Aggregations'; import { getCurrentLanguage } from '@/react/common/helpers/GetCurrentLanguage'; import CustomIds from '../enum/CustomTermIds'; import SearchComponents from '../enum/SearchComponents'; import { getInitialLanguage } from '../helpers/Language'; -import transformDropdownsValues, { - paramsFromSelections, -} from '../helpers/Params'; +import transformDropdownsValues, { paramsFromSelections } from '../helpers/Params'; import { areaFilterAtom, areaFilterSelectionAtom, @@ -39,8 +34,7 @@ import type OptionType from '../types/OptionType'; import SelectionsContainer from './SelectionsContainer'; const FormContainer = () => { - const formAction = - drupalSettings?.helfi_rekry_job_search?.results_page_path || ''; + const formAction = drupalSettings?.helfi_rekry_job_search?.results_page_path || ''; const [continuous, setContinuous] = useAtom(continuousAtom); const [internship, setInternship] = useAtom(internshipAtom); const [summerJobs, setSummerJobs] = useAtom(summerJobsAtom); @@ -48,14 +42,10 @@ const FormContainer = () => { const [keyword, setKeyword] = useAtom(keywordAtom); const urlParams = useAtomValue(urlAtom); const setUrlParams = useSetAtom(urlUpdateAtom); - const [taskAreaSelection, setTaskAreaFilter] = useAtom( - taskAreasSelectionAtom, - ); + const [taskAreaSelection, setTaskAreaFilter] = useAtom(taskAreasSelectionAtom); const taskAreasOptions = useAtomValue(taskAreasAtom); const employmentOptions = useAtomValue(employmentAtom); - const [employmentSelection, setEmploymentFilter] = useAtom( - employmentSelectionAtom, - ); + const [employmentSelection, setEmploymentFilter] = useAtom(employmentSelectionAtom); const languagesOptions = useAtomValue(languagesAtom); const [languageSelection, setLanguageFilter] = useAtom(languageSelectionAtom); const { employmentSearchIds } = useAtomValue(configurationsAtom); @@ -68,23 +58,14 @@ const FormContainer = () => { // biome-ignore lint/correctness/useExhaustiveDependencies: @todo UHF-12501 useEffect(() => { setKeyword(urlParams?.keyword?.toString() || ''); - setAreaFilter( - transformDropdownsValues(urlParams?.area_filter, areaFilterOptions), - ); - setTaskAreaFilter( - transformDropdownsValues(urlParams?.task_areas, taskAreasOptions), - ); - setEmploymentFilter( - transformDropdownsValues(urlParams?.employment, employmentOptions), - ); + setAreaFilter(transformDropdownsValues(urlParams?.area_filter, areaFilterOptions)); + setTaskAreaFilter(transformDropdownsValues(urlParams?.task_areas, taskAreasOptions)); + setEmploymentFilter(transformDropdownsValues(urlParams?.employment, employmentOptions)); setContinuous(!!urlParams?.continuous); setInternship(!!urlParams?.internship); setSummerJobs(!!urlParams?.summer_jobs); setYouthSummerJobs(!!urlParams?.youth_summer_jobs); - const initialLanguage: OptionType | undefined = getInitialLanguage( - urlParams?.language, - languagesOptions, - ); + const initialLanguage: OptionType | undefined = getInitialLanguage(urlParams?.language, languagesOptions); if (initialLanguage) { setLanguageFilter([initialLanguage]); @@ -95,9 +76,7 @@ const FormContainer = () => { event.preventDefault(); const selections = { - area_filter: areaFilterSelection.map( - (selection: OptionType) => selection.value, - ), + area_filter: areaFilterSelection.map((selection: OptionType) => selection.value), employment: employmentSelection.reduce( // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 (acc: any, curr: any) => acc.concat(curr.value), @@ -107,9 +86,7 @@ const FormContainer = () => { language: languageSelection?.[0]?.value || undefined, continuous, internship, - task_areas: taskAreaSelection.map( - (selection: OptionType) => selection.value, - ), + task_areas: taskAreaSelection.map((selection: OptionType) => selection.value), summer_jobs: summerJobs, youth_summer_jobs: youthSummerJobs, }; @@ -122,9 +99,7 @@ const FormContainer = () => { } setUrlParams({ - area_filter: areaFilterSelection.map( - (selection: OptionType) => selection.value, - ), + area_filter: areaFilterSelection.map((selection: OptionType) => selection.value), employment: employmentSelection.reduce( // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 (acc: any, curr: any) => acc.concat(curr.value), @@ -134,65 +109,34 @@ const FormContainer = () => { language: languageSelection?.[0]?.value || undefined, continuous, internship, - task_areas: taskAreaSelection.map( - (selection: OptionType) => selection.value, - ), + task_areas: taskAreaSelection.map((selection: OptionType) => selection.value), summer_jobs: summerJobs, youth_summer_jobs: youthSummerJobs, }); setSubmitted(false); }; - const handleKeywordChange = ({ - target: { value }, - }: { - target: { value: string }; - }) => setKeyword(value.replace(/\s+/g, ' ')); + const handleKeywordChange = ({ target: { value } }: { target: { value: string } }) => + setKeyword(value.replace(/\s+/g, ' ')); - const isFullSearch = - !drupalSettings?.helfi_rekry_job_search?.results_page_path; + const isFullSearch = !drupalSettings?.helfi_rekry_job_search?.results_page_path; const showContinuous = employmentSearchIdMap.get(CustomIds.CONTINUOUS); const showInternships = employmentSearchIdMap.get(CustomIds.TRAINING); const showSummerJobs = employmentSearchIdMap.get(CustomIds.SUMMER_JOBS); const showYouthSummerJobs = - employmentSearchIdMap.get(CustomIds.YOUTH_SUMMER_JOBS) || - employmentSearchIdMap.get(CustomIds.COOL_SUMMER_PROJECT); - const showCheckboxes = - showContinuous || showInternships || showSummerJobs || showYouthSummerJobs; + employmentSearchIdMap.get(CustomIds.YOUTH_SUMMER_JOBS) || employmentSearchIdMap.get(CustomIds.COOL_SUMMER_PROJECT); + const showCheckboxes = showContinuous || showInternships || showSummerJobs || showYouthSummerJobs; - const areaFilterLabel: string = Drupal.t( - 'Job location', - {}, - { context: 'Job search: Job location label' }, - ); - const taskAreasLabel: string = Drupal.t( - 'Task area', - {}, - { context: 'Task areas filter label' }, - ); - const employmentRelationshipLabel: string = Drupal.t( - 'Employment type', - {}, - { context: 'Employment filter label' }, - ); - const languageLabel: string = Drupal.t( - 'Language', - {}, - { context: 'Language filter label' }, - ); - const currentLanguage = getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ); + const areaFilterLabel: string = Drupal.t('Job location', {}, { context: 'Job search: Job location label' }); + const taskAreasLabel: string = Drupal.t('Task area', {}, { context: 'Task areas filter label' }); + const employmentRelationshipLabel: string = Drupal.t('Employment type', {}, { context: 'Employment filter label' }); + const languageLabel: string = Drupal.t('Language', {}, { context: 'Language filter label' }); + const currentLanguage = getCurrentLanguage(window.drupalSettings.path.currentLanguage); return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
+ { )} type='search' value={keyword} - clearButtonAriaLabel={Drupal.t( - 'Clear', - {}, - { context: 'React search' }, - )} + clearButtonAriaLabel={Drupal.t('Clear', {}, { context: 'React search' })} style={defaultTextInputStyle} />
@@ -239,11 +179,7 @@ const FormContainer = () => { ), label: taskAreasLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All fields', - {}, - { context: 'Task areas filter placeholder' }, - ), + placeholder: Drupal.t('All fields', {}, { context: 'Task areas filter placeholder' }), }} value={taskAreaSelection} theme={defaultMultiSelectTheme} @@ -256,9 +192,7 @@ const FormContainer = () => { id={SearchComponents.EMPLOYMENT_RELATIONSHIP} multiSelect noTags - onChange={(selectedOptions) => - setEmploymentFilter(selectedOptions) - } + onChange={(selectedOptions) => setEmploymentFilter(selectedOptions)} options={employmentOptions} texts={{ clearButtonAriaLabel_one: Drupal.t( @@ -273,11 +207,7 @@ const FormContainer = () => { ), label: employmentRelationshipLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All types of employment', - {}, - { context: 'Employment filter placeholder' }, - ), + placeholder: Drupal.t('All types of employment', {}, { context: 'Employment filter placeholder' }), }} value={employmentSelection} theme={defaultMultiSelectTheme} @@ -311,11 +241,7 @@ const FormContainer = () => { ), label: languageLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All languages', - {}, - { context: 'Language placeholder' }, - ), + placeholder: Drupal.t('All languages', {}, { context: 'Language placeholder' }), }} value={languageSelection} theme={defaultSelectTheme} @@ -346,11 +272,7 @@ const FormContainer = () => { ), label: areaFilterLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All areas', - {}, - { context: 'Location placeholder' }, - ), + placeholder: Drupal.t('All areas', {}, { context: 'Location placeholder' }), }} theme={defaultMultiSelectTheme} /> @@ -368,11 +290,7 @@ const FormContainer = () => { checked={continuous} className='job-search-form__checkbox' id={SearchComponents.CONTINUOUS} - label={Drupal.t( - 'Open-ended vacancies', - {}, - { context: 'Job search' }, - )} + label={Drupal.t('Open-ended vacancies', {}, { context: 'Job search' })} name={SearchComponents.CONTINUOUS} onClick={() => setContinuous(!continuous)} value={continuous.toString()} @@ -384,11 +302,7 @@ const FormContainer = () => { checked={internship} className='job-search-form__checkbox' id={SearchComponents.INTERNSHIPS} - label={Drupal.t( - 'Practical training', - {}, - { context: 'Job search' }, - )} + label={Drupal.t('Practical training', {}, { context: 'Job search' })} name={SearchComponents.INTERNSHIPS} onClick={() => setInternship(!internship)} value={internship.toString()} @@ -412,11 +326,7 @@ const FormContainer = () => { checked={youthSummerJobs} className='job-search-form__checkbox' id={SearchComponents.YOUTH_SUMMER_JOBS} - label={Drupal.t( - 'Summer jobs for young people', - {}, - { context: 'Job search' }, - )} + label={Drupal.t('Summer jobs for young people', {}, { context: 'Job search' })} name={SearchComponents.YOUTH_SUMMER_JOBS} onClick={() => setYouthSummerJobs(!youthSummerJobs)} value={youthSummerJobs.toString()} @@ -425,15 +335,8 @@ const FormContainer = () => { )} )} - diff --git a/src/js/react/apps/job-search/containers/ResultsContainer.tsx b/src/js/react/apps/job-search/containers/ResultsContainer.tsx index 3ec840bbe..b1787ad68 100644 --- a/src/js/react/apps/job-search/containers/ResultsContainer.tsx +++ b/src/js/react/apps/job-search/containers/ResultsContainer.tsx @@ -25,11 +25,7 @@ const ResultsContainer = () => { const scrollTarget = createRef(); const { query, promoted, handleResults } = useResultsQuery(urlParams); - const { data, error, isLoading, isValidating } = useIndexQuery({ - keepPreviousData: true, - query, - multi: promoted, - }); + const { data, error, isLoading, isValidating } = useIndexQuery({ keepPreviousData: true, query, multi: promoted }); // Scroll to results when they change. const choices = Boolean(Object.keys(urlParams).length); @@ -61,12 +57,7 @@ const ResultsContainer = () => { const { results, jobs, total } = handleResults(data || {}); if (total <= 0) { - return ( - - ); + return ; } const pages = Math.ceil(total / size); @@ -103,27 +94,16 @@ const ResultsContainer = () => { ref={scrollTarget} /> - {pages > 1 && ( - - )} + {pages > 1 && } ); }; return ( <> - {drupalSettings?.helfi_react_search?.hakuvahti_url_set && ( - - )} + {drupalSettings?.helfi_react_search?.hakuvahti_url_set && }
- - {getResults()} - + {getResults()}
); diff --git a/src/js/react/apps/job-search/containers/SearchContainer.tsx b/src/js/react/apps/job-search/containers/SearchContainer.tsx index 25bcef819..c06b52214 100644 --- a/src/js/react/apps/job-search/containers/SearchContainer.tsx +++ b/src/js/react/apps/job-search/containers/SearchContainer.tsx @@ -10,9 +10,7 @@ const SearchContainer = () => ( {/* For async atoms that need to load option values from elastic */} }> - {!drupalSettings?.helfi_rekry_job_search?.results_page_path && ( - - )} + {!drupalSettings?.helfi_rekry_job_search?.results_page_path && }
); diff --git a/src/js/react/apps/job-search/containers/SearchMonitorContainer.tsx b/src/js/react/apps/job-search/containers/SearchMonitorContainer.tsx index 33da5c34b..e093aad29 100644 --- a/src/js/react/apps/job-search/containers/SearchMonitorContainer.tsx +++ b/src/js/react/apps/job-search/containers/SearchMonitorContainer.tsx @@ -56,30 +56,20 @@ const SearchMonitorContainer = () => { lang: window.drupalSettings.path.currentLanguage || 'fi', }; - const onSubmit = async ( - event: React.FormEvent, - ): Promise => { + const onSubmit = async (event: React.FormEvent): Promise => { event.preventDefault(); // Validate stuff to submit form if (!termsAgreed) { seterrorMessage( - Drupal.t( - 'The choice is mandatory: Terms of service', - {}, - { context: 'Search monitor error terms' }, - ), + Drupal.t('The choice is mandatory: Terms of service', {}, { context: 'Search monitor error terms' }), ); return; } if (!email) { seterrorMessage( - Drupal.t( - 'This field is mandatory: Email address', - {}, - { context: 'Search monitor error email' }, - ), + Drupal.t('This field is mandatory: Email address', {}, { context: 'Search monitor error email' }), ); return; } @@ -98,9 +88,7 @@ const SearchMonitorContainer = () => { } // Make submit button disabled after submitting to prevent double submits - const submitButton = document.getElementById( - 'job-search-form__search-monitor__submit-button', - ); + const submitButton = document.getElementById('job-search-form__search-monitor__submit-button'); if (submitButton) { submitButton.setAttribute('disabled', 'true'); } @@ -149,11 +137,7 @@ const SearchMonitorContainer = () => { if (!response.ok) { console.warn(response.statusText); seterrorMessage( - Drupal.t( - 'Saving search failed. Please try again.', - {}, - { context: 'Search monitor error submitting' }, - ), + Drupal.t('Saving search failed. Please try again.', {}, { context: 'Search monitor error submitting' }), ); if (submitButton) { submitButton.removeAttribute('disabled'); @@ -185,26 +169,10 @@ const SearchMonitorContainer = () => { } }, [shouldScroll, setShouldScroll]); - const formHeader: string = Drupal.t( - 'Receive search results by email', - {}, - { context: 'Search monitor header' }, - ); - const openLabel: string = Drupal.t( - 'Open the order form', - {}, - { context: 'Search monitor open label' }, - ); - const closeLabel: string = Drupal.t( - 'Close the order form', - {}, - { context: 'Search monitor close label' }, - ); - const descriptionHeader: string = Drupal.t( - 'Saved search', - {}, - { context: 'Search monitor content title' }, - ); + const formHeader: string = Drupal.t('Receive search results by email', {}, { context: 'Search monitor header' }); + const openLabel: string = Drupal.t('Open the order form', {}, { context: 'Search monitor open label' }); + const closeLabel: string = Drupal.t('Close the order form', {}, { context: 'Search monitor close label' }); + const descriptionHeader: string = Drupal.t('Saved search', {}, { context: 'Search monitor content title' }); const descriptionFirstPart: string = Drupal.t( 'To receive job alerts, carry out the search desired and then save your search. This will allow you to receive email notifications about any new matches.', {}, @@ -215,16 +183,8 @@ const SearchMonitorContainer = () => { {}, { context: 'Search monitor content' }, ); - const emailLabel: string = Drupal.t( - 'Email address', - {}, - { context: 'Search monitor email label' }, - ); - const buttonLabel: string = Drupal.t( - 'Save your search', - {}, - { context: 'Search monitor submit button label' }, - ); + const emailLabel: string = Drupal.t('Email address', {}, { context: 'Search monitor email label' }); + const buttonLabel: string = Drupal.t('Save your search', {}, { context: 'Search monitor submit button label' }); const thankYouHeader: string = Drupal.t( 'Your search has been saved', {}, @@ -235,33 +195,21 @@ const SearchMonitorContainer = () => { {}, { context: 'Search monitor thank you message' }, ); - const errorLabel: string = Drupal.t( - 'Please check these selections', - {}, - { context: 'Search monitor error label' }, - ); - const tosCheckboxLabel: string = - window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_checkbox_label; - const tosLinkLabel: string = - window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_text; - const tosLinkUrl: string = - window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_url; + const errorLabel: string = Drupal.t('Please check these selections', {}, { context: 'Search monitor error label' }); + const tosCheckboxLabel: string = window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_checkbox_label; + const tosLinkLabel: string = window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_text; + const tosLinkUrl: string = window.drupalSettings.helfi_rekry_job_search.hakuvahti_tos_link_url; const tosLinkSuffix: string = Drupal.t( 'The link opens in a new tab', {}, - { - context: - 'Explanation for users that the link opens in a new tab instead of the expected current tab', - }, + { context: 'Explanation for users that the link opens in a new tab instead of the expected current tab' }, ); return (
{!submitted && ( <> -

- {formHeader} -

+

{formHeader}

); diff --git a/src/js/react/apps/linkedevents/components/TargetGroupFilter.tsx b/src/js/react/apps/linkedevents/components/TargetGroupFilter.tsx index 832ef873a..f37930022 100644 --- a/src/js/react/apps/linkedevents/components/TargetGroupFilter.tsx +++ b/src/js/react/apps/linkedevents/components/TargetGroupFilter.tsx @@ -22,11 +22,7 @@ export const TargetGroupFilter = () => { .map(([label, _value]) => ({ label, value: label })) .sort((a, b) => a.label.localeCompare(b.label)); - const selectLabel = Drupal.t( - 'Target group', - {}, - { context: 'Event search: target group label' }, - ); + const selectLabel = Drupal.t('Target group', {}, { context: 'Event search: target group label' }); return (
@@ -49,14 +45,8 @@ export const TargetGroupFilter = () => { { context: 'React search clear selection label' }, ), label: selectLabel, - language: getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ), - placeholder: Drupal.t( - 'All target groups', - {}, - { context: 'Event search: target group placeholder' }, - ), + language: getCurrentLanguage(window.drupalSettings.path.currentLanguage), + placeholder: Drupal.t('All target groups', {}, { context: 'Event search: target group placeholder' }), }} theme={defaultSelectTheme} value={targetGroupSelection} diff --git a/src/js/react/apps/linkedevents/components/TopicsFilter.tsx b/src/js/react/apps/linkedevents/components/TopicsFilter.tsx index 9a57da877..da402e04b 100644 --- a/src/js/react/apps/linkedevents/components/TopicsFilter.tsx +++ b/src/js/react/apps/linkedevents/components/TopicsFilter.tsx @@ -25,11 +25,7 @@ function TopicsFilter() { }); }; - const selectLabel: string = Drupal.t( - 'Topic', - {}, - { context: 'React search: topics filter' }, - ); + const selectLabel: string = Drupal.t('Topic', {}, { context: 'React search: topics filter' }); const storage = useSelectStorage({ id: SearchComponents.TOPICS, @@ -40,11 +36,7 @@ function TopicsFilter() { texts: { label: selectLabel, language: getCurrentLanguage(window.drupalSettings.path.currentLanguage), - placeholder: Drupal.t( - 'All topics', - {}, - { context: 'React search: topics filter' }, - ), + placeholder: Drupal.t('All topics', {}, { context: 'React search: topics filter' }), }, theme: defaultSelectTheme, }); @@ -55,10 +47,7 @@ function TopicsFilter() { const updateSelections = () => { storage.updateAllOptions((option, _group, _groupindex) => { - if ( - option.selected && - !topicSelection.some((selection) => selection.value === option.value) - ) { + if (option.selected && !topicSelection.some((selection) => selection.value === option.value)) { return { ...option, selected: false }; } return option; @@ -67,17 +56,11 @@ function TopicsFilter() { }; useEffect(() => { - window.addEventListener( - `eventsearch-clear-${SearchComponents.TOPICS}`, - updateSelections, - ); + window.addEventListener(`eventsearch-clear-${SearchComponents.TOPICS}`, updateSelections); return () => { window.addEventListener('eventsearch-clear', clearAllSelections); - window.removeEventListener( - `eventsearch-clear-${SearchComponents.TOPICS}`, - updateSelections, - ); + window.removeEventListener(`eventsearch-clear-${SearchComponents.TOPICS}`, updateSelections); }; }); diff --git a/src/js/react/apps/linkedevents/containers/FormContainer.tsx b/src/js/react/apps/linkedevents/containers/FormContainer.tsx index 8646494c1..341b654dd 100644 --- a/src/js/react/apps/linkedevents/containers/FormContainer.tsx +++ b/src/js/react/apps/linkedevents/containers/FormContainer.tsx @@ -55,27 +55,11 @@ function FormContainer() { }; const bothCheckboxes = showFreeFilter && showRemoteFilter; - const showOnlyLabel = Drupal.t( - 'Show only', - {}, - { context: 'Events search: event type prefix' }, - ); - const freeTranslation = Drupal.t( - 'Free-of-charge', - {}, - { context: 'Events search: free filter label' }, - ); - const remoteTranslation = Drupal.t( - 'Remote participation', - {}, - { context: 'Events search: remote filter label' }, - ); - const freeLabel = bothCheckboxes - ? freeTranslation - : `${showOnlyLabel} ${freeTranslation.toLowerCase()}`; - const remoteLabel = bothCheckboxes - ? remoteTranslation - : `${showOnlyLabel} ${remoteTranslation.toLowerCase()}`; + const showOnlyLabel = Drupal.t('Show only', {}, { context: 'Events search: event type prefix' }); + const freeTranslation = Drupal.t('Free-of-charge', {}, { context: 'Events search: free filter label' }); + const remoteTranslation = Drupal.t('Remote participation', {}, { context: 'Events search: remote filter label' }); + const freeLabel = bothCheckboxes ? freeTranslation : `${showOnlyLabel} ${freeTranslation.toLowerCase()}`; + const remoteLabel = bothCheckboxes ? remoteTranslation : `${showOnlyLabel} ${remoteTranslation.toLowerCase()}`; const showForm = showLocation || @@ -93,25 +77,13 @@ function FormContainer() { let heading = ''; switch (eventListType) { case 'events': - heading = Drupal.t( - 'Filter events', - {}, - { context: 'Events search: search form title' }, - ); + heading = Drupal.t('Filter events', {}, { context: 'Events search: search form title' }); break; case 'hobbies': - heading = Drupal.t( - 'Filter hobbies', - {}, - { context: 'Events search: search form title' }, - ); + heading = Drupal.t('Filter hobbies', {}, { context: 'Events search: search form title' }); break; case 'events_and_hobbies': - heading = Drupal.t( - 'Filter events and hobbies', - {}, - { context: 'Events search: search form title' }, - ); + heading = Drupal.t('Filter events and hobbies', {}, { context: 'Events search: search form title' }); break; default: break; @@ -119,36 +91,18 @@ function FormContainer() { return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 - - {!hideHeading && ( - {heading} - )} + + {!hideHeading && {heading}}
{useLocationSearch && ( updateAddress(value)} onSubmit={(value: string) => updateAddress(value)} - placeholder={Drupal.t( - 'For example, Kotikatu 1', - {}, - { context: 'Helsinki near you events search' }, - )} + placeholder={Drupal.t('For example, Kotikatu 1', {}, { context: 'Helsinki near you events search' })} value={address || ''} visibleSuggestions={5} /> @@ -157,12 +111,7 @@ function FormContainer() { {showTopicsFilter && } {useFullTopicsFilter && } {useTargetGroupFilter && } - {showLocation && - (useFullLocationFilter ? ( - - ) : ( - - ))} + {showLocation && (useFullLocationFilter ? : )} {showTimeFilter && } {showLanguageFilter && }
@@ -170,11 +119,7 @@ function FormContainer() {
- {Drupal.t( - 'Type', - {}, - { context: 'Event search: type filter label' }, - )} + {Drupal.t('Type', {}, { context: 'Event search: type filter label' })}
@@ -183,11 +128,7 @@ function FormContainer() { {(showFreeFilter || showRemoteFilter) && (
- {bothCheckboxes && ( - - {showOnlyLabel} - - )} + {bothCheckboxes && {showOnlyLabel}} {showRemoteFilter && ( )} {showFreeFilter && ( - + )}
)} - +
diff --git a/src/js/react/apps/linkedevents/containers/ResultsContainer.tsx b/src/js/react/apps/linkedevents/containers/ResultsContainer.tsx index 889fd466f..96b845604 100644 --- a/src/js/react/apps/linkedevents/containers/ResultsContainer.tsx +++ b/src/js/react/apps/linkedevents/containers/ResultsContainer.tsx @@ -39,15 +39,10 @@ function ResultsContainer({ const url = useAtomValue(urlAtom); // Checks when user makes the first search and api url is set. const choices = Boolean(url); - const readInitialized = useAtomCallback( - useCallback((get) => get(initializedAtom), []), - ); + const readInitialized = useAtomCallback(useCallback((get) => get(initializedAtom), [])); const setInitialized = useSetAtom(initializedAtom); - useScrollToResults( - scrollTarget, - readInitialized() && choices && !loading && !validating, - ); + useScrollToResults(scrollTarget, readInitialized() && choices && !loading && !validating); useEffect(() => { if (!readInitialized() && !loading && !validating && scrollTarget.current) { @@ -85,13 +80,7 @@ function ResultsContainer({ - {Drupal.t( - 'Start by searching with your address.', - {}, - { context: 'Helsinki near you events search' }, - )} - + <>{Drupal.t('Start by searching with your address.', {}, { context: 'Helsinki near you events search' })} } ref={scrollTarget} /> @@ -121,26 +110,15 @@ function ResultsContainer({ ) : ( events.map((event) => ( - + )) )} - {!settings.hidePagination && ( - - )} + {!settings.hidePagination && } ); } - return ( - - ); + return ; }; return ( @@ -149,11 +127,7 @@ function ResultsContainer({ {seeAllNearYouLink ? ( ) : ( diff --git a/src/js/react/apps/linkedevents/containers/SearchContainer.tsx b/src/js/react/apps/linkedevents/containers/SearchContainer.tsx index 83e2b169e..c3f810385 100644 --- a/src/js/react/apps/linkedevents/containers/SearchContainer.tsx +++ b/src/js/react/apps/linkedevents/containers/SearchContainer.tsx @@ -3,20 +3,12 @@ import { useEffect, useState } from 'react'; import useSWR from 'swr'; import useTimeoutFetch from '@/react/common/hooks/useTimeoutFetch'; import ApiKeys from '../enum/ApiKeys'; -import { - loadableUrlAtom, - settingsAtom, - updateUrlAtom, - useFixturesAtom, -} from '../store'; +import { loadableUrlAtom, settingsAtom, updateUrlAtom, useFixturesAtom } from '../store'; import type Event from '../types/Event'; import FormContainer from './FormContainer'; import ResultsContainer from './ResultsContainer'; -type ResponseType = { - data: Event[]; - meta: { count: number; next?: string; previous?: string }; -}; +type ResponseType = { data: Event[]; meta: { count: number; next?: string; previous?: string } }; const SWR_REFRESH_OPTIONS = { errorRetryCount: 3, @@ -74,26 +66,21 @@ const SearchContainer = () => { }; const shouldFetch = - urlData.state === 'hasData' && - (!settings.useLocationSearch || urlData.data.includes(ApiKeys.COORDINATES)); + urlData.state === 'hasData' && (!settings.useLocationSearch || urlData.data.includes(ApiKeys.COORDINATES)); // biome-ignore lint/correctness/useHookAtTopLevel: @todo UHF-12501 - const { data, error, isLoading, isValidating } = useSWR( - shouldFetch ? urlData.data : null, - getEvents, - { - ...SWR_REFRESH_OPTIONS, - onErrorRetry(_err, _key, _config, revalidate, revalidateOpts) { - if (revalidateOpts.retryCount >= SWR_REFRESH_OPTIONS.errorRetryCount) { - setRetriesExhausted(true); - return; - } + const { data, error, isLoading, isValidating } = useSWR(shouldFetch ? urlData.data : null, getEvents, { + ...SWR_REFRESH_OPTIONS, + onErrorRetry(_err, _key, _config, revalidate, revalidateOpts) { + if (revalidateOpts.retryCount >= SWR_REFRESH_OPTIONS.errorRetryCount) { + setRetriesExhausted(true); + return; + } - revalidate({ ...revalidateOpts }); - }, - keepPreviousData: true, + revalidate({ ...revalidateOpts }); }, - ); + keepPreviousData: true, + }); return ( <> diff --git a/src/js/react/apps/linkedevents/containers/SelectionsContainer.tsx b/src/js/react/apps/linkedevents/containers/SelectionsContainer.tsx index b43cb58fc..58baf42d8 100644 --- a/src/js/react/apps/linkedevents/containers/SelectionsContainer.tsx +++ b/src/js/react/apps/linkedevents/containers/SelectionsContainer.tsx @@ -33,9 +33,7 @@ const SelectionsContainer = () => { const remoteFilter = useAtomValue(remoteFilterAtom); const startDate = useAtomValue(startDateAtom); const endDate = useAtomValue(endDateAtom); - const [locationSelection, setLocationSelection] = useAtom( - locationSelectionAtom, - ); + const [locationSelection, setLocationSelection] = useAtom(locationSelectionAtom); const [topicsSelection, setTopicsSelection] = useAtom(topicSelectionAtom); const targetGroups = useAtomValue(targetGroupsAtom); const [languageSelection, setLanguageSelection] = useAtom(languageAtom); @@ -59,11 +57,7 @@ const SelectionsContainer = () => { } return ( - + { values={languageSelection} url={urlData.data} /> - + { value={remoteFilter} /> { +const FilterBullets = ({ showClearButton, resetForm, children, url }: FilterBulletsProps) => { // SelectionWrapper hasContent doesn't work for this, we need to bind the check to // showClearButton which checks if any of the filters have values if (!showClearButton) { @@ -145,12 +126,7 @@ type ListFilterBulletsProps = { url: string | null; }; -const ListFilterBullets = ({ - updater, - values, - valueKey, - url, -}: ListFilterBulletsProps) => { +const ListFilterBullets = ({ updater, values, valueKey, url }: ListFilterBulletsProps) => { const updateParams = useSetAtom(updateParamsAtom); const updateUrl = useSetAtom(updateUrlAtom); @@ -160,9 +136,7 @@ const ListFilterBullets = ({ const removeSelection = (value: string) => { const newValue = values; - const index = newValue.findIndex( - (selection: OptionType) => selection.value === value, - ); + const index = newValue.findIndex((selection: OptionType) => selection.value === value); newValue.splice(index, 1); updater(newValue); // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 @@ -195,13 +169,7 @@ type CheckboxFilterBulletProps = { value: boolean; }; -const CheckboxFilterBullet = ({ - atom, - valueKey, - label, - url, - value, -}: CheckboxFilterBulletProps) => { +const CheckboxFilterBullet = ({ atom, valueKey, label, url, value }: CheckboxFilterBulletProps) => { const setValue = useSetAtom(atom); const resetParam = useSetAtom(resetParamAtom); const updateUrl = useSetAtom(updateUrlAtom); @@ -222,11 +190,7 @@ const CheckboxFilterBullet = ({ ); }; -type DateFilterBulletProps = { - startDate: DateTime | undefined; - endDate: DateTime | undefined; - url: string | null; -}; +type DateFilterBulletProps = { startDate: DateTime | undefined; endDate: DateTime | undefined; url: string | null }; const TypeFilterBullets = ({ eventTypeSelection, @@ -248,24 +212,16 @@ const TypeFilterBullets = ({ {eventTypeSelection.map((selection: EventTypeOption) => ( { - const value = eventTypeSelection.filter( - (type) => type !== selection, - ); + const value = eventTypeSelection.filter((type) => type !== selection); setEventTypeSelection(value); - updateParams({ - [ApiKeys.EVENT_TYPE]: typeSelectionsToString(value), - }); + updateParams({ [ApiKeys.EVENT_TYPE]: typeSelectionsToString(value) }); updateUrl(); }} key={selection} value={ selection === 'General' ? Drupal.t('Events', {}, { context: 'Event search: events type' }) - : Drupal.t( - 'Hobbies', - {}, - { context: 'Event search: hobbies type' }, - ) + : Drupal.t('Hobbies', {}, { context: 'Event search: hobbies type' }) } /> ))} @@ -273,11 +229,7 @@ const TypeFilterBullets = ({ ); }; -const DateFilterBullet = ({ - startDate, - endDate, - url, -}: DateFilterBulletProps) => { +const DateFilterBullet = ({ startDate, endDate, url }: DateFilterBulletProps) => { const setStartDate = useSetAtom(startDateAtom); const setEndDate = useSetAtom(endDateAtom); const resetParam = useSetAtom(resetParamAtom); @@ -301,13 +253,7 @@ const DateFilterBullet = ({ ); }; -const TargetGroupsBullets = ({ - targetGroups, - url, -}: { - targetGroups: OptionType[]; - url: string | null; -}) => { +const TargetGroupsBullets = ({ targetGroups, url }: { targetGroups: OptionType[]; url: string | null }) => { const setTargetGroups = useSetAtom(targetGroupsAtom); const updateParams = useSetAtom(updateParamsAtom); const updateUrl = useSetAtom(updateUrlAtom); @@ -321,9 +267,7 @@ const TargetGroupsBullets = ({ {targetGroups.map((selection: OptionType) => ( { - const value = targetGroups.filter( - (targetGroup) => targetGroup.value !== selection.value, - ); + const value = targetGroups.filter((targetGroup) => targetGroup.value !== selection.value); setTargetGroups(value); updateParams(targetGroupsToParams(value)); updateUrl(); diff --git a/src/js/react/apps/linkedevents/enum/LanguageOptions.ts b/src/js/react/apps/linkedevents/enum/LanguageOptions.ts index 65718e1c2..f8a508b40 100644 --- a/src/js/react/apps/linkedevents/enum/LanguageOptions.ts +++ b/src/js/react/apps/linkedevents/enum/LanguageOptions.ts @@ -1,7 +1 @@ -export const LanguageOptions = { - ar: 'العربية', - en: 'English', - fi: 'Suomi', - sv: 'Svenska', - ru: 'Pусский', -}; +export const LanguageOptions = { ar: 'العربية', en: 'English', fi: 'Suomi', sv: 'Svenska', ru: 'Pусский' }; diff --git a/src/js/react/apps/linkedevents/enum/TargetGroups.ts b/src/js/react/apps/linkedevents/enum/TargetGroups.ts index 01e3a4d56..57bf1a035 100644 --- a/src/js/react/apps/linkedevents/enum/TargetGroups.ts +++ b/src/js/react/apps/linkedevents/enum/TargetGroups.ts @@ -24,26 +24,12 @@ export const BloatingTargetGroups = [ ]; export const TargetGroups = { - [Drupal.t( - 'Families with babies', - {}, - { context: 'Event search: target group' }, - )]: { ids: ['yso:p20513'] }, - [Drupal.t('Children', {}, { context: 'Event search: target group' })]: { - ids: ['yso:p4354'], - }, - [Drupal.t('Youth', {}, { context: 'Event search: target group' })]: { - ids: ['yso:p11617'], - }, - [Drupal.t('Adults', {}, { context: 'Event search: target group' })]: { - negateIds: BloatingTargetGroups, - }, - [Drupal.t('Seniors', {}, { context: 'Event search: target group' })]: { - ids: ['yso:p2433'], - }, - [Drupal.t('Immigrants', {}, { context: 'Event search: target group' })]: { - ids: ['yso:p6165'], - }, + [Drupal.t('Families with babies', {}, { context: 'Event search: target group' })]: { ids: ['yso:p20513'] }, + [Drupal.t('Children', {}, { context: 'Event search: target group' })]: { ids: ['yso:p4354'] }, + [Drupal.t('Youth', {}, { context: 'Event search: target group' })]: { ids: ['yso:p11617'] }, + [Drupal.t('Adults', {}, { context: 'Event search: target group' })]: { negateIds: BloatingTargetGroups }, + [Drupal.t('Seniors', {}, { context: 'Event search: target group' })]: { ids: ['yso:p2433'] }, + [Drupal.t('Immigrants', {}, { context: 'Event search: target group' })]: { ids: ['yso:p6165'] }, [Drupal.t('Unemployed', {}, { context: 'Event search: target group' })]: { ids: [ // "Unemployed" diff --git a/src/js/react/apps/linkedevents/helpers/TargetGroupsToParams.ts b/src/js/react/apps/linkedevents/helpers/TargetGroupsToParams.ts index 40dce580c..68cfc64ba 100644 --- a/src/js/react/apps/linkedevents/helpers/TargetGroupsToParams.ts +++ b/src/js/react/apps/linkedevents/helpers/TargetGroupsToParams.ts @@ -22,8 +22,6 @@ export const targetGroupsToParams = (selectedGroups: OptionType[]) => { return { [ApiKeys.KEYWORDS]: result[0].join(','), // Filter out intersecting target groups - [ApiKeys.NEGATE_KEYWORDS]: result[1] - .filter((targetGroup) => result[0].indexOf(targetGroup) === -1) - .join(','), + [ApiKeys.NEGATE_KEYWORDS]: result[1].filter((targetGroup) => result[0].indexOf(targetGroup) === -1).join(','), }; }; diff --git a/src/js/react/apps/linkedevents/store.ts b/src/js/react/apps/linkedevents/store.ts index b03efcdfa..b4cb14a33 100644 --- a/src/js/react/apps/linkedevents/store.ts +++ b/src/js/react/apps/linkedevents/store.ts @@ -32,10 +32,7 @@ const transformLocations = (locations: any = null) => { keys.forEach((id: string) => { const location = locations[id]; if (location.id && location.name && location.name[currentLanguage]) { - locationOptions.push({ - value: location.id, - label: location.name[currentLanguage], - }); + locationOptions.push({ value: location.id, label: location.name[currentLanguage] }); } }); @@ -57,8 +54,7 @@ const getInitialSettings = () => { const useFixtures = settings?.use_fixtures; const eventsApiUrl = settings?.events_api_url; const eventListTitle = settings?.field_event_list_title; - const eventsPublicUrl = - settings?.events_public_url || 'https://tapahtumat.hel.fi'; + const eventsPublicUrl = settings?.events_public_url || 'https://tapahtumat.hel.fi'; const filterSettings: FilterSettings = { eventCount: Number(settings?.field_event_count), @@ -136,9 +132,7 @@ export const initialUrlAtom = atom((get) => { return `${baseUrl}?${initialParams.toString()}`; }); -export const initialParamsAtom = atom( - (get) => get(baseAtom)?.initialParams || new URLSearchParams(), -); +export const initialParamsAtom = atom((get) => get(baseAtom)?.initialParams || new URLSearchParams()); export const locationAtom = atom((get) => get(baseAtom)?.locations || []); @@ -170,9 +164,7 @@ export const settingsAtom = atom( }, ); -export const useFixturesAtom = atom( - (get) => get(baseAtom)?.useFixtures, -); +export const useFixturesAtom = atom((get) => get(baseAtom)?.useFixtures); export const pageAtom = atom(1); @@ -188,9 +180,7 @@ const getIsoTime = (date: DateTime, key: string) => { if (!date) { return undefined; } - return key === 'start' - ? date.startOf('day').toISO() - : date.endOf('day').toISO(); + return key === 'start' ? date.startOf('day').toISO() : date.endOf('day').toISO(); }; const getDateParams = (dates: { start?: DateTime; end?: DateTime }) => { @@ -225,29 +215,23 @@ export const setEndDisabledAtom = atom(null, (get, set, disabled: boolean) => { set(endDisabledAtom, disabled); }); -export const updateDateAtom = atom( - null, - (get, set, date: DateTime | undefined, key: string) => { - const endDisabled = get(endDisabledAtom); - const dateAtom = key === 'start' ? startDateAtom : endDateAtom; - const dates = { [key]: date }; - - if (key === 'start' && endDisabled) { - dates.end = date; - } +export const updateDateAtom = atom(null, (get, set, date: DateTime | undefined, key: string) => { + const endDisabled = get(endDisabledAtom); + const dateAtom = key === 'start' ? startDateAtom : endDateAtom; + const dates = { [key]: date }; - const dateParams = getDateParams(dates); + if (key === 'start' && endDisabled) { + dates.end = date; + } - set(dateAtom, date); - set(updateParamsAtom, dateParams); - }, -); + const dateParams = getDateParams(dates); -export const formErrorsAtom = atom({ - invalidEndDate: false, - invalidStartDate: false, + set(dateAtom, date); + set(updateParamsAtom, dateParams); }); +export const formErrorsAtom = atom({ invalidEndDate: false, invalidStartDate: false }); + export const freeFilterAtom = atom(false); export const remoteFilterAtom = atom(false); @@ -280,9 +264,7 @@ export const resetFormAtom = atom(null, (get, set) => { window.dispatchEvent(clearEvent); }); -export const submittedParamsAtom = atom( - new URLSearchParams(initialSettings.initialParams), -); +export const submittedParamsAtom = atom(new URLSearchParams(initialSettings.initialParams)); export const updateUrlAtom = atom(null, async (get, set) => { const address = get(addressAtom); @@ -310,9 +292,7 @@ export const urlAtom = atom(async (get) => { export const loadableUrlAtom = loadable(urlAtom); -export const paramsAtom = atom( - new URLSearchParams(initialSettings.initialParams), -); +export const paramsAtom = atom(new URLSearchParams(initialSettings.initialParams)); export const updatePageParamAtom = atom(null, (get, set, page: number) => { const submittedParams = new URLSearchParams(get(submittedParamsAtom)); @@ -326,10 +306,7 @@ export const resetParamAtom = atom(null, (get, set, option: string) => { const params = new URLSearchParams(get(paramsAtom)); const skipParams = [ApiKeys.COORDINATES, ApiKeys.RADIUS]; - if ( - Object.values(ApiKeys).indexOf(option) !== -1 && - skipParams.indexOf(option) === -1 - ) { + if (Object.values(ApiKeys).indexOf(option) !== -1 && skipParams.indexOf(option) === -1) { const initial = initialParams.get(option); initial ? params.set(option, initial) : params.delete(option); set(paramsAtom, params); @@ -340,18 +317,14 @@ export const updateParamsAtom = atom(null, (get, set, options: Options) => { const params = new URLSearchParams(get(paramsAtom)); Object.keys(options).forEach((option: string) => { if (Object.values(ApiKeys).indexOf(option) !== -1) { - options[option] === undefined - ? params.delete(option) - : params.set(option, options[option]); + options[option] === undefined ? params.delete(option) : params.set(option, options[option]); } }); set(paramsAtom, params); }); // Strore address input. Converted to coordinates during form submit. -export const addressAtom = atom( - queryStringParams.get('address'), -); +export const addressAtom = atom(queryStringParams.get('address')); export const languageAtom = atom([]); diff --git a/src/js/react/apps/linkedevents/types/Event.ts b/src/js/react/apps/linkedevents/types/Event.ts index 3c67c441c..592cea7d7 100644 --- a/src/js/react/apps/linkedevents/types/Event.ts +++ b/src/js/react/apps/linkedevents/types/Event.ts @@ -1,22 +1,12 @@ type MultilingualString = { fi?: string; en?: string; sv?: string }; -export type EventImage = { - alt_text: string; - id: number; - name?: string; - photographer_name?: string; - url?: string; -}; +export type EventImage = { alt_text: string; id: number; name?: string; photographer_name?: string; url?: string }; export type EventKeyword = { id: string; name: MultilingualString }; type EventOffers = { info_url: MultilingualString; is_free: boolean }; -type EventLocation = { - id: string; - name?: MultilingualString; - street_address?: MultilingualString; -}; +type EventLocation = { id: string; name?: MultilingualString; street_address?: MultilingualString }; export type Event = { end_time: number; diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultCard.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultCard.tsx index 9a1f5618d..057788154 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultCard.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultCard.tsx @@ -23,9 +23,7 @@ const ResultCard = ({ let cardImage: CardImageType; if (imageOverride) { - cardImage = ( - - ); + cardImage = ; } else if (picture_url?.[0]) { cardImage = ; } else { @@ -39,20 +37,10 @@ const ResultCard = ({ cardTitle={title} cardUrl={url?.[0] || ''} location={address?.[0]} - locationLabel={Drupal.t( - 'Address', - {}, - { context: 'React search: location label' }, - )} + locationLabel={Drupal.t('Address', {}, { context: 'React search: location label' })} cardCategoryTag={ provided_languages.includes('sv') - ? { - tag: Drupal.t( - 'Service in Swedish', - {}, - { context: 'React search: Service in Swedish tag' }, - ), - } + ? { tag: Drupal.t('Service in Swedish', {}, { context: 'React search: Service in Swedish tag' }) } : undefined } /> diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultsList.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultsList.tsx index a08ca05ac..fd4c35eac 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultsList.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/components/ResultsList.tsx @@ -25,14 +25,7 @@ type ResultsListProps = { updatePage: Function; }; -const ResultsList = ({ - data, - error, - isLoading, - isValidating, - page, - updatePage, -}: ResultsListProps) => { +const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }: ResultsListProps) => { const [useMap, setUseMap] = useState(false); const { size } = AppSettings; const params = useAtomValue(paramsAtom); @@ -54,8 +47,7 @@ const ResultsList = ({ } const results = data.hits.hits; - const total = - address && sv_only ? data.hits.hits.length : data.hits.total.value; + const total = address && sv_only ? data.hits.hits.length : data.hits.total.value; const pages = Math.floor(total / size); const addLastPage = total > size && total % size; const showPagination = !useMap && (pages > 1 || addLastPage); @@ -78,10 +70,7 @@ const ResultsList = ({ '1 clinic', '@count clinics', {}, - { - context: - 'React search: Maternity and child health clinic result count', - }, + { context: 'React search: Maternity and child health clinic result count' }, )} {data?.addressName ? ` ${Drupal.t('using address', {}, { context: 'React search: Address result display' })} ${data?.addressName}` @@ -98,11 +87,7 @@ const ResultsList = ({ aria-controls='hdbt-search--react__results--tabpanel' onClick={() => setUseMap(false)} > - {Drupal.t( - 'View as a list', - {}, - { context: 'React search: result display' }, - )} + {Drupal.t('View as a list', {}, { context: 'React search: result display' })} } diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/containers/FormContainer.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/containers/FormContainer.tsx index 7c572e4b7..d0cca9696 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/containers/FormContainer.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/containers/FormContainer.tsx @@ -7,11 +7,7 @@ import type SearchParams from '../types/SearchParams'; type SubmitFormType = HTMLFormElement & { sv_only: HTMLInputElement }; -const ProximityFormContainer = ({ - initialParams, -}: { - initialParams: SearchParams | null; -}) => { +const ProximityFormContainer = ({ initialParams }: { initialParams: SearchParams | null }) => { const [keyword, setKeyword] = useAtom(keywordAtom); const stagedParams = useAtomValue(stagedParamsAtom); const setParams = useSetAtom(paramsAtom); @@ -33,18 +29,10 @@ const ProximityFormContainer = ({ return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
+ setKeyword(address)} onSubmit={(address: string) => setKeyword(address)} placeholder={Drupal.t( @@ -73,12 +57,7 @@ const ProximityFormContainer = ({ id='sv_only' name='sv_only' value='sv_only' - onClick={() => - setStagedParams({ - ...stagedParams, - sv_only: !stagedParams?.sv_only, - }) - } + onClick={() => setStagedParams({ ...stagedParams, sv_only: !stagedParams?.sv_only })} label={Drupal.t( 'Show the nearest service location where service is available in Swedish.', {}, @@ -89,11 +68,7 @@ const ProximityFormContainer = ({ ); diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/containers/ResultsContainer.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/containers/ResultsContainer.tsx index 72e0279fa..0d76bd9c7 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/containers/ResultsContainer.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/containers/ResultsContainer.tsx @@ -13,11 +13,7 @@ const ProximityResultsContainer = () => { const { data, error, isLoading, isValidating } = UseProximityQuery(params); const { page } = params; - return ( - - ); + return ; }; export default ProximityResultsContainer; diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/helpers/ProximityQuery.ts b/src/js/react/apps/maternity-and-child-health-clinic-search/helpers/ProximityQuery.ts index b74b9d142..808140efa 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/helpers/ProximityQuery.ts +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/helpers/ProximityQuery.ts @@ -1,18 +1,11 @@ import type BooleanQuery from '@/types/BooleanQuery'; import AppSettings from '../enum/AppSettings'; -const getQueryString = ( - ids: number[] | null, - coordinates: number[] | null, - page: number, - svOnly?: boolean, -) => { +const getQueryString = (ids: number[] | null, coordinates: number[] | null, page: number, svOnly?: boolean) => { let { size } = AppSettings; const lang = drupalSettings.path.currentLanguage; - const query: BooleanQuery = { - bool: { filter: [{ term: { search_api_language: lang } }] }, - }; + const query: BooleanQuery = { bool: { filter: [{ term: { search_api_language: lang } }] } }; if (svOnly) { query.bool.filter?.push({ term: { provided_languages: 'sv' } }); diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/hooks/UseProximityQuery.ts b/src/js/react/apps/maternity-and-child-health-clinic-search/hooks/UseProximityQuery.ts index 48f0339c6..92e5fd6e7 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/hooks/UseProximityQuery.ts +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/hooks/UseProximityQuery.ts @@ -1,12 +1,7 @@ import { useAtomValue } from 'jotai'; import useSWR from 'swr'; import getNameTranslation from '@/react/common/helpers/ServiceMap'; -import { - getAddresses, - getAddressUrls, - getLocationsUrl, - parseCoordinates, -} from '@/react/common/helpers/SubQueries'; +import { getAddresses, getAddressUrls, getLocationsUrl, parseCoordinates } from '@/react/common/helpers/SubQueries'; import useTimeoutFetch from '@/react/common/hooks/useTimeoutFetch'; import AppSettings from '../enum/AppSettings'; import getQueryString from '../helpers/ProximityQuery'; @@ -34,10 +29,7 @@ const UseProximityQuery = (params: SearchParams) => { addresses = addresses.filter((_address: any) => _address.results.length); if (addresses.length) { - resolvedName = getNameTranslation( - addresses[0].results[0].name, - drupalSettings.path.currentLanguage, - ); + resolvedName = getNameTranslation(addresses[0].results[0].name, drupalSettings.path.currentLanguage); coordinates = parseCoordinates(addresses); } } @@ -48,18 +40,14 @@ const UseProximityQuery = (params: SearchParams) => { if (coordinates?.length) { const [lat, lon] = coordinates; - const locationsResponse = await fetch( - getLocationsUrl(locationsBaseUrl, lat, lon), - ); + const locationsResponse = await fetch(getLocationsUrl(locationsBaseUrl, lat, lon)); const locationsData = await locationsResponse.json(); if (!locationsData || !locationsData.results) { return null; } - ids = locationsData.results.flatMap( - (result: Result) => result.units ?? [], - ); + ids = locationsData.results.flatMap((result: Result) => result.units ?? []); } // biome-ignore lint/correctness/useHookAtTopLevel: @todo UHF-12501 @@ -78,11 +66,9 @@ const UseProximityQuery = (params: SearchParams) => { return { addressName: resolvedName, ...json }; }; - const { data, error, isLoading, isValidating } = useSWR( - `_${Object.values(params).toString()}`, - fetcher, - { revalidateOnFocus: false }, - ); + const { data, error, isLoading, isValidating } = useSWR(`_${Object.values(params).toString()}`, fetcher, { + revalidateOnFocus: false, + }); return { data, error, isLoading, isValidating }; }; diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/index.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/index.tsx index 3f3707e2e..df150a752 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/index.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/index.tsx @@ -12,10 +12,7 @@ const start = () => { const rootElement: HTMLElement | null = document.getElementById(ROOT_ID); if (!rootElement) { - console.warn( - 'Root id missing for Maternity and Child Health Clinic search app', - { ROOT_ID }, - ); + console.warn('Root id missing for Maternity and Child Health Clinic search app', { ROOT_ID }); return; } diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/store.tsx b/src/js/react/apps/maternity-and-child-health-clinic-search/store.tsx index b4e727ec5..2845a1fc3 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/store.tsx +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/store.tsx @@ -10,23 +10,18 @@ export const configurationsAtom = atom(() => { export const paramsAtom = atom({}); export const stagedParamsAtom = atom({}); -export const updateParamsAtom = atom( - null, - (_get, set, params: SearchParams) => { - const urlSearchParams: { [key: string]: string } = {}; - Object.keys(params).forEach((key: string) => { - if (key === 'query') { - return; - } +export const updateParamsAtom = atom(null, (_get, set, params: SearchParams) => { + const urlSearchParams: { [key: string]: string } = {}; + Object.keys(params).forEach((key: string) => { + if (key === 'query') { + return; + } - urlSearchParams[key as string] = String( - params[key as keyof SearchParams], - ); - }); - const query = new URLSearchParams(urlSearchParams).toString(); - set(stagedParamsAtom, { ...params, query }); - set(paramsAtom, { ...params, query }); - }, -); + urlSearchParams[key as string] = String(params[key as keyof SearchParams]); + }); + const query = new URLSearchParams(urlSearchParams).toString(); + set(stagedParamsAtom, { ...params, query }); + set(paramsAtom, { ...params, query }); +}); export const keywordAtom = atom(''); diff --git a/src/js/react/apps/maternity-and-child-health-clinic-search/types/SearchParams.ts b/src/js/react/apps/maternity-and-child-health-clinic-search/types/SearchParams.ts index 4c966d496..e153f5ef3 100644 --- a/src/js/react/apps/maternity-and-child-health-clinic-search/types/SearchParams.ts +++ b/src/js/react/apps/maternity-and-child-health-clinic-search/types/SearchParams.ts @@ -1,8 +1,3 @@ -type SearchParams = { - address?: string; - page?: number; - query?: string; - sv_only?: boolean; -}; +type SearchParams = { address?: string; page?: number; query?: string; sv_only?: boolean }; export default SearchParams; diff --git a/src/js/react/apps/news-archive/components/Filter.tsx b/src/js/react/apps/news-archive/components/Filter.tsx index ef04b249a..8d9080ac9 100644 --- a/src/js/react/apps/news-archive/components/Filter.tsx +++ b/src/js/react/apps/news-archive/components/Filter.tsx @@ -6,20 +6,9 @@ import type OptionType from '@/types/OptionType'; import { stagedParamsAtom } from '../store'; import type URLParams from '../types/URLParams'; -type FilterProps = { - label: string; - options: OptionType[]; - placeholder: string; - stateKey: keyof URLParams; -}; +type FilterProps = { label: string; options: OptionType[]; placeholder: string; stateKey: keyof URLParams }; -const Filter = ({ - label, - options, - placeholder, - stateKey, - ...rest -}: FilterProps) => { +const Filter = ({ label, options, placeholder, stateKey, ...rest }: FilterProps) => { const [params, setParams] = useAtom(stagedParamsAtom); const valueIds = params?.[stateKey] || []; @@ -28,9 +17,7 @@ const Filter = ({ if (Array.isArray(valueIds)) { valueIds.forEach((id: number) => { - const option = options.find( - (valueOption: OptionType) => id.toString() === valueOption.value, - ); + const option = options.find((valueOption: OptionType) => id.toString() === valueOption.value); if (option) { values.push(option); @@ -41,16 +28,8 @@ const Filter = ({ return values; }; - const onChange = ( - selectedOptions: OptionType[], - _clickedOption?: OptionType, - ) => { - setParams({ - ...params, - [stateKey]: selectedOptions.map((option: OptionType) => - Number(option.value), - ), - }); + const onChange = (selectedOptions: OptionType[], _clickedOption?: OptionType) => { + setParams({ ...params, [stateKey]: selectedOptions.map((option: OptionType) => Number(option.value)) }); }; return ( @@ -72,9 +51,7 @@ const Filter = ({ { context: 'React search clear selection label' }, ), label, - language: getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ), + language: getCurrentLanguage(window.drupalSettings.path.currentLanguage), placeholder, }} theme={defaultMultiSelectTheme} diff --git a/src/js/react/apps/news-archive/components/RssFeedLink.tsx b/src/js/react/apps/news-archive/components/RssFeedLink.tsx index 265bbdf01..476255e8e 100644 --- a/src/js/react/apps/news-archive/components/RssFeedLink.tsx +++ b/src/js/react/apps/news-archive/components/RssFeedLink.tsx @@ -3,25 +3,17 @@ import { urlAtom } from '../store'; const RssFeedLink = () => { const params = useAtomValue(urlAtom); - const feedBaseUrl = - drupalSettings?.helfi_news_archive?.feed_base_url ?? '/news/rss'; + const feedBaseUrl = drupalSettings?.helfi_news_archive?.feed_base_url ?? '/news/rss'; const getFeedUrl = () => { - const feedUrlWithParams = window.location.search - ? feedBaseUrl + window.location.search - : feedBaseUrl; + const feedUrlWithParams = window.location.search ? feedBaseUrl + window.location.search : feedBaseUrl; - document - .getElementById('news-feed-url') - ?.setAttribute('href', feedUrlWithParams); + document.getElementById('news-feed-url')?.setAttribute('href', feedUrlWithParams); return feedUrlWithParams; }; - const choices = - params.topic?.length || - params.neighbourhoods?.length || - params.groups?.length; + const choices = params.topic?.length || params.neighbourhoods?.length || params.groups?.length; return (
@@ -38,11 +30,7 @@ const RssFeedLink = () => { {}, { context: 'News RSS feed subscribe link' }, ) - : Drupal.t( - 'Subscribe to all news as RSS feed', - {}, - { context: 'News RSS feed subscribe link' }, - )} + : Drupal.t('Subscribe to all news as RSS feed', {}, { context: 'News RSS feed subscribe link' })}
); diff --git a/src/js/react/apps/news-archive/components/SearchInput.tsx b/src/js/react/apps/news-archive/components/SearchInput.tsx index c5db46b24..4dc781ce9 100644 --- a/src/js/react/apps/news-archive/components/SearchInput.tsx +++ b/src/js/react/apps/news-archive/components/SearchInput.tsx @@ -12,14 +12,8 @@ export const SearchInput = () => { className='hdbt-search__filter hdbt-search--react__text-field' id={SearchComponents.KEYWORD} label={Drupal.t('Search term', {}, { context: 'Search keyword label' })} - onChange={(e) => - setParams({ ...params, [SearchComponents.KEYWORD]: e.target.value }) - } - placeholder={Drupal.t( - 'For example, budget proposal', - {}, - { context: 'News archive: keyword placeholder' }, - )} + onChange={(e) => setParams({ ...params, [SearchComponents.KEYWORD]: e.target.value })} + placeholder={Drupal.t('For example, budget proposal', {}, { context: 'News archive: keyword placeholder' })} type='search' value={params?.keyword || ''} style={defaultTextInputStyle} diff --git a/src/js/react/apps/news-archive/components/results/ResultCard.tsx b/src/js/react/apps/news-archive/components/results/ResultCard.tsx index e987ec80b..816d8a252 100644 --- a/src/js/react/apps/news-archive/components/results/ResultCard.tsx +++ b/src/js/react/apps/news-archive/components/results/ResultCard.tsx @@ -45,10 +45,7 @@ const ResultCard = ({ let imageUrls: ImageUrls = {}; try { - imageUrls = - typeof main_image_url?.[0] === 'string' - ? JSON.parse(main_image_url?.[0]) - : main_image_url?.[0]; + imageUrls = typeof main_image_url?.[0] === 'string' ? JSON.parse(main_image_url?.[0]) : main_image_url?.[0]; } catch (e) { console.error('Failed to parse main_image_url', e); return undefined; // Return undefined if parsing fails @@ -57,9 +54,7 @@ const ResultCard = ({ return ( ); diff --git a/src/js/react/apps/news-archive/containers/FormContainer.tsx b/src/js/react/apps/news-archive/containers/FormContainer.tsx index 4b2fe8ade..0b9ef6359 100644 --- a/src/js/react/apps/news-archive/containers/FormContainer.tsx +++ b/src/js/react/apps/news-archive/containers/FormContainer.tsx @@ -28,11 +28,7 @@ const FormContainer = () => { const stagedParams = useAtomValue(stagedParamsAtom); const setParams = useSetAtom(urlUpdateAtom); const initialQuery = useInitialQuery(); - const { data, isLoading, isValidating } = useIndexQuery({ - query: initialQuery, - multi: true, - key: 'initialdata', - }); + const { data, isLoading, isValidating } = useIndexQuery({ query: initialQuery, multi: true, key: 'initialdata' }); let topicOptions: OptionType[] = []; let neighbourhoodOptions: OptionType[] = []; @@ -42,10 +38,8 @@ const FormContainer = () => { const [topicData, neighbourhoodData, groupData] = data.responses; [ - topicData?.aggregations?.[IndexFields.FIELD_NEWS_ITEM_TAGS]?.buckets || - [], - neighbourhoodData?.aggregations?.[IndexFields.FIELD_NEWS_NEIGHBOURHOODS] - ?.buckets || [], + topicData?.aggregations?.[IndexFields.FIELD_NEWS_ITEM_TAGS]?.buckets || [], + neighbourhoodData?.aggregations?.[IndexFields.FIELD_NEWS_NEIGHBOURHOODS]?.buckets || [], groupData?.aggregations?.[IndexFields.FIELD_NEWS_GROUPS]?.buckets || [], ].forEach((sourceData, index) => { const parsedData = parseAggData(sourceData); @@ -72,40 +66,20 @@ const FormContainer = () => { }; const loading = isLoading || isValidating; - const topicLabel = Drupal.t( - 'Topics', - {}, - { context: 'News archive topics label' }, - ); - const neighbourhoodLabel = Drupal.t( - 'City districts', - {}, - { context: 'News archive neighbourhoods label' }, - ); - const groupLabel = Drupal.t( - 'Target groups', - {}, - { context: 'News archive groups label' }, - ); + const topicLabel = Drupal.t('Topics', {}, { context: 'News archive topics label' }); + const neighbourhoodLabel = Drupal.t('City districts', {}, { context: 'News archive neighbourhoods label' }); + const groupLabel = Drupal.t('Target groups', {}, { context: 'News archive groups label' }); return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
+
{topicOptions && ( )} @@ -113,11 +87,7 @@ const FormContainer = () => { )} @@ -125,11 +95,7 @@ const FormContainer = () => { )} @@ -141,18 +107,10 @@ const FormContainer = () => { type='submit' variant={ButtonVariant.Primary} > - {Drupal.t( - 'Search', - {}, - { context: 'React search: submit button label' }, - )} + {Drupal.t('Search', {}, { context: 'React search: submit button label' })}
- + ); }; diff --git a/src/js/react/apps/news-archive/containers/ResultsContainer.tsx b/src/js/react/apps/news-archive/containers/ResultsContainer.tsx index d8bcbd755..1aa57f62b 100644 --- a/src/js/react/apps/news-archive/containers/ResultsContainer.tsx +++ b/src/js/react/apps/news-archive/containers/ResultsContainer.tsx @@ -23,15 +23,11 @@ const ResultsContainer = ({ }: ResultsContainerProps): JSX.Element => { const size = drupalSettings?.helfi_news_archive?.max_results ?? Global.SIZE; const hideForm = drupalSettings?.helfi_news_archive?.hide_form ?? false; - const cardsWithBorders = - drupalSettings?.helfi_news_archive?.cardsWithBorders ?? false; + const cardsWithBorders = drupalSettings?.helfi_news_archive?.cardsWithBorders ?? false; const urlParams = useAtomValue(urlAtom); const queryString = useQueryString(urlParams); const setPage = useSetAtom(setPageAtom); - const { data, error } = useIndexQuery({ - keepPreviousData: true, - query: queryString, - }); + const { data, error } = useIndexQuery({ keepPreviousData: true, query: queryString }); const scrollTarget = createRef(); const choices = Boolean(urlParams.groups?.length) || @@ -53,23 +49,14 @@ const ResultsContainer = ({ } if (error) { - return ( - - ); + return ; } if (!results?.length) { return ; } - const updatePage = ( - e: SyntheticEvent, - newPage: number, - ) => { + const updatePage = (e: SyntheticEvent, newPage: number) => { e.preventDefault(); setPage(newPage); }; diff --git a/src/js/react/apps/news-archive/containers/SelectionsContainer.tsx b/src/js/react/apps/news-archive/containers/SelectionsContainer.tsx index e08532536..5b28dfb1f 100644 --- a/src/js/react/apps/news-archive/containers/SelectionsContainer.tsx +++ b/src/js/react/apps/news-archive/containers/SelectionsContainer.tsx @@ -5,19 +5,11 @@ import type OptionType from '@/types/OptionType'; import { urlAtom, urlUpdateAtom } from '../store'; import type URLParams from '../types/URLParams'; -type SelectionsContainerProps = { - topic?: OptionType[]; - neighbourhoods?: OptionType[]; - groups?: OptionType[]; -}; +type SelectionsContainerProps = { topic?: OptionType[]; neighbourhoods?: OptionType[]; groups?: OptionType[] }; type ParamsKey = keyof Omit; -const SelectionsContainer = ({ - topic, - neighbourhoods, - groups, -}: SelectionsContainerProps) => { +const SelectionsContainer = ({ topic, neighbourhoods, groups }: SelectionsContainerProps) => { const params = useAtomValue(urlAtom); const updateParams = useSetAtom(urlUpdateAtom); @@ -29,11 +21,7 @@ const SelectionsContainer = ({ const newParams = { ...params, page: 1 }; const index = newParams?.[key]?.indexOf(Number(option.value)); - if ( - typeof index !== 'undefined' && - !Number.isNaN(index) && - index !== -1 - ) { + if (typeof index !== 'undefined' && !Number.isNaN(index) && index !== -1) { newParams[key]?.splice(index, 1); updateParams({ ...newParams }); } @@ -46,24 +34,22 @@ const SelectionsContainer = ({ const keys: ParamsKey[] = ['topic', 'neighbourhoods', 'groups']; const passedOptions = { topic, neighbourhoods, groups }; - [params.topic, params.neighbourhoods, params.groups].forEach( - (selections, index) => { - if (selections?.length) { - selections.forEach((id) => { - const option = passedOptions[keys[index]]?.find( - (valueOption: OptionType) => id === Number(valueOption.value), - ); + [params.topic, params.neighbourhoods, params.groups].forEach((selections, index) => { + if (selections?.length) { + selections.forEach((id) => { + const option = passedOptions[keys[index]]?.find( + (valueOption: OptionType) => id === Number(valueOption.value), + ); - if (!option) { - return; - } + if (!option) { + return; + } - const paramKey = keys[index]; - pills.push(generatePill(option, paramKey)); - }); - } - }, - ); + const paramKey = keys[index]; + pills.push(generatePill(option, paramKey)); + }); + } + }); return pills; }; @@ -72,16 +58,10 @@ const SelectionsContainer = ({ updateParams({ page: 1 }); }; - const showClearButton = - params.topic?.length || - params.neighbourhoods?.length || - params.groups?.length; + const showClearButton = params.topic?.length || params.neighbourhoods?.length || params.groups?.length; return ( - + {getPills()} ); diff --git a/src/js/react/apps/news-archive/helpers/NewsSearchParams.ts b/src/js/react/apps/news-archive/helpers/NewsSearchParams.ts index b77a8b615..e64e498de 100644 --- a/src/js/react/apps/news-archive/helpers/NewsSearchParams.ts +++ b/src/js/react/apps/news-archive/helpers/NewsSearchParams.ts @@ -37,11 +37,7 @@ class NewsSearchParams extends URLSearchParams { } toInitialValue(): URLParams { - const initialParams: URLParams = { - groups: [], - neighbourhoods: [], - topic: [], - }; + const initialParams: URLParams = { groups: [], neighbourhoods: [], topic: [] }; const keys = Object.keys(initialParams); const entries = this.entries(); @@ -52,8 +48,7 @@ class NewsSearchParams extends URLSearchParams { if (matchedKey) { const arrayValue = value.split(','); - initialParams[matchedKey as keyof Omit] = - arrayValue.map((id) => Number(id)); + initialParams[matchedKey as keyof Omit] = arrayValue.map((id) => Number(id)); } result = entries.next(); diff --git a/src/js/react/apps/news-archive/hooks/useIndexQuery.tsx b/src/js/react/apps/news-archive/hooks/useIndexQuery.tsx index 42d0d0894..66e8c9aae 100644 --- a/src/js/react/apps/news-archive/hooks/useIndexQuery.tsx +++ b/src/js/react/apps/news-archive/hooks/useIndexQuery.tsx @@ -14,17 +14,10 @@ type useIndexQueryProps = { query: string; } & Partial; // Allows passing SWR hook options -const useIndexQuery = ({ - debug, - query, - multi, - key, - ...rest -}: useIndexQueryProps) => { +const useIndexQuery = ({ debug, query, multi, key, ...rest }: useIndexQueryProps) => { const fetcher = () => { const index = Global.INDEX; - const url: string | undefined = - drupalSettings?.helfi_news_archive?.elastic_proxy_url; + const url: string | undefined = drupalSettings?.helfi_news_archive?.elastic_proxy_url; const endpoint = multi ? '_msearch' : '_search'; const contentType = multi ? 'application/x-ndjson' : 'application/json'; diff --git a/src/js/react/apps/news-archive/hooks/useInitialQuery.tsx b/src/js/react/apps/news-archive/hooks/useInitialQuery.tsx index bb56b14f4..3f0714a43 100644 --- a/src/js/react/apps/news-archive/hooks/useInitialQuery.tsx +++ b/src/js/react/apps/news-archive/hooks/useInitialQuery.tsx @@ -8,19 +8,9 @@ const useInitialQuery = () => { const getAggQuery = (key: string, vid: string) => ({ aggs: { - [key]: { - multi_terms: { - terms: [{ field: 'name' }, { field: 'tid' }], - size: 100000, - order: { _key: 'asc' }, - }, - }, - }, - query: { - bool: { - filter: [{ term: { vid } }, termFilter, ...languageFilter.bool.filter], - }, + [key]: { multi_terms: { terms: [{ field: 'name' }, { field: 'tid' }], size: 100000, order: { _key: 'asc' } } }, }, + query: { bool: { filter: [{ term: { vid } }, termFilter, ...languageFilter.bool.filter] } }, size: 10000, }); diff --git a/src/js/react/apps/news-archive/hooks/useLanguageQuery.ts b/src/js/react/apps/news-archive/hooks/useLanguageQuery.ts index 0e01f26d8..c62ee483e 100644 --- a/src/js/react/apps/news-archive/hooks/useLanguageQuery.ts +++ b/src/js/react/apps/news-archive/hooks/useLanguageQuery.ts @@ -1,14 +1,5 @@ export const useLanguageQuery = () => ({ - bool: { - filter: [ - { - term: { - search_api_language: - window.drupalSettings.path.currentLanguage || 'fi', - }, - }, - ], - }, + bool: { filter: [{ term: { search_api_language: window.drupalSettings.path.currentLanguage || 'fi' } }] }, }); export default useLanguageQuery; diff --git a/src/js/react/apps/news-archive/hooks/useQueryString.tsx b/src/js/react/apps/news-archive/hooks/useQueryString.tsx index 383139c31..be3ea1af5 100644 --- a/src/js/react/apps/news-archive/hooks/useQueryString.tsx +++ b/src/js/react/apps/news-archive/hooks/useQueryString.tsx @@ -8,9 +8,7 @@ import useLanguageQuery from './useLanguageQuery'; const useQueryString = (urlParams: URLParams): string => { const languageFilter = useLanguageQuery(); const size = drupalSettings?.helfi_news_archive?.max_results ?? Global.SIZE; - const page = Number.isNaN(Number(urlParams.page)) - ? 1 - : Number(urlParams.page); + const page = Number.isNaN(Number(urlParams.page)) ? 1 : Number(urlParams.page); const must: estypes.QueryDslQueryContainer[] = []; // Add entity type filteration to languageFilter so that only nodes are listed on results. @@ -27,9 +25,7 @@ const useQueryString = (urlParams: URLParams): string => { } if (urlParams?.neighbourhoods?.length) { - must.push({ - terms: { [IndexFields.NEIGHBOURHOODS]: urlParams.neighbourhoods }, - }); + must.push({ terms: { [IndexFields.NEIGHBOURHOODS]: urlParams.neighbourhoods } }); } if (urlParams?.keyword?.length) { @@ -46,11 +42,7 @@ const useQueryString = (urlParams: URLParams): string => { ], }, }, - { - wildcard: { - [`${IndexFields.TITLE}.keyword`]: `*${urlParams.keyword}*`, - }, - }, + { wildcard: { [`${IndexFields.TITLE}.keyword`]: `*${urlParams.keyword}*` } }, ], minimum_should_match: 1, }, diff --git a/src/js/react/apps/news-archive/store.ts b/src/js/react/apps/news-archive/store.ts index d5c4aa94a..8f65c4616 100644 --- a/src/js/react/apps/news-archive/store.ts +++ b/src/js/react/apps/news-archive/store.ts @@ -2,8 +2,7 @@ import { atom } from 'jotai'; import NewsSearchParams from './helpers/NewsSearchParams'; import type URLParams from './types/URLParams'; -const initialParamString = - drupalSettings.helfi_news_archive.default_query ?? window.location.search; +const initialParamString = drupalSettings.helfi_news_archive.default_query ?? window.location.search; const params = new NewsSearchParams(initialParamString); const initialParams = params.toInitialValue(); diff --git a/src/js/react/apps/news-archive/types/AggregationItem.ts b/src/js/react/apps/news-archive/types/AggregationItem.ts index 48a0dd437..1f7aa85fe 100644 --- a/src/js/react/apps/news-archive/types/AggregationItem.ts +++ b/src/js/react/apps/news-archive/types/AggregationItem.ts @@ -1,7 +1,3 @@ -type AggregationItem = { - doc_count: number; - key: Array; - key_as_string: string; -}; +type AggregationItem = { doc_count: number; key: Array; key_as_string: string }; export default AggregationItem; diff --git a/src/js/react/apps/news-archive/types/URLParams.ts b/src/js/react/apps/news-archive/types/URLParams.ts index cc020d572..d02f64c13 100644 --- a/src/js/react/apps/news-archive/types/URLParams.ts +++ b/src/js/react/apps/news-archive/types/URLParams.ts @@ -1,9 +1,3 @@ -type URLParams = { - groups?: number[]; - neighbourhoods?: number[]; - page?: number; - keyword?: string; - topic?: number[]; -}; +type URLParams = { groups?: number[]; neighbourhoods?: number[]; page?: number; keyword?: string; topic?: number[] }; export default URLParams; diff --git a/src/js/react/apps/ploughing-schedule/components/ResultCard.tsx b/src/js/react/apps/ploughing-schedule/components/ResultCard.tsx index adbe8f2f0..f76606a25 100644 --- a/src/js/react/apps/ploughing-schedule/components/ResultCard.tsx +++ b/src/js/react/apps/ploughing-schedule/components/ResultCard.tsx @@ -1,32 +1,16 @@ import { type ForwardedRef, forwardRef } from 'react'; -type CardProps = { - title: string; - address?: string; - lead?: string; - description: string | JSX.Element | JSX.Element[]; -}; +type CardProps = { title: string; address?: string; lead?: string; description: string | JSX.Element | JSX.Element[] }; -const ResultCard = forwardRef( - ( - { description, lead, title, address }: CardProps, - ref: ForwardedRef, - ) => ( -
-

- {title} -

- {address && ( -

- {address} -

- )} -
- {lead &&

{lead}

} -

{description}

-
+const ResultCard = forwardRef(({ description, lead, title, address }: CardProps, ref: ForwardedRef) => ( +
+

{title}

+ {address &&

{address}

} +
+ {lead &&

{lead}

} +

{description}

- ), -); +
+)); export default ResultCard; diff --git a/src/js/react/apps/ploughing-schedule/components/ResultsList.tsx b/src/js/react/apps/ploughing-schedule/components/ResultsList.tsx index 54437f15c..85ff73abe 100644 --- a/src/js/react/apps/ploughing-schedule/components/ResultsList.tsx +++ b/src/js/react/apps/ploughing-schedule/components/ResultsList.tsx @@ -16,12 +16,7 @@ type ResultsListProps = { isValidating: boolean; }; -const ResultsList = ({ - data, - error, - isLoading, - isValidating, -}: ResultsListProps) => { +const ResultsList = ({ data, error, isLoading, isValidating }: ResultsListProps) => { const params = useAtomValue(paramsAtom); const scrollTarget = createRef(); const choices = Boolean(Object.keys(params).length); @@ -41,8 +36,7 @@ const ResultsList = ({ const results = data.hits.hits; const several = results.length > 1; - const address = - params.address?.replace(/^(?![A-Za-z]\d+$)(.*?)(\s*\d+\w?)$/, '$1') ?? ''; + const address = params.address?.replace(/^(?![A-Za-z]\d+$)(.*?)(\s*\d+\w?)$/, '$1') ?? ''; return (
diff --git a/src/js/react/apps/ploughing-schedule/containers/FormContainer.tsx b/src/js/react/apps/ploughing-schedule/containers/FormContainer.tsx index 8a0a188b6..5e678d23e 100644 --- a/src/js/react/apps/ploughing-schedule/containers/FormContainer.tsx +++ b/src/js/react/apps/ploughing-schedule/containers/FormContainer.tsx @@ -7,11 +7,7 @@ import type SearchParams from '../types/SearchParams'; type SuggestionItemType = { value: string }; -const FormContainer = ({ - initialParams, -}: { - initialParams?: SearchParams | null; -}) => { +const FormContainer = ({ initialParams }: { initialParams?: SearchParams | null }) => { const setParams = useSetAtom(paramsAtom); const [address, setAddress] = useState(initialParams?.address || ''); const { baseUrl, index } = useAtomValue(configurationsAtom); @@ -22,9 +18,7 @@ const FormContainer = ({ setParams(params); }; - const getSuggestions = ( - searchString: string, - ): Promise => + const getSuggestions = (searchString: string): Promise => fetch(`${baseUrl}/${index}/_search`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -34,45 +28,30 @@ const FormContainer = ({ .then((data) => { if (data?.error?.type === 'index_not_found_exception') { console.warn( - `[Ploughing Schedule] Elasticsearch index "${index}" not found. ` + - `Reason: ${data.error.reason}`, + `[Ploughing Schedule] Elasticsearch index "${index}" not found. ` + `Reason: ${data.error.reason}`, ); return []; } const hits = data?.hits?.hits ?? []; // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 - const streetNames: SuggestionItemType[] = hits.map((hit: any) => ({ - value: hit.fields.street_name[0], - })); + const streetNames: SuggestionItemType[] = hits.map((hit: any) => ({ value: hit.fields.street_name[0] })); // Remove duplicates return streetNames.filter( - (item, itemIndex, self) => - itemIndex === self.findIndex((curr) => curr.value === item.value), + (item, itemIndex, self) => itemIndex === self.findIndex((curr) => curr.value === item.value), ); }) .catch((error) => { - console.warn( - '[Ploughing Schedule] Failed to fetch suggestions.', - error, - ); + console.warn('[Ploughing Schedule] Failed to fetch suggestions.', error); return []; }); return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
+

- {Drupal.t( - 'See the ploughing schedule', - {}, - { context: 'Ploughing schedule: Form title / submit' }, - )} + {Drupal.t('See the ploughing schedule', {}, { context: 'Ploughing schedule: Form title / submit' })}

{Drupal.t( @@ -84,32 +63,20 @@ const FormContainer = ({ setAddress(value)} onChange={(value) => setAddress(value)} visibleSuggestions={5} - placeholder={Drupal.t( - 'For example, Mannerheimintie', - {}, - { context: 'Ploughing schedule: Input placeholder' }, - )} + placeholder={Drupal.t('For example, Mannerheimintie', {}, { context: 'Ploughing schedule: Input placeholder' })} value={address} /> ); diff --git a/src/js/react/apps/ploughing-schedule/helpers/GetQueryString.ts b/src/js/react/apps/ploughing-schedule/helpers/GetQueryString.ts index f3525886c..b9be64487 100644 --- a/src/js/react/apps/ploughing-schedule/helpers/GetQueryString.ts +++ b/src/js/react/apps/ploughing-schedule/helpers/GetQueryString.ts @@ -1,9 +1,7 @@ import type BooleanQuery from '@/types/BooleanQuery'; const getQueryString = (address: string) => { - const query: BooleanQuery = { - bool: { must: [{ match: { street_name: address } }] }, - }; + const query: BooleanQuery = { bool: { must: [{ match: { street_name: address } }] } }; const sort = [{ length: 'desc' }]; diff --git a/src/js/react/apps/ploughing-schedule/helpers/GetScheduleCard.ts b/src/js/react/apps/ploughing-schedule/helpers/GetScheduleCard.ts index 278b9e357..b040e3e11 100644 --- a/src/js/react/apps/ploughing-schedule/helpers/GetScheduleCard.ts +++ b/src/js/react/apps/ploughing-schedule/helpers/GetScheduleCard.ts @@ -26,11 +26,7 @@ const getScheduleCard = (maintenanceClass: number, several?: boolean) => { ); return { - title: Drupal.t( - 'Estimated ploughing schedule', - {}, - { context: 'Ploughing schedule: Result title' }, - ), + title: Drupal.t('Estimated ploughing schedule', {}, { context: 'Ploughing schedule: Result title' }), description: parse(schedules[maintenanceClass]), lead: several ? leadText : '', }; diff --git a/src/js/react/apps/ploughing-schedule/hooks/UseQuery.ts b/src/js/react/apps/ploughing-schedule/hooks/UseQuery.ts index ede67d405..653771798 100644 --- a/src/js/react/apps/ploughing-schedule/hooks/UseQuery.ts +++ b/src/js/react/apps/ploughing-schedule/hooks/UseQuery.ts @@ -23,11 +23,9 @@ const UseQuery = (params: SearchParams) => { }).then((res) => res.json()); }; - const { data, error, isLoading, isValidating } = useSWR( - `_${Object.values(params).toString()}`, - fetcher, - { revalidateOnFocus: false }, - ); + const { data, error, isLoading, isValidating } = useSWR(`_${Object.values(params).toString()}`, fetcher, { + revalidateOnFocus: false, + }); return { data, error, isLoading, isValidating }; }; diff --git a/src/js/react/apps/ploughing-schedule/store.tsx b/src/js/react/apps/ploughing-schedule/store.tsx index 2188e1852..a2382b3f3 100644 --- a/src/js/react/apps/ploughing-schedule/store.tsx +++ b/src/js/react/apps/ploughing-schedule/store.tsx @@ -10,12 +10,9 @@ export const configurationsAtom = atom(() => { export const paramsAtom = atom({}); export const stagedParamsAtom = atom({}); -export const updateParamsAtom = atom( - null, - (_get, set, params: SearchParams) => { - set(stagedParamsAtom, { ...params }); - set(paramsAtom, { ...params }); - }, -); +export const updateParamsAtom = atom(null, (_get, set, params: SearchParams) => { + set(stagedParamsAtom, { ...params }); + set(paramsAtom, { ...params }); +}); export default configurationsAtom; diff --git a/src/js/react/apps/ploughing-schedule/types/Street.ts b/src/js/react/apps/ploughing-schedule/types/Street.ts index 10d8d4cf1..b269034e8 100644 --- a/src/js/react/apps/ploughing-schedule/types/Street.ts +++ b/src/js/react/apps/ploughing-schedule/types/Street.ts @@ -1,5 +1 @@ -export type Street = { - id: string[]; - maintenance_class: number; - street_name: string[]; -}; +export type Street = { id: string[]; maintenance_class: number; street_name: string[] }; diff --git a/src/js/react/apps/school-search/components/ResultCard.tsx b/src/js/react/apps/school-search/components/ResultCard.tsx index 55d2a9833..1d81c5123 100644 --- a/src/js/react/apps/school-search/components/ResultCard.tsx +++ b/src/js/react/apps/school-search/components/ResultCard.tsx @@ -28,9 +28,7 @@ const ResultCard = ({ let cardImage: CardImageType; if (imageOverride) { - cardImage = ( - - ); + cardImage = ; } else if (picture_url?.[0]) { cardImage = ; } else { @@ -41,22 +39,12 @@ const ResultCard = ({ let language; if (additionalFilters.finnish_education) { - language = Drupal.t( - 'Finnish', - {}, - { context: 'School search: language option' }, - ); + language = Drupal.t('Finnish', {}, { context: 'School search: language option' }); } if (additionalFilters.swedish_education) { - const swedish = Drupal.t( - 'Swedish', - {}, - { context: 'School search: language option' }, - ); - language = language?.length - ? `${language}, ${swedish.toLowerCase()}` - : swedish; + const swedish = Drupal.t('Swedish', {}, { context: 'School search: language option' }); + language = language?.length ? `${language}, ${swedish.toLowerCase()}` : swedish; } let languageEducation = ontologyword_ids?.reduce( @@ -93,30 +81,14 @@ const ResultCard = ({ cardImage={cardImage} cardTitle={title} cardUrl={url?.[0] || ''} - language={ - bilingualEducation?.length - ? `${language}, ${bilingualEducation.join(', ')}` - : language - } - languageLabel={Drupal.t( - 'Language of instruction', - {}, - { context: 'School search: language options' }, - )} + language={bilingualEducation?.length ? `${language}, ${bilingualEducation.join(', ')}` : language} + languageLabel={Drupal.t('Language of instruction', {}, { context: 'School search: language options' })} location={address?.[0]} - locationLabel={Drupal.t( - 'Address', - {}, - { context: 'React search: location label' }, - )} + locationLabel={Drupal.t('Address', {}, { context: 'React search: location label' })} weightedEducation={ - ontologyword_details_clarifications?.length - ? ontologyword_details_clarifications.join(', ') - : '' - } - languageEducation={ - languageEducation?.length ? languageEducation.join(', ') : '' + ontologyword_details_clarifications?.length ? ontologyword_details_clarifications.join(', ') : '' } + languageEducation={languageEducation?.length ? languageEducation.join(', ') : ''} /> ); }; diff --git a/src/js/react/apps/school-search/components/ResultsList.tsx b/src/js/react/apps/school-search/components/ResultsList.tsx index 3e466b69c..2ae715531 100644 --- a/src/js/react/apps/school-search/components/ResultsList.tsx +++ b/src/js/react/apps/school-search/components/ResultsList.tsx @@ -25,14 +25,7 @@ type ResultsListProps = { updatePage: Function; }; -const ResultsList = ({ - data, - error, - isLoading, - isValidating, - page, - updatePage, -}: ResultsListProps) => { +const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }: ResultsListProps) => { const [useMap, setUseMap] = useState(false); const { size } = AppSettings; const params = useAtomValue(paramsAtom); @@ -85,11 +78,7 @@ const ResultsList = ({ aria-controls='school-search-results-tabpanel-list' onClick={() => setUseMap(false)} > - {Drupal.t( - 'View as a list', - {}, - { context: 'React search: result display' }, - )} + {Drupal.t('View as a list', {}, { context: 'React search: result display' })}

} diff --git a/src/js/react/apps/school-search/containers/FeatureFormContainer.tsx b/src/js/react/apps/school-search/containers/FeatureFormContainer.tsx index 5588cfc52..825e30b63 100644 --- a/src/js/react/apps/school-search/containers/FeatureFormContainer.tsx +++ b/src/js/react/apps/school-search/containers/FeatureFormContainer.tsx @@ -48,53 +48,29 @@ const FeatureFormContainer = () => { const b2Options = useAtomValue(b2Atom); const [b2Selection, setB2Filter] = useAtom(b2SelectionAtom); const weightedOptions = useAtomValue(weightedEducationAtom); - const [weightedSelection, setWeightedFilter] = useAtom( - weightedEducationSelectionAtom, - ); + const [weightedSelection, setWeightedFilter] = useAtom(weightedEducationSelectionAtom); const bilingualOptions = useAtomValue(bilingualEducationAtom); - const [bilingualSelection, setBilingualFilter] = useAtom( - bilingualEducationSelectionAtom, - ); + const [bilingualSelection, setBilingualFilter] = useAtom(bilingualEducationSelectionAtom); const onSubmit = (event: React.FormEvent) => { event.preventDefault(); - const { - keyword, - finnish_education, - grades_1_6, - grades_1_9, - grades_7_9, - swedish_education, - } = event.target as SubmitFormType; + const { keyword, finnish_education, grades_1_6, grades_1_9, grades_7_9, swedish_education } = + event.target as SubmitFormType; const params: SearchParams = {}; if (keyword.value?.length) { params.keyword = keyword.value; } - [ - finnish_education, - grades_1_6, - grades_1_9, - grades_7_9, - swedish_education, - ].forEach((element) => { + [finnish_education, grades_1_6, grades_1_9, grades_7_9, swedish_education].forEach((element) => { if (!element || !element.checked || !element.name) { return; } const name = element.name as keyof Omit< SearchParams, - | 'keyword' - | 'page' - | 'query' - | 'a1' - | 'a2' - | 'b1' - | 'b2' - | 'weighted_education' - | 'bilingual_education' + 'keyword' | 'page' | 'query' | 'a1' | 'a2' | 'b1' | 'b2' | 'weighted_education' | 'bilingual_education' >; params[name] = true; }); @@ -103,12 +79,8 @@ const FeatureFormContainer = () => { params.a2 = a2Selection.map((selection: OptionType) => selection.value); params.b1 = b1Selection.map((selection: OptionType) => selection.value); params.b2 = b2Selection.map((selection: OptionType) => selection.value); - params.weighted_education = weightedSelection.map( - (selection: OptionType) => selection.value, - ); - params.bilingual_education = bilingualSelection.flatMap( - (selection: OptionType) => selection.value.split(','), - ); + params.weighted_education = weightedSelection.map((selection: OptionType) => selection.value); + params.bilingual_education = bilingualSelection.flatMap((selection: OptionType) => selection.value.split(',')); setParams(params); }; @@ -116,23 +88,9 @@ const FeatureFormContainer = () => { const keys: Array< keyof Omit< SearchParams, - | 'keyword' - | 'page' - | 'query' - | 'a1' - | 'a2' - | 'b1' - | 'b2' - | 'weighted_education' - | 'bilingual_education' + 'keyword' | 'page' | 'query' | 'a1' | 'a2' | 'b1' | 'b2' | 'weighted_education' | 'bilingual_education' > - > = [ - 'grades_1_6', - 'grades_1_9', - 'grades_7_9', - 'finnish_education', - 'swedish_education', - ]; + > = ['grades_1_6', 'grades_1_9', 'grades_7_9', 'finnish_education', 'swedish_education']; const a1Label: string = Drupal.t( 'Language starting in Grade 1 (A1)', {}, @@ -163,24 +121,12 @@ const FeatureFormContainer = () => { {}, { context: 'TPR Ontologyword details schools' }, ); - const currentLanguage = getCurrentLanguage( - window.drupalSettings.path.currentLanguage, - ); + const currentLanguage = getCurrentLanguage(window.drupalSettings.path.currentLanguage); return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 -
-

- {Drupal.t( - 'Search with school details', - {}, - { context: 'School search: Feature form title' }, - )} -

+ +

{Drupal.t('Search with school details', {}, { context: 'School search: Feature form title' })}

{Drupal.t( 'You can search for a school by its name, language of instruction, grade or post code.', @@ -191,11 +137,7 @@ const FeatureFormContainer = () => { setKeywordValue(value)} placeholder={Drupal.t( @@ -205,38 +147,21 @@ const FeatureFormContainer = () => { )} type='search' value={keywordValue || ''} // Ensure value is always a string. - clearButtonAriaLabel={Drupal.t( - 'Clear', - {}, - { context: 'React search' }, - )} + clearButtonAriaLabel={Drupal.t('Clear', {}, { context: 'React search' })} style={defaultTextInputStyle} />

- {Drupal.t( - 'Language of instruction', - {}, - { context: 'School search: language options' }, - )} + {Drupal.t('Language of instruction', {}, { context: 'School search: language options' })} - setStagedParams({ - ...stagedParams, - finnish_education: !stagedParams?.finnish_education, - }) - } + onClick={() => setStagedParams({ ...stagedParams, finnish_education: !stagedParams?.finnish_education })} value={stagedParams?.finnish_education?.toString() || 'false'} style={defaultCheckboxStyle} /> @@ -244,46 +169,24 @@ const FeatureFormContainer = () => { checked={stagedParams?.swedish_education || false} className='hdbt-search--react__checkbox' id='swedish_education' - label={Drupal.t( - 'Swedish', - {}, - { context: 'School search: language option' }, - )} + label={Drupal.t('Swedish', {}, { context: 'School search: language option' })} name='swedish_education' - onClick={() => - setStagedParams({ - ...stagedParams, - swedish_education: !stagedParams?.swedish_education, - }) - } + onClick={() => setStagedParams({ ...stagedParams, swedish_education: !stagedParams?.swedish_education })} value={stagedParams?.swedish_education?.toString() || 'false'} style={defaultCheckboxStyle} />
- {Drupal.t( - 'Grade', - {}, - { context: 'School search: education level' }, - )} + {Drupal.t('Grade', {}, { context: 'School search: education level' })} - setStagedParams({ - ...stagedParams, - grades_1_6: !stagedParams?.grades_1_6, - }) - } + onClick={() => setStagedParams({ ...stagedParams, grades_1_6: !stagedParams?.grades_1_6 })} value={stagedParams?.grades_1_6?.toString() || 'false'} style={defaultCheckboxStyle} /> @@ -291,18 +194,9 @@ const FeatureFormContainer = () => { checked={stagedParams?.grades_1_9 || false} className='hdbt-search--react__checkbox' id='grades_1_9' - label={Drupal.t( - 'School providing grades 1 to 9', - {}, - { context: 'School search: education level option' }, - )} + label={Drupal.t('School providing grades 1 to 9', {}, { context: 'School search: education level option' })} name='grades_1_9' - onClick={() => - setStagedParams({ - ...stagedParams, - grades_1_9: !stagedParams?.grades_1_9, - }) - } + onClick={() => setStagedParams({ ...stagedParams, grades_1_9: !stagedParams?.grades_1_9 })} value={stagedParams?.grades_1_9?.toString() || 'false'} style={defaultCheckboxStyle} /> @@ -310,18 +204,9 @@ const FeatureFormContainer = () => { checked={stagedParams?.grades_7_9 || false} className='hdbt-search--react__checkbox' id='grades_7_9' - label={Drupal.t( - 'School providing grades 7 to 9', - {}, - { context: 'School search: education level option' }, - )} + label={Drupal.t('School providing grades 7 to 9', {}, { context: 'School search: education level option' })} name='grades_7_9' - onClick={() => - setStagedParams({ - ...stagedParams, - grades_7_9: !stagedParams?.grades_7_9, - }) - } + onClick={() => setStagedParams({ ...stagedParams, grades_7_9: !stagedParams?.grades_7_9 })} value={stagedParams?.grades_7_9?.toString() || 'false'} style={defaultCheckboxStyle} /> @@ -341,11 +226,7 @@ const FeatureFormContainer = () => { texts={{ label: a1Label, language: currentLanguage, - placeholder: Drupal.t( - 'All languages', - {}, - { context: 'School search: language placeholder' }, - ), + placeholder: Drupal.t('All languages', {}, { context: 'School search: language placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': a2Label }, @@ -373,11 +254,7 @@ const FeatureFormContainer = () => { texts={{ label: a2Label, language: currentLanguage, - placeholder: Drupal.t( - 'All languages', - {}, - { context: 'School search: language placeholder' }, - ), + placeholder: Drupal.t('All languages', {}, { context: 'School search: language placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': a2Label }, @@ -405,11 +282,7 @@ const FeatureFormContainer = () => { texts={{ label: b1Label, language: currentLanguage, - placeholder: Drupal.t( - 'All languages', - {}, - { context: 'School search: language placeholder' }, - ), + placeholder: Drupal.t('All languages', {}, { context: 'School search: language placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': b1Label }, @@ -437,11 +310,7 @@ const FeatureFormContainer = () => { texts={{ label: b2Label, language: currentLanguage, - placeholder: Drupal.t( - 'All languages', - {}, - { context: 'School search: language placeholder' }, - ), + placeholder: Drupal.t('All languages', {}, { context: 'School search: language placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': b2Label }, @@ -469,11 +338,7 @@ const FeatureFormContainer = () => { texts={{ label: weightedEducationLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All', - {}, - { context: 'React search all placeholder' }, - ), + placeholder: Drupal.t('All', {}, { context: 'React search all placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': weightedEducationLabel }, @@ -501,11 +366,7 @@ const FeatureFormContainer = () => { texts={{ label: bilingualEducationLabel, language: currentLanguage, - placeholder: Drupal.t( - 'All', - {}, - { context: 'React search all placeholder' }, - ), + placeholder: Drupal.t('All', {}, { context: 'React search all placeholder' }), clearButtonAriaLabel_one: Drupal.t( 'Clear @label selection', { '@label': bilingualEducationLabel }, @@ -523,11 +384,7 @@ const FeatureFormContainer = () => {
diff --git a/src/js/react/apps/school-search/containers/FeatureResultsContainer.tsx b/src/js/react/apps/school-search/containers/FeatureResultsContainer.tsx index fb8265db7..4bce854d5 100644 --- a/src/js/react/apps/school-search/containers/FeatureResultsContainer.tsx +++ b/src/js/react/apps/school-search/containers/FeatureResultsContainer.tsx @@ -13,11 +13,7 @@ const FeatureResultsContainer = () => { const { data, error, isLoading, isValidating } = UseFeatureQuery(params); const { page } = params; - return ( - - ); + return ; }; export default FeatureResultsContainer; diff --git a/src/js/react/apps/school-search/containers/ProximityFormContainer.tsx b/src/js/react/apps/school-search/containers/ProximityFormContainer.tsx index cb82edeac..5f1732b42 100644 --- a/src/js/react/apps/school-search/containers/ProximityFormContainer.tsx +++ b/src/js/react/apps/school-search/containers/ProximityFormContainer.tsx @@ -4,11 +4,7 @@ import { AddressSearch } from '@/react/common/AddressSearch'; import { keywordAtom, paramsAtom } from '../store'; import type SearchParams from '../types/SearchParams'; -const ProximityFormContainer = ({ - initialAddress, -}: { - initialAddress?: string; -}) => { +const ProximityFormContainer = ({ initialAddress }: { initialAddress?: string }) => { const [keyword, setKeyword] = useAtom(keywordAtom); const setParams = useSetAtom(paramsAtom); @@ -33,18 +29,8 @@ const ProximityFormContainer = ({ return ( // biome-ignore lint/a11y/useSemanticElements: @todo UHF-12501 - -

- {Drupal.t( - 'Search for your local school', - {}, - { context: 'School search: local search title' }, - )} -

+ +

{Drupal.t('Search for your local school', {}, { context: 'School search: local search title' })}

{Drupal.t( "Your child's primary comprehensive school, i.e., the local school, is assigned based on the child's home address. You can search for Finnish- and Swedish-language comprehensive schools.", @@ -54,11 +40,7 @@ const ProximityFormContainer = ({

setKeyword(value)} onSubmit={(value: string) => setKeyword(value)} placeholder={Drupal.t( @@ -81,11 +59,7 @@ const ProximityFormContainer = ({ visibleSuggestions={5} /> ); diff --git a/src/js/react/apps/school-search/containers/ProximityResultsContainer.tsx b/src/js/react/apps/school-search/containers/ProximityResultsContainer.tsx index 72e0279fa..0d76bd9c7 100644 --- a/src/js/react/apps/school-search/containers/ProximityResultsContainer.tsx +++ b/src/js/react/apps/school-search/containers/ProximityResultsContainer.tsx @@ -13,11 +13,7 @@ const ProximityResultsContainer = () => { const { data, error, isLoading, isValidating } = UseProximityQuery(params); const { page } = params; - return ( - - ); + return ; }; export default ProximityResultsContainer; diff --git a/src/js/react/apps/school-search/containers/SearchContainer.tsx b/src/js/react/apps/school-search/containers/SearchContainer.tsx index d9b9f5697..de765f23b 100644 --- a/src/js/react/apps/school-search/containers/SearchContainer.tsx +++ b/src/js/react/apps/school-search/containers/SearchContainer.tsx @@ -20,8 +20,7 @@ const MODE_OPTIONS = { }; const SearchContainer = () => { - const { data: configurations, error: configurationsError } = - UseConfigurationsQuery(); + const { data: configurations, error: configurationsError } = UseConfigurationsQuery(); const [searchMode, setSearchMode] = useState(MODE_OPTIONS.proximity); const setKeyword = useSetAtom(keywordAtom); const setParams = useSetAtom(paramsAtom); @@ -65,11 +64,7 @@ const SearchContainer = () => { aria-controls='school-search-tabpanel-proximity' onClick={() => changeSearchMode(MODE_OPTIONS.proximity)} > - {Drupal.t( - 'Search for your local school', - {}, - { context: 'School search: local search title' }, - )} + {Drupal.t('Search for your local school', {}, { context: 'School search: local search title' })}
- - } - > + }> }> {searchMode === MODE_OPTIONS.proximity ? ( -
+
) : ( -
+
diff --git a/src/js/react/apps/school-search/containers/SelectionsContainer.tsx b/src/js/react/apps/school-search/containers/SelectionsContainer.tsx index 4af4d7b20..36bda4d6d 100644 --- a/src/js/react/apps/school-search/containers/SelectionsContainer.tsx +++ b/src/js/react/apps/school-search/containers/SelectionsContainer.tsx @@ -26,15 +26,7 @@ type SelectionsContainerProps = { keys: Array< keyof Omit< SearchParams, - | 'keyword' - | 'page' - | 'query' - | 'a1' - | 'a2' - | 'b1' - | 'b2' - | 'weighted_education' - | 'bilingual_education' + 'keyword' | 'page' | 'query' | 'a1' | 'a2' | 'b1' | 'b2' | 'weighted_education' | 'bilingual_education' > >; }; @@ -56,31 +48,11 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { const updateBilingual = useSetAtom(bilingualEducationSelectionAtom); const checkBoxFilters = { - grades_1_6: Drupal.t( - 'School providing grades 1 to 6', - {}, - { context: 'School search: education level option' }, - ), - grades_1_9: Drupal.t( - 'School providing grades 1 to 9', - {}, - { context: 'School search: education level option' }, - ), - grades_7_9: Drupal.t( - 'School providing grades 7 to 9', - {}, - { context: 'School search: education level option' }, - ), - finnish_education: Drupal.t( - 'Finnish', - {}, - { context: 'School search: language option' }, - ), - swedish_education: Drupal.t( - 'Swedish', - {}, - { context: 'School search: language option' }, - ), + grades_1_6: Drupal.t('School providing grades 1 to 6', {}, { context: 'School search: education level option' }), + grades_1_9: Drupal.t('School providing grades 1 to 9', {}, { context: 'School search: education level option' }), + grades_7_9: Drupal.t('School providing grades 7 to 9', {}, { context: 'School search: education level option' }), + finnish_education: Drupal.t('Finnish', {}, { context: 'School search: language option' }), + swedish_education: Drupal.t('Swedish', {}, { context: 'School search: language option' }), }; const checkBoxKeys = Object.keys(checkBoxFilters); @@ -137,25 +109,13 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { searchParams.weighted_education?.length || searchParams.bilingual_education?.length; - const showA1 = Boolean( - searchParams.a1?.length && searchParams.a1?.length > 0, - ); - const showA2 = Boolean( - searchParams.a2?.length && searchParams.a2?.length > 0, - ); - const showB1 = Boolean( - searchParams.b1?.length && searchParams.b1?.length > 0, - ); - const showB2 = Boolean( - searchParams.b2?.length && searchParams.b2?.length > 0, - ); - const showWeighted = Boolean( - searchParams.weighted_education?.length && - searchParams.weighted_education?.length > 0, - ); + const showA1 = Boolean(searchParams.a1?.length && searchParams.a1?.length > 0); + const showA2 = Boolean(searchParams.a2?.length && searchParams.a2?.length > 0); + const showB1 = Boolean(searchParams.b1?.length && searchParams.b1?.length > 0); + const showB2 = Boolean(searchParams.b2?.length && searchParams.b2?.length > 0); + const showWeighted = Boolean(searchParams.weighted_education?.length && searchParams.weighted_education?.length > 0); const showBilingual = Boolean( - searchParams.bilingual_education?.length && - searchParams.bilingual_education?.length > 0, + searchParams.bilingual_education?.length && searchParams.bilingual_education?.length > 0, ); return ( @@ -166,11 +126,7 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { updater={updateA1} valueKey={SearchComponents.A1} values={transformDropdownsValues(searchParams.a1, a1Options)} - labelPrefix={Drupal.t( - 'A1-language', - {}, - { context: 'TPR Ontologyword details schools' }, - )} + labelPrefix={Drupal.t('A1-language', {}, { context: 'TPR Ontologyword details schools' })} /> )} {showA2 && ( @@ -178,11 +134,7 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { updater={updateA2} valueKey={SearchComponents.A2} values={transformDropdownsValues(searchParams.a2, a2Options)} - labelPrefix={Drupal.t( - 'A2-language', - {}, - { context: 'TPR Ontologyword details schools' }, - )} + labelPrefix={Drupal.t('A2-language', {}, { context: 'TPR Ontologyword details schools' })} /> )} {showB1 && ( @@ -190,11 +142,7 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { updater={updateB1} valueKey={SearchComponents.B1} values={transformDropdownsValues(searchParams.b1, b1Options)} - labelPrefix={Drupal.t( - 'B1-language', - {}, - { context: 'TPR Ontologyword details schools' }, - )} + labelPrefix={Drupal.t('B1-language', {}, { context: 'TPR Ontologyword details schools' })} /> )} {showB2 && ( @@ -202,36 +150,22 @@ const SelectionsContainer = ({ keys }: SelectionsContainerProps) => { updater={updateB2} valueKey={SearchComponents.B2} values={transformDropdownsValues(searchParams.b2, b2Options)} - labelPrefix={Drupal.t( - 'B2-language', - {}, - { context: 'TPR Ontologyword details schools' }, - )} + labelPrefix={Drupal.t('B2-language', {}, { context: 'TPR Ontologyword details schools' })} /> )} {showWeighted && ( )} {showBilingual && ( )} @@ -248,35 +182,23 @@ type ListFilterProps = { labelPrefix?: string; }; -const ListFilter = ({ - updater, - values, - valueKey, - labelPrefix, -}: ListFilterProps) => { +const ListFilter = ({ updater, values, valueKey, labelPrefix }: ListFilterProps) => { const searchParams = useAtomValue(paramsAtom); const setSearchParams = useSetAtom(updateParamsAtom); const removeSelection = (value: string) => { const newValue = values; - const index = newValue.findIndex( - (selection: OptionType) => selection.value === value, - ); + const index = newValue.findIndex((selection: OptionType) => selection.value === value); newValue.splice(index, 1); updater(newValue); - setSearchParams({ - ...searchParams, - [valueKey]: newValue.map((selection: OptionType) => selection.value), - }); + setSearchParams({ ...searchParams, [valueKey]: newValue.map((selection: OptionType) => selection.value) }); }; return ( <> {values.map((selection: OptionType) => ( removeSelection(selection.value)} key={selection.value} /> diff --git a/src/js/react/apps/school-search/enum/LanguageEducationMap.ts b/src/js/react/apps/school-search/enum/LanguageEducationMap.ts index 3b4b4bb0b..6a21b919b 100644 --- a/src/js/react/apps/school-search/enum/LanguageEducationMap.ts +++ b/src/js/react/apps/school-search/enum/LanguageEducationMap.ts @@ -2,284 +2,76 @@ import type OntologyDetailMap from '../types/OntologyDetailsMap'; const ontologyDetailsIdsToLang: OntologyDetailMap = { a1: { - 15: Drupal.t( - 'English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 16: Drupal.t( - 'Spanish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 15: Drupal.t('English', {}, { context: 'TPR Ontologyword details schools' }), + 16: Drupal.t('Spanish', {}, { context: 'TPR Ontologyword details schools' }), 17: Drupal.t('Hebrew', {}, { context: 'TPR Ontologyword details schools' }), - 18: Drupal.t( - 'Italian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 19: Drupal.t( - 'Chinese', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 18: Drupal.t('Italian', {}, { context: 'TPR Ontologyword details schools' }), + 19: Drupal.t('Chinese', {}, { context: 'TPR Ontologyword details schools' }), 20: Drupal.t('Latin', {}, { context: 'TPR Ontologyword details schools' }), 21: Drupal.t('French', {}, { context: 'TPR Ontologyword details schools' }), - 22: Drupal.t( - 'Swedish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 22: Drupal.t('Swedish', {}, { context: 'TPR Ontologyword details schools' }), 23: Drupal.t('German', {}, { context: 'TPR Ontologyword details schools' }), - 24: Drupal.t( - 'Finnish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 25: Drupal.t( - 'Russian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 26: Drupal.t( - 'Estonian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 24: Drupal.t('Finnish', {}, { context: 'TPR Ontologyword details schools' }), + 25: Drupal.t('Russian', {}, { context: 'TPR Ontologyword details schools' }), + 26: Drupal.t('Estonian', {}, { context: 'TPR Ontologyword details schools' }), }, a2: { - 27: Drupal.t( - 'English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 28: Drupal.t( - 'Spanish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 27: Drupal.t('English', {}, { context: 'TPR Ontologyword details schools' }), + 28: Drupal.t('Spanish', {}, { context: 'TPR Ontologyword details schools' }), 29: Drupal.t('Hebrew', {}, { context: 'TPR Ontologyword details schools' }), - 30: Drupal.t( - 'Italian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 31: Drupal.t( - 'Chinese', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 30: Drupal.t('Italian', {}, { context: 'TPR Ontologyword details schools' }), + 31: Drupal.t('Chinese', {}, { context: 'TPR Ontologyword details schools' }), 32: Drupal.t('Latin', {}, { context: 'TPR Ontologyword details schools' }), 33: Drupal.t('French', {}, { context: 'TPR Ontologyword details schools' }), - 34: Drupal.t( - 'Swedish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 34: Drupal.t('Swedish', {}, { context: 'TPR Ontologyword details schools' }), 35: Drupal.t('German', {}, { context: 'TPR Ontologyword details schools' }), - 36: Drupal.t( - 'Finnish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 37: Drupal.t( - 'Russian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 38: Drupal.t( - 'Estonian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 36: Drupal.t('Finnish', {}, { context: 'TPR Ontologyword details schools' }), + 37: Drupal.t('Russian', {}, { context: 'TPR Ontologyword details schools' }), + 38: Drupal.t('Estonian', {}, { context: 'TPR Ontologyword details schools' }), }, b1: { - 101: Drupal.t( - 'English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 102: Drupal.t( - 'Spanish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 103: Drupal.t( - 'Hebrew', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 104: Drupal.t( - 'Italian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 105: Drupal.t( - 'Chinese', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 101: Drupal.t('English', {}, { context: 'TPR Ontologyword details schools' }), + 102: Drupal.t('Spanish', {}, { context: 'TPR Ontologyword details schools' }), + 103: Drupal.t('Hebrew', {}, { context: 'TPR Ontologyword details schools' }), + 104: Drupal.t('Italian', {}, { context: 'TPR Ontologyword details schools' }), + 105: Drupal.t('Chinese', {}, { context: 'TPR Ontologyword details schools' }), 106: Drupal.t('Latin', {}, { context: 'TPR Ontologyword details schools' }), - 107: Drupal.t( - 'French', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 108: Drupal.t( - 'Swedish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 109: Drupal.t( - 'German', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 110: Drupal.t( - 'Finnish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 111: Drupal.t( - 'Russian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 112: Drupal.t( - 'Estonian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 107: Drupal.t('French', {}, { context: 'TPR Ontologyword details schools' }), + 108: Drupal.t('Swedish', {}, { context: 'TPR Ontologyword details schools' }), + 109: Drupal.t('German', {}, { context: 'TPR Ontologyword details schools' }), + 110: Drupal.t('Finnish', {}, { context: 'TPR Ontologyword details schools' }), + 111: Drupal.t('Russian', {}, { context: 'TPR Ontologyword details schools' }), + 112: Drupal.t('Estonian', {}, { context: 'TPR Ontologyword details schools' }), }, b2: { - 113: Drupal.t( - 'English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 114: Drupal.t( - 'Spanish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 115: Drupal.t( - 'Hebrew', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 116: Drupal.t( - 'Italian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 117: Drupal.t( - 'Chinese', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 113: Drupal.t('English', {}, { context: 'TPR Ontologyword details schools' }), + 114: Drupal.t('Spanish', {}, { context: 'TPR Ontologyword details schools' }), + 115: Drupal.t('Hebrew', {}, { context: 'TPR Ontologyword details schools' }), + 116: Drupal.t('Italian', {}, { context: 'TPR Ontologyword details schools' }), + 117: Drupal.t('Chinese', {}, { context: 'TPR Ontologyword details schools' }), 118: Drupal.t('Latin', {}, { context: 'TPR Ontologyword details schools' }), - 119: Drupal.t( - 'French', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 120: Drupal.t( - 'Swedish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 121: Drupal.t( - 'German', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 122: Drupal.t( - 'Finnish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 123: Drupal.t( - 'Russian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 124: Drupal.t( - 'Estonian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 119: Drupal.t('French', {}, { context: 'TPR Ontologyword details schools' }), + 120: Drupal.t('Swedish', {}, { context: 'TPR Ontologyword details schools' }), + 121: Drupal.t('German', {}, { context: 'TPR Ontologyword details schools' }), + 122: Drupal.t('Finnish', {}, { context: 'TPR Ontologyword details schools' }), + 123: Drupal.t('Russian', {}, { context: 'TPR Ontologyword details schools' }), + 124: Drupal.t('Estonian', {}, { context: 'TPR Ontologyword details schools' }), }, bilingualEducation: { - 149: Drupal.t( - 'Teaching in English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 150: Drupal.t( - 'Teaching in English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 293: Drupal.t( - 'Language immersion (English)', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 295: Drupal.t( - 'Language immersion (Swedish)', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 297: Drupal.t( - 'Language immersion (German)', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 904: Drupal.t( - 'Finnish-English', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 905: Drupal.t( - 'Finnish-Chinese', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 906: Drupal.t( - 'Finnish-Spanish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 907: Drupal.t( - 'Finnish-Northern Sami', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 908: Drupal.t( - 'Finnish-Estonian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 909: Drupal.t( - 'Finnish-Russian', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 910: Drupal.t( - 'Language-enriched education (Finnish-English)', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 911: Drupal.t( - 'Language-enriched education (Finnish-Russian)', - {}, - { context: 'TPR Ontologyword details schools' }, - ), - 1041: Drupal.t( - 'Finnish-Swedish', - {}, - { context: 'TPR Ontologyword details schools' }, - ), + 149: Drupal.t('Teaching in English', {}, { context: 'TPR Ontologyword details schools' }), + 150: Drupal.t('Teaching in English', {}, { context: 'TPR Ontologyword details schools' }), + 293: Drupal.t('Language immersion (English)', {}, { context: 'TPR Ontologyword details schools' }), + 295: Drupal.t('Language immersion (Swedish)', {}, { context: 'TPR Ontologyword details schools' }), + 297: Drupal.t('Language immersion (German)', {}, { context: 'TPR Ontologyword details schools' }), + 904: Drupal.t('Finnish-English', {}, { context: 'TPR Ontologyword details schools' }), + 905: Drupal.t('Finnish-Chinese', {}, { context: 'TPR Ontologyword details schools' }), + 906: Drupal.t('Finnish-Spanish', {}, { context: 'TPR Ontologyword details schools' }), + 907: Drupal.t('Finnish-Northern Sami', {}, { context: 'TPR Ontologyword details schools' }), + 908: Drupal.t('Finnish-Estonian', {}, { context: 'TPR Ontologyword details schools' }), + 909: Drupal.t('Finnish-Russian', {}, { context: 'TPR Ontologyword details schools' }), + 910: Drupal.t('Language-enriched education (Finnish-English)', {}, { context: 'TPR Ontologyword details schools' }), + 911: Drupal.t('Language-enriched education (Finnish-Russian)', {}, { context: 'TPR Ontologyword details schools' }), + 1041: Drupal.t('Finnish-Swedish', {}, { context: 'TPR Ontologyword details schools' }), }, }; diff --git a/src/js/react/apps/school-search/helpers/FeatureQuery.ts b/src/js/react/apps/school-search/helpers/FeatureQuery.ts index d4090cd87..c2de6dcc4 100644 --- a/src/js/react/apps/school-search/helpers/FeatureQuery.ts +++ b/src/js/react/apps/school-search/helpers/FeatureQuery.ts @@ -6,10 +6,7 @@ import type SearchParams from '../types/SearchParams'; // Filter by current language // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 export const languageFilter: any = { - term: { - [`${IndexFields.LANGUAGE}`]: - window.drupalSettings.path.currentLanguage || 'fi', - }, + term: { [`${IndexFields.LANGUAGE}`]: window.drupalSettings.path.currentLanguage || 'fi' }, }; const getCheckBoxFilters = (params: SearchParams) => { @@ -31,9 +28,7 @@ const getCheckBoxFilters = (params: SearchParams) => { query.push({ bool: { minimum_should_match: 1, - should: hits.map((hit) => ({ - term: { [`additional_filters.${hit}`]: true }, - })), + should: hits.map((hit) => ({ term: { [`additional_filters.${hit}`]: true } })), }, }); } @@ -58,25 +53,17 @@ const getDropdownFilters = (filterValues: any, indexField: string) => { export const AGGREGATIONS = { aggs: { ontologywordIds: { terms: { field: 'ontologyword_ids', size: 100 } }, - ontologywordClarifications: { - terms: { field: 'ontologyword_details_clarifications', size: 100 }, - }, + ontologywordClarifications: { terms: { field: 'ontologyword_details_clarifications', size: 100 } }, }, query: { bool: { filter: [languageFilter] } }, }; const getQueryString = (params: SearchParams, page: number) => { const { size } = AppSettings; - const { keyword, a1, a2, b1, b2, weighted_education, bilingual_education } = - params; + const { keyword, a1, a2, b1, b2, weighted_education, bilingual_education } = params; const query: BooleanQuery = { - bool: { - filter: [ - { term: { search_api_language: drupalSettings.path.currentLanguage } }, - ], - must: [], - }, + bool: { filter: [{ term: { search_api_language: drupalSettings.path.currentLanguage } }], must: [] }, }; if (keyword?.length) { @@ -93,14 +80,7 @@ const getQueryString = (params: SearchParams, page: number) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 const checkBoxFilters: any = getCheckBoxFilters(params); if (checkBoxFilters.length) { - query.bool.must = [ - { - nested: { - path: 'additional_filters', - query: { bool: { must: checkBoxFilters } }, - }, - }, - ]; + query.bool.must = [{ nested: { path: 'additional_filters', query: { bool: { must: checkBoxFilters } } } }]; } if (a1?.length) { @@ -129,19 +109,13 @@ const getQueryString = (params: SearchParams, page: number) => { if (weighted_education?.length) { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 - const dropdownFilters: any = getDropdownFilters( - weighted_education, - 'ontologyword_details_clarifications', - ); + const dropdownFilters: any = getDropdownFilters(weighted_education, 'ontologyword_details_clarifications'); query.bool.must?.push(...dropdownFilters); } if (bilingual_education?.length) { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 - const dropdownFilters: any = getDropdownFilters( - bilingual_education, - 'ontologyword_ids', - ); + const dropdownFilters: any = getDropdownFilters(bilingual_education, 'ontologyword_ids'); query.bool.must?.push(...dropdownFilters); } diff --git a/src/js/react/apps/school-search/helpers/ProximityQuery.ts b/src/js/react/apps/school-search/helpers/ProximityQuery.ts index 2efb003f5..97578dbc7 100644 --- a/src/js/react/apps/school-search/helpers/ProximityQuery.ts +++ b/src/js/react/apps/school-search/helpers/ProximityQuery.ts @@ -1,17 +1,11 @@ import type BooleanQuery from '@/types/BooleanQuery'; import AppSettings from '../enum/AppSettings'; -const getQueryString = ( - ids: number[] | null, - coordinates: number[] | null, - page: number, -) => { +const getQueryString = (ids: number[] | null, coordinates: number[] | null, page: number) => { const { size } = AppSettings; const lang = drupalSettings.path.currentLanguage; - const query: BooleanQuery = { - bool: { filter: [{ term: { search_api_language: lang } }] }, - }; + const query: BooleanQuery = { bool: { filter: [{ term: { search_api_language: lang } }] } }; if (ids && Array.isArray(ids)) { query.bool.must = [{ terms: { id: ids } }]; @@ -26,9 +20,9 @@ const getQueryString = ( boost: 1, filter: { term: { - [lang === 'sv' - ? 'additional_filters.swedish_education' - : 'additional_filters.finnish_education']: { value: true }, + [lang === 'sv' ? 'additional_filters.swedish_education' : 'additional_filters.finnish_education']: { + value: true, + }, }, }, }, diff --git a/src/js/react/apps/school-search/hooks/UseFeatureQuery.ts b/src/js/react/apps/school-search/hooks/UseFeatureQuery.ts index 0e514306f..23401024e 100644 --- a/src/js/react/apps/school-search/hooks/UseFeatureQuery.ts +++ b/src/js/react/apps/school-search/hooks/UseFeatureQuery.ts @@ -21,11 +21,7 @@ const UseFeatureQuery = (params: SearchParams) => { }).then((res) => res.json()); }; - const { data, error, isLoading, isValidating } = useSWR( - `_${query || ''}}`, - fetcher, - { revalidateOnFocus: false }, - ); + const { data, error, isLoading, isValidating } = useSWR(`_${query || ''}}`, fetcher, { revalidateOnFocus: false }); return { data, error, isLoading, isValidating }; }; diff --git a/src/js/react/apps/school-search/hooks/UseProximityQuery.ts b/src/js/react/apps/school-search/hooks/UseProximityQuery.ts index 963887e0c..e561b7c36 100644 --- a/src/js/react/apps/school-search/hooks/UseProximityQuery.ts +++ b/src/js/react/apps/school-search/hooks/UseProximityQuery.ts @@ -1,12 +1,7 @@ import { useAtomValue } from 'jotai'; import useSWR from 'swr'; import getNameTranslation from '@/react/common/helpers/ServiceMap'; -import { - getAddresses, - getAddressUrls, - getLocationsUrl, - parseCoordinates, -} from '@/react/common/helpers/SubQueries'; +import { getAddresses, getAddressUrls, getLocationsUrl, parseCoordinates } from '@/react/common/helpers/SubQueries'; import AppSettings from '../enum/AppSettings'; import getQueryString from '../helpers/ProximityQuery'; import { configurationsAtom } from '../store'; @@ -32,10 +27,7 @@ const UseProximityQuery = (params: SearchParams) => { addresses = addresses.filter((address) => address.results.length); if (addresses.length) { - resolvedName = getNameTranslation( - addresses[0].results[0].name, - drupalSettings.path.currentLanguage, - ); + resolvedName = getNameTranslation(addresses[0].results[0].name, drupalSettings.path.currentLanguage); coordinates = parseCoordinates(addresses); } } @@ -46,18 +38,14 @@ const UseProximityQuery = (params: SearchParams) => { if (coordinates?.length) { const [lat, lon] = coordinates; - const locationsResponse = await fetch( - getLocationsUrl(locationsBaseUrl, lat, lon), - ); + const locationsResponse = await fetch(getLocationsUrl(locationsBaseUrl, lat, lon)); const locationsData = await locationsResponse.json(); if (!locationsData || !locationsData.results) { return null; } - ids = locationsData.results.flatMap( - (result: Result) => result.units ?? [], - ); + ids = locationsData.results.flatMap((result: Result) => result.units ?? []); } const result = await fetch(`${baseUrl}/${index}/_search`, { diff --git a/src/js/react/apps/school-search/index.tsx b/src/js/react/apps/school-search/index.tsx index d6d16fda1..e3b4ddec6 100644 --- a/src/js/react/apps/school-search/index.tsx +++ b/src/js/react/apps/school-search/index.tsx @@ -23,11 +23,7 @@ const start = () => { ReactDOM.render(
- - } - > + }> }> diff --git a/src/js/react/apps/school-search/store.tsx b/src/js/react/apps/school-search/store.tsx index c766c6d95..e72d4470e 100644 --- a/src/js/react/apps/school-search/store.tsx +++ b/src/js/react/apps/school-search/store.tsx @@ -10,17 +10,10 @@ type Configurations = { baseUrl: string; }; -export const configurationsAtom = atom({ - error: null, - aggs: {}, - baseUrl: '', +export const configurationsAtom = atom({ error: null, aggs: {}, baseUrl: '' }); +export const setConfigurationsAtom = atom(null, (_get, set, configurations: Configurations) => { + set(configurationsAtom, configurations); }); -export const setConfigurationsAtom = atom( - null, - (_get, set, configurations: Configurations) => { - set(configurationsAtom, configurations); - }, -); export const a1Atom = atom(async (get) => { const { @@ -36,10 +29,7 @@ export const a1Atom = atom(async (get) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 return ontologywordIds?.buckets.reduce((acc: any, currentItem: any) => { if (ontologyDetailsIdsToLang.a1[currentItem.key]) { - acc.push({ - label: ontologyDetailsIdsToLang.a1[currentItem.key], - value: currentItem.key, - }); + acc.push({ label: ontologyDetailsIdsToLang.a1[currentItem.key], value: currentItem.key }); } return acc; @@ -61,10 +51,7 @@ export const a2Atom = atom(async (get) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 return ontologywordIds?.buckets.reduce((acc: any, currentItem: any) => { if (ontologyDetailsIdsToLang.a2[currentItem.key]) { - acc.push({ - label: ontologyDetailsIdsToLang.a2[currentItem.key], - value: currentItem.key, - }); + acc.push({ label: ontologyDetailsIdsToLang.a2[currentItem.key], value: currentItem.key }); } return acc; }, []); @@ -85,10 +72,7 @@ export const b1Atom = atom(async (get) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 return ontologywordIds?.buckets.reduce((acc: any, currentItem: any) => { if (ontologyDetailsIdsToLang.b1[currentItem.key]) { - acc.push({ - label: ontologyDetailsIdsToLang.b1[currentItem.key], - value: currentItem.key, - }); + acc.push({ label: ontologyDetailsIdsToLang.b1[currentItem.key], value: currentItem.key }); } return acc; }, []); @@ -109,10 +93,7 @@ export const b2Atom = atom(async (get) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 return ontologywordIds?.buckets.reduce((acc: any, currentItem: any) => { if (ontologyDetailsIdsToLang.b2[currentItem.key]) { - acc.push({ - label: ontologyDetailsIdsToLang.b2[currentItem.key], - value: currentItem.key, - }); + acc.push({ label: ontologyDetailsIdsToLang.b2[currentItem.key], value: currentItem.key }); } return acc; }, []); @@ -139,9 +120,7 @@ export const weightedEducationAtom = atom(async (get) => { [], ); }); -export const weightedEducationSelectionAtom = atom( - [] as OptionType[], -); +export const weightedEducationSelectionAtom = atom([] as OptionType[]); export const bilingualEducationAtom = atom(async (get) => { const { @@ -157,8 +136,7 @@ export const bilingualEducationAtom = atom(async (get) => { // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 return ontologywordIds?.buckets.reduce((acc: any, currentItem: any) => { if (ontologyDetailsIdsToLang.bilingualEducation[currentItem.key]) { - const label = - ontologyDetailsIdsToLang.bilingualEducation[currentItem.key]; + const label = ontologyDetailsIdsToLang.bilingualEducation[currentItem.key]; // Deduplicate options. // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 @@ -177,29 +155,22 @@ export const bilingualEducationAtom = atom(async (get) => { return acc; }, []); }); -export const bilingualEducationSelectionAtom = atom( - [] as OptionType[], -); +export const bilingualEducationSelectionAtom = atom([] as OptionType[]); export const paramsAtom = atom({}); export const stagedParamsAtom = atom({}); -export const updateParamsAtom = atom( - null, - (_get, set, params: SearchParams) => { - const urlSearchParams: { [key: string]: string } = {}; - Object.keys(params).forEach((key: string) => { - if (key === 'query') { - return; - } +export const updateParamsAtom = atom(null, (_get, set, params: SearchParams) => { + const urlSearchParams: { [key: string]: string } = {}; + Object.keys(params).forEach((key: string) => { + if (key === 'query') { + return; + } - urlSearchParams[key as string] = String( - params[key as keyof SearchParams], - ); - }); - const query = new URLSearchParams(urlSearchParams).toString(); - set(stagedParamsAtom, { ...params, query }); - set(paramsAtom, { ...params, query }); - }, -); + urlSearchParams[key as string] = String(params[key as keyof SearchParams]); + }); + const query = new URLSearchParams(urlSearchParams).toString(); + set(stagedParamsAtom, { ...params, query }); + set(paramsAtom, { ...params, query }); +}); export const keywordAtom = atom(''); diff --git a/src/js/react/common/AddressNotFound.tsx b/src/js/react/common/AddressNotFound.tsx index 68e7560f4..9db1b8af0 100644 --- a/src/js/react/common/AddressNotFound.tsx +++ b/src/js/react/common/AddressNotFound.tsx @@ -1,26 +1,20 @@ import { type ForwardedRef, forwardRef } from 'react'; -export const AddressNotFound = forwardRef( - (_props, ref: ForwardedRef) => ( +export const AddressNotFound = forwardRef((_props, ref: ForwardedRef) => ( +
+
+

+ {Drupal.t('No results for the address entered', {}, { context: 'React search: Address not found title' })} +

+
-
-

- {Drupal.t( - 'No results for the address entered', - {}, - { context: 'React search: Address not found title' }, - )} -

-
-
- - {Drupal.t( - 'Make sure the address is written correctly. You can also search using a nearby street number.', - {}, - { context: 'React search: Address not found hint' }, - )} - -
+ + {Drupal.t( + 'Make sure the address is written correctly. You can also search using a nearby street number.', + {}, + { context: 'React search: Address not found hint' }, + )} +
- ), -); +
+)); diff --git a/src/js/react/common/AddressSearch.tsx b/src/js/react/common/AddressSearch.tsx index 695b4069a..6709d5888 100644 --- a/src/js/react/common/AddressSearch.tsx +++ b/src/js/react/common/AddressSearch.tsx @@ -5,13 +5,8 @@ import type { ServiceMapAddress, ServiceMapResponse } from '@/types/ServiceMap'; import ServiceMap from './enum/ServiceMap'; import getNameTranslation from './helpers/ServiceMap'; -export type AddressWithCoordinates = { - label: string; - value: [number, number, string]; -}; -type SubmitHandler = T extends true - ? (address: AddressWithCoordinates) => void - : (address: string) => void; +export type AddressWithCoordinates = { label: string; value: [number, number, string] }; +type SubmitHandler = T extends true ? (address: AddressWithCoordinates) => void : (address: string) => void; export const AddressSearch = ({ className, @@ -21,11 +16,7 @@ export const AddressSearch = ({ {}, { context: 'Loading finished indicator for suggestive search' }, ), - loadingSpinnerText = Drupal.t( - 'Loading suggestions...', - {}, - { context: 'Loading indicator for suggestive search' }, - ), + loadingSpinnerText = Drupal.t('Loading suggestions...', {}, { context: 'Loading indicator for suggestive search' }), onSubmit, searchInputClassname, value, @@ -35,10 +26,7 @@ export const AddressSearch = ({ includeCoordinates?: boolean; onSubmit: SubmitHandler; searchInputClassname?: string; -} & Omit< - React.ComponentProps, - 'suggestionLabelField' | 'getSuggestions' | 'onSubmit' ->) => { +} & Omit, 'suggestionLabelField' | 'getSuggestions' | 'onSubmit'>) => { const addressMap = new Map(); const getSuggestions = async (searchTerm?: string) => { @@ -65,18 +53,11 @@ export const AddressSearch = ({ ); const [fiParams, svParams] = params; - const results = Promise.all([ - fetchSuggestions(fiParams), - fetchSuggestions(svParams), - ]); + const results = Promise.all([fetchSuggestions(fiParams), fetchSuggestions(svParams)]); - const parseResults = ( - result: ServiceMapResponse, - langKey: string, - ) => + const parseResults = (result: ServiceMapResponse, langKey: string) => result.results.map((addressResult) => { - const resolvedName: string = - getNameTranslation(addressResult.name, langKey) || ''; + const resolvedName: string = getNameTranslation(addressResult.name, langKey) || ''; if (includeCoordinates) { addressMap.set(resolvedName, addressResult.location?.coordinates); } @@ -86,10 +67,7 @@ export const AddressSearch = ({ const [fiResults, svResults] = await results; - const result = [ - ...parseResults(fiResults, 'fi'), - ...parseResults(svResults, 'sv'), - ].slice(0, 10); + const result = [...parseResults(fiResults, 'fi'), ...parseResults(svResults, 'sv')].slice(0, 10); return result; }; @@ -98,9 +76,7 @@ export const AddressSearch = ({ if (includeCoordinates) { onSubmit({ label: address, - value: addressMap.has(address) - ? [...addressMap.get(address), address] - : null, + value: addressMap.has(address) ? [...addressMap.get(address), address] : null, // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 } as any); } else { @@ -113,17 +89,8 @@ export const AddressSearch = ({ const searchInput = useMemo( () => ( {searchInput}
- ); + return
{searchInput}
; }; diff --git a/src/js/react/common/Card.tsx b/src/js/react/common/Card.tsx index b643751a6..d6c013da3 100644 --- a/src/js/react/common/Card.tsx +++ b/src/js/react/common/Card.tsx @@ -5,16 +5,9 @@ import type TagType from '@/types/TagType'; import Icon from './Icon'; import Tags from './Tags'; -export const Metarow = ({ - icon, - label, - content, - langAttribute, -}: MetadataType) => ( +export const Metarow = ({ icon, label, content, langAttribute }: MetadataType) => (
- - {typeof icon === 'string' ? : icon} - + {typeof icon === 'string' ? : icon} {label}: {content} @@ -95,9 +88,7 @@ function CardItem({ ${cardModifierClass ? ` ${cardModifierClass}` : ''} ${cardUrlExternal ? ' card--external' : ''} `; - const HeadingTag = cardTitleLevel - ? (`h${cardTitleLevel}` as keyof JSX.IntrinsicElements) - : 'h4'; + const HeadingTag = cardTitleLevel ? (`h${cardTitleLevel}` as keyof JSX.IntrinsicElements) : 'h4'; return (
@@ -110,12 +101,7 @@ function CardItem({ {cardTitle} ) : ( - + )} {cardCategoryTag && ( @@ -126,57 +112,37 @@ function CardItem({ {cardDescription && (
- {cardDescriptionHtml ? ( - parse(cardDescription) - ) : ( -

{cardDescription}

- )} + {cardDescriptionHtml ? parse(cardDescription) :

{cardDescription}

}
)} {cardHelptext && ( -
- {cardHelptextHtml ? parse(cardHelptext) :

{cardHelptext}

} -
+
{cardHelptextHtml ? parse(cardHelptext) :

{cardHelptext}

}
)}
- {customMetaRows?.top && - customMetaRows.top.length > 0 && - customMetaRows.top} + {customMetaRows?.top && customMetaRows.top.length > 0 && customMetaRows.top} {location && ( )} {distance && ( - + )} {date && ( )} {daterange && ( @@ -184,61 +150,42 @@ function CardItem({ {theme && ( )} {weightedEducation && ( )} {languageEducation && ( )} {language && ( )} {time && ( )} {signUp && ( @@ -246,11 +193,7 @@ function CardItem({ {registrationRequired && ( )} - {customMetaRows?.bottom && - customMetaRows.bottom.length > 0 && - customMetaRows.bottom} + {customMetaRows?.bottom && customMetaRows.bottom.length > 0 && customMetaRows.bottom}
{cardTags && cardTags.length > 0 && ( diff --git a/src/js/react/common/CardImage.tsx b/src/js/react/common/CardImage.tsx index 06377d968..9899e7060 100644 --- a/src/js/react/common/CardImage.tsx +++ b/src/js/react/common/CardImage.tsx @@ -1,8 +1,6 @@ import type { ImgHTMLAttributes } from 'react'; -type CardImageProps = { - photographer?: string; -} & ImgHTMLAttributes; +type CardImageProps = { photographer?: string } & ImgHTMLAttributes; const CardImage = (props: CardImageProps) => { // biome-ignore lint/correctness/noUnusedVariables: @todo UHF-12501 diff --git a/src/js/react/common/CardPicture.tsx b/src/js/react/common/CardPicture.tsx index 177988c43..7c165d90f 100644 --- a/src/js/react/common/CardPicture.tsx +++ b/src/js/react/common/CardPicture.tsx @@ -2,12 +2,7 @@ import type { ImgHTMLAttributes } from 'react'; type ImageUrls = { [key: string]: string }; -type ImageOverride = { - alt?: string; - photographer?: string; - title?: string; - variants: { [key: string]: string }; -}; +type ImageOverride = { alt?: string; photographer?: string; title?: string; variants: { [key: string]: string } }; type CardPictureProps = { photographer?: string; @@ -73,12 +68,7 @@ const CardPicture = (props: CardPictureProps) => { type={source.type} /> ))} - + ); }; diff --git a/src/js/react/common/Collapsible.tsx b/src/js/react/common/Collapsible.tsx index fd78b7f32..a250e6b14 100644 --- a/src/js/react/common/Collapsible.tsx +++ b/src/js/react/common/Collapsible.tsx @@ -32,24 +32,14 @@ function Collapsible({ }: Props) { const [isActive, setActive] = useState(active || false); const ref = useRef(null); - const helperIds = [helper ? `${id}-helper` : undefined, `${id}-title`].filter( - Boolean, - ); + const helperIds = [helper ? `${id}-helper` : undefined, `${id}-title`].filter(Boolean); const getHandle = () => { if (showHandle !== false) { return isActive ? ( - setActive(!isActive)} - /> + setActive(!isActive)} /> ) : ( - setActive(!isActive)} - /> + setActive(!isActive)} /> ); } }; @@ -60,18 +50,12 @@ function Collapsible({ const titleElement = React.createElement( 'span', - { - id: `${id}-title`, - className: `collapsible__title${isPlaceholder ? ' collapsible__title--placeholder' : ''}`, - }, + { id: `${id}-title`, className: `collapsible__title${isPlaceholder ? ' collapsible__title--placeholder' : ''}` }, title, ); return ( -
+
@@ -89,11 +73,7 @@ function Collapsible({ {getHandle()} {isActive && ( -
+
{children}
)} diff --git a/src/js/react/common/CookieComplianceStatement.tsx b/src/js/react/common/CookieComplianceStatement.tsx index 41753e13d..5c78d6bbd 100644 --- a/src/js/react/common/CookieComplianceStatement.tsx +++ b/src/js/react/common/CookieComplianceStatement.tsx @@ -7,26 +7,12 @@ declare global { } } -type CookiCookieComplianceStatementProps = { - host: string; - policyUrl?: string; - sourceUrl?: string; -}; +type CookiCookieComplianceStatementProps = { host: string; policyUrl?: string; sourceUrl?: string }; -const CookieComplianceStatement = ({ - host, - policyUrl, - sourceUrl, -}: CookiCookieComplianceStatementProps) => ( +const CookieComplianceStatement = ({ host, policyUrl, sourceUrl }: CookiCookieComplianceStatementProps) => (
-

- {Drupal.t( - 'Content cannot be displayed', - {}, - { context: 'Cookie compliance' }, - )} -

+

{Drupal.t('Content cannot be displayed', {}, { context: 'Cookie compliance' })}

{Drupal.t( 'This content is hosted by @media_service_url. To see the content, switch over to the external site or modify your cookie settings to allow for preference and statistics cookies.', @@ -40,11 +26,7 @@ const CookieComplianceStatement = ({ data-hds-component='button' data-hds-variant='primary' href={sourceUrl} - title={Drupal.t( - 'See content on external site', - {}, - { context: 'Cookie compliance' }, - )} + title={Drupal.t('See content on external site', {}, { context: 'Cookie compliance' })} /> )} {policyUrl && ( @@ -55,20 +37,13 @@ const CookieComplianceStatement = ({ href={policyUrl} onClick={(event) => { if (typeof window.hdsCookieConsentClickEvent === 'function') { - window.hdsCookieConsentClickEvent( - event.nativeEvent, - event.currentTarget, - ); + window.hdsCookieConsentClickEvent(event.nativeEvent, event.currentTarget); } else { console.warn('hdsCookieConsentClickEvent is not defined'); } }} > - {Drupal.t( - 'Change cookie settings', - {}, - { context: 'Cookie compliance' }, - )} + {Drupal.t('Change cookie settings', {}, { context: 'Cookie compliance' })} )}

diff --git a/src/js/react/common/DateRangeSelect.tsx b/src/js/react/common/DateRangeSelect.tsx index 1230db57d..b4c632984 100644 --- a/src/js/react/common/DateRangeSelect.tsx +++ b/src/js/react/common/DateRangeSelect.tsx @@ -7,22 +7,14 @@ import Collapsible from './Collapsible'; import { HDS_DATE_FORMAT } from './enum/HDSDateFormat'; import getDateString from './helpers/GetDateString'; -const dateHelperText = Drupal.t( - 'Use the format D.M.YYYY', - {}, - { context: 'React search: date range select' }, -); -const getDateTimeFromHDSFormat = (d: string): DateTime => - DateTime.fromFormat(d, HDS_DATE_FORMAT, { locale: 'fi' }); +const dateHelperText = Drupal.t('Use the format D.M.YYYY', {}, { context: 'React search: date range select' }); +const getDateTimeFromHDSFormat = (d: string): DateTime => DateTime.fromFormat(d, HDS_DATE_FORMAT, { locale: 'fi' }); // End date must be after start date. But only if both are defined. const isOutOfRange = ({ endDate, startDate }: DateSelectDateTimes): boolean => !!(startDate && endDate && startDate.startOf('day') >= endDate.endOf('day')); -type DateSelectDateTimes = { - startDate: DateTime | undefined; - endDate: DateTime | undefined; -}; +type DateSelectDateTimes = { startDate: DateTime | undefined; endDate: DateTime | undefined }; // Date must be in within the next 1000 years or so.... // This also validates that the string is not too long even though it might be valid. @@ -37,25 +29,13 @@ const INVALID_DATE = (dt: DateTime | undefined): boolean => { }; export const DateRangeSelect = ({ - dialogLabel = Drupal.t( - 'Choose date', - {}, - { context: 'React search: date range select' }, - ), + dialogLabel = Drupal.t('Choose date', {}, { context: 'React search: date range select' }), endDate, endDateHelperText = dateHelperText, endDateId = 'end-date', - endDateLabel = Drupal.t( - 'Last day of the time period', - {}, - { context: 'React search: date range select' }, - ), + endDateLabel = Drupal.t('Last day of the time period', {}, { context: 'React search: date range select' }), endDisabled, - helperText = Drupal.t( - 'Select a time period for the event', - {}, - { context: 'React search: date range select' }, - ), + helperText = Drupal.t('Select a time period for the event', {}, { context: 'React search: date range select' }), id, label, language = 'fi', @@ -65,11 +45,7 @@ export const DateRangeSelect = ({ startDate, startDateHelperText = dateHelperText, startDateId = 'start-date', - startDateLabel = Drupal.t( - 'First day of the time period', - {}, - { context: 'React search: date range select' }, - ), + startDateLabel = Drupal.t('First day of the time period', {}, { context: 'React search: date range select' }), // biome-ignore lint/correctness/noUnusedFunctionParameters: @todo UHF-12501 title, }: { @@ -95,20 +71,12 @@ export const DateRangeSelect = ({ const [errors, setErrors] = useState<{ start?: string; end?: string }>({}); const collapsibleTitleText = getDateString({ - endDate: endDate - ? DateTime.fromFormat(endDate, HDS_DATE_FORMAT, { locale: 'fi' }) - : undefined, - startDate: startDate - ? DateTime.fromFormat(startDate, HDS_DATE_FORMAT, { locale: 'fi' }) - : undefined, + endDate: endDate ? DateTime.fromFormat(endDate, HDS_DATE_FORMAT, { locale: 'fi' }) : undefined, + startDate: startDate ? DateTime.fromFormat(startDate, HDS_DATE_FORMAT, { locale: 'fi' }) : undefined, }); const collapsibleTitleSRText = getDateString({ - endDate: endDate - ? DateTime.fromFormat(endDate, HDS_DATE_FORMAT, { locale: 'fi' }) - : undefined, - startDate: startDate - ? DateTime.fromFormat(startDate, HDS_DATE_FORMAT, { locale: 'fi' }) - : undefined, + endDate: endDate ? DateTime.fromFormat(endDate, HDS_DATE_FORMAT, { locale: 'fi' }) : undefined, + startDate: startDate ? DateTime.fromFormat(startDate, HDS_DATE_FORMAT, { locale: 'fi' }) : undefined, showLabels: true, }); const collapsibleTitleSRLabel = Drupal.t( @@ -123,16 +91,8 @@ export const DateRangeSelect = ({ ); - const startDateErrorText = Drupal.t( - 'Invalid start date', - {}, - { context: 'React search: date range select' }, - ); - const endDateErrorText = Drupal.t( - 'Invalid end date', - {}, - { context: 'React search: date range select' }, - ); + const startDateErrorText = Drupal.t('Invalid start date', {}, { context: 'React search: date range select' }); + const endDateErrorText = Drupal.t('Invalid end date', {}, { context: 'React search: date range select' }); const onStartChange = (d: string) => { const end = endDate ? getDateTimeFromHDSFormat(endDate) : undefined; @@ -172,9 +132,7 @@ export const DateRangeSelect = ({ } } else { if (isOutOfRange({ startDate: start, endDate: end }) && start) { - console.warn( - 'Selected end date is out of range, setting end date to next day after start date.', - ); + console.warn('Selected end date is out of range, setting end date to next day after start date.'); setEnd(start.toFormat(HDS_DATE_FORMAT)); } else { setEnd(end.toFormat(HDS_DATE_FORMAT)); diff --git a/src/js/react/common/ExternalLink.tsx b/src/js/react/common/ExternalLink.tsx index b8aa6fafb..3b4a55829 100644 --- a/src/js/react/common/ExternalLink.tsx +++ b/src/js/react/common/ExternalLink.tsx @@ -21,18 +21,10 @@ const ExternalLink = ({ }; return ( - + {title} - {!dataHdsComponent && ( - - )} + {!dataHdsComponent && } {Drupal.t( 'Link leads to external service', diff --git a/src/js/react/common/FilterButton.tsx b/src/js/react/common/FilterButton.tsx index 2b8e4c1ae..dd3ec2626 100644 --- a/src/js/react/common/FilterButton.tsx +++ b/src/js/react/common/FilterButton.tsx @@ -1,16 +1,10 @@ import { Tag, TagSize } from 'hds-react'; import type { CSSProperties, MouseEventHandler } from 'react'; -type FilterButtonProps = { - value: string; - clearSelection: MouseEventHandler; -}; +type FilterButtonProps = { value: string; clearSelection: MouseEventHandler }; const FilterButton = ({ value, clearSelection }: FilterButtonProps) => ( -
  • +
  • ( +export const GhostList = ({ bordered = false, count }: { bordered?: boolean; count: number }) => (
    - {Drupal.t( - 'Search results are loading', - {}, - { context: 'React search: results loading' }, - )} + {Drupal.t('Search results are loading', {}, { context: 'React search: results loading' })}
    {Array.from(Array(count)).map((_, i) => ( // biome-ignore lint/suspicious/noArrayIndexKey: @todo UHF-12501 diff --git a/src/js/react/common/LoadingOverlay.tsx b/src/js/react/common/LoadingOverlay.tsx index 9e7bd23db..5868d7200 100644 --- a/src/js/react/common/LoadingOverlay.tsx +++ b/src/js/react/common/LoadingOverlay.tsx @@ -1,17 +1,9 @@ import { LoadingSpinner } from 'hds-react'; const LoadingOverlay = () => ( -
    +
    - {Drupal.t( - 'Search results are loading', - {}, - { context: 'React search: results loading' }, - )} + {Drupal.t('Search results are loading', {}, { context: 'React search: results loading' })}
    diff --git a/src/js/react/common/Pagination.tsx b/src/js/react/common/Pagination.tsx index 05149f59d..65b7f4e40 100644 --- a/src/js/react/common/Pagination.tsx +++ b/src/js/react/common/Pagination.tsx @@ -30,17 +30,8 @@ const getPagination = (current: number, pages: number, totalPages: number) => { return { prevPages, nextPages }; }; -export const Pagination = ({ - updatePage, - currentPage, - pages, - totalPages, -}: PaginationProps) => { - const { prevPages, nextPages } = getPagination( - currentPage, - pages, - totalPages, - ); +export const Pagination = ({ updatePage, currentPage, pages, totalPages }: PaginationProps) => { + const { prevPages, nextPages } = getPagination(currentPage, pages, totalPages); const prevPageExists = currentPage > 1; const nextPageExists = currentPage < totalPages; const firstWithinRange = prevPages.includes(1) || !prevPages.length; @@ -50,16 +41,8 @@ export const Pagination = ({
  • {prevPages[0] - 1 > 0 && ( -
  • - - … - +
  • +
  • )} @@ -145,11 +109,7 @@ export const Pagination = ({ // biome-ignore lint/suspicious/noArrayIndexKey: @todo UHF-12501
  • updatePage(e, pageIndex)} @@ -160,10 +120,7 @@ export const Pagination = ({
  • ))}
  • - + {currentPage}
  • @@ -171,11 +128,7 @@ export const Pagination = ({ // biome-ignore lint/suspicious/noArrayIndexKey: @todo UHF-12501
  • updatePage(e, pageIndex)} @@ -220,15 +173,8 @@ export const Pagination = ({ rel='next' role='button' > - @@ -243,15 +189,8 @@ export const Pagination = ({ )} type='button' > -
  • diff --git a/src/js/react/common/Tags.tsx b/src/js/react/common/Tags.tsx index fa68eca29..cab0d0700 100644 --- a/src/js/react/common/Tags.tsx +++ b/src/js/react/common/Tags.tsx @@ -10,15 +10,8 @@ interface TagsProps { insideCard?: boolean; } -export function Tags({ - tags, - isInteractive, - langAttribute, - insideCard, -}: TagsProps): JSX.Element { - const typeClass = isInteractive - ? 'content-tags__tags--interactive' - : 'content-tags__tags--static'; +export function Tags({ tags, isInteractive, langAttribute, insideCard }: TagsProps): JSX.Element { + const typeClass = isInteractive ? 'content-tags__tags--interactive' : 'content-tags__tags--static'; // When inside a card, use a div instead of a section to avoid duplicating the aria-label description on each card. const Element = insideCard ? 'div' : 'section'; @@ -47,10 +40,7 @@ export function Tags({ > {/* @todo UHF-11117 Check if this works after react is updated */} {/* @ts-ignore */} - + {item.tag} diff --git a/src/js/react/common/constants/textInputStyle.ts b/src/js/react/common/constants/textInputStyle.ts index 3ee286543..70557cf79 100644 --- a/src/js/react/common/constants/textInputStyle.ts +++ b/src/js/react/common/constants/textInputStyle.ts @@ -2,6 +2,4 @@ import type { Properties } from 'csstype'; type CSSWithVars = Properties & Record; -export const defaultTextInputStyle: CSSWithVars = { - '--color-focus-outline': 'var(--color-coat-of-arms)', -}; +export const defaultTextInputStyle: CSSWithVars = { '--color-focus-outline': 'var(--color-coat-of-arms)' }; diff --git a/src/js/react/common/helpers/GetCurrentLanguage.ts b/src/js/react/common/helpers/GetCurrentLanguage.ts index 2c9ad29ac..7326cc21f 100644 --- a/src/js/react/common/helpers/GetCurrentLanguage.ts +++ b/src/js/react/common/helpers/GetCurrentLanguage.ts @@ -1,8 +1,6 @@ // helpers/getCurrentLanguage.ts export type SupportedLanguage = 'fi' | 'sv' | 'en'; -export function getCurrentLanguage( - lang: string | undefined, -): SupportedLanguage { +export function getCurrentLanguage(lang: string | undefined): SupportedLanguage { return lang === 'fi' || lang === 'sv' || lang === 'en' ? lang : 'fi'; } diff --git a/src/js/react/common/helpers/GetDateString.ts b/src/js/react/common/helpers/GetDateString.ts index f1b9354bc..80831f22a 100644 --- a/src/js/react/common/helpers/GetDateString.ts +++ b/src/js/react/common/helpers/GetDateString.ts @@ -1,33 +1,21 @@ import type DateSelectDateTimes from '@/types/DateSelectDateTimes'; import { HDS_DATE_FORMAT } from '../enum/HDSDateFormat'; -export const getDateString = ({ - startDate, - endDate, - showLabels, -}: DateSelectDateTimes): string => { +export const getDateString = ({ startDate, endDate, showLabels }: DateSelectDateTimes): string => { if ((!startDate || !startDate.isValid) && (!endDate || !endDate.isValid)) { return Drupal.t('All dates', {}, { context: 'Events search' }); } if (startDate?.isValid && (!endDate || !endDate.isValid)) { if (showLabels) { - return Drupal.t( - 'From @date', - { '@date': startDate.toFormat(HDS_DATE_FORMAT) }, - { context: 'Events search' }, - ); + return Drupal.t('From @date', { '@date': startDate.toFormat(HDS_DATE_FORMAT) }, { context: 'Events search' }); } return startDate.toFormat(HDS_DATE_FORMAT); } if ((!startDate || !startDate.isValid) && endDate?.isValid) { if (showLabels) { - return Drupal.t( - 'Until @date', - { '@date': endDate.toFormat(HDS_DATE_FORMAT) }, - { context: 'Events search' }, - ); + return Drupal.t('Until @date', { '@date': endDate.toFormat(HDS_DATE_FORMAT) }, { context: 'Events search' }); } return `- ${endDate.toFormat(HDS_DATE_FORMAT)}`; } @@ -35,10 +23,7 @@ export const getDateString = ({ if (showLabels) { return Drupal.t( 'From @date until @date2', - { - '@date': startDate?.toFormat(HDS_DATE_FORMAT), - '@date2': endDate?.toFormat(HDS_DATE_FORMAT), - }, + { '@date': startDate?.toFormat(HDS_DATE_FORMAT), '@date2': endDate?.toFormat(HDS_DATE_FORMAT) }, { context: 'Events search' }, ); } diff --git a/src/js/react/common/helpers/HDS.ts b/src/js/react/common/helpers/HDS.ts index 53ef46466..fb654c9d4 100644 --- a/src/js/react/common/helpers/HDS.ts +++ b/src/js/react/common/helpers/HDS.ts @@ -24,15 +24,9 @@ export const clearAllSelectionsFromStorage = (storage: HDSStorage) => { storage.render(); }; -export const updateSelectionsInStorage = ( - storage: HDSStorage, - selections: OptionType[], -) => { +export const updateSelectionsInStorage = (storage: HDSStorage, selections: OptionType[]) => { storage.updateAllOptions((option, _group, _groupindex) => { - if ( - option.selected && - !selections.some((selection) => selection.value === option.value) - ) { + if (option.selected && !selections.some((selection) => selection.value === option.value)) { return { ...option, selected: false }; } return option; diff --git a/src/js/react/common/helpers/Params.ts b/src/js/react/common/helpers/Params.ts index b295b25b5..83344f739 100644 --- a/src/js/react/common/helpers/Params.ts +++ b/src/js/react/common/helpers/Params.ts @@ -1,9 +1,6 @@ import type OptionType from '@/types/OptionType'; -const transformDropdownsValues = ( - paramOptions: string[] | undefined = [], - availableOptions: OptionType[] = [], -) => { +const transformDropdownsValues = (paramOptions: string[] | undefined = [], availableOptions: OptionType[] = []) => { const transformedOptions: OptionType[] = []; paramOptions.forEach((selection: string) => { diff --git a/src/js/react/common/helpers/ServiceMap.ts b/src/js/react/common/helpers/ServiceMap.ts index 4de9791ce..4c7a33451 100644 --- a/src/js/react/common/helpers/ServiceMap.ts +++ b/src/js/react/common/helpers/ServiceMap.ts @@ -1,9 +1,6 @@ import type { TranslatedString } from '@/types/ServiceMap'; -export const getNameTranslation = ( - names: TranslatedString, - language: string | null, -) => { +export const getNameTranslation = (names: TranslatedString, language: string | null) => { if (language && names[language as 'fi' | 'sv' | 'en']) { return names[language as 'fi' | 'sv' | 'en']; } diff --git a/src/js/react/common/helpers/SubQueries.ts b/src/js/react/common/helpers/SubQueries.ts index 12709f332..6f88d6dbb 100644 --- a/src/js/react/common/helpers/SubQueries.ts +++ b/src/js/react/common/helpers/SubQueries.ts @@ -17,28 +17,18 @@ export const getAddressUrls = (address: string) => { }); }; -export const getAddresses = ( - urls: string[], -): Promise[]> => { - const promises = urls.map(async (url: string) => - fetch(url).then((res) => res.json()), - ); +export const getAddresses = (urls: string[]): Promise[]> => { + const promises = urls.map(async (url: string) => fetch(url).then((res) => res.json())); return Promise.all(promises); }; -export const parseCoordinates = ( - addressData: ServiceMapResponse[], -) => { +export const parseCoordinates = (addressData: ServiceMapResponse[]) => { const [lon, lat]: number[] = addressData[0].results[0].location.coordinates; return [lat, lon]; }; -export const getLocationsUrl = ( - locationsBaseUrl: string, - lat: number | undefined, - lon: number | undefined, -) => { +export const getLocationsUrl = (locationsBaseUrl: string, lat: number | undefined, lon: number | undefined) => { const url = new URL(locationsBaseUrl); const params = new URLSearchParams(url.search); diff --git a/src/js/react/common/hooks/useAddressToCoordsQuery.ts b/src/js/react/common/hooks/useAddressToCoordsQuery.ts index de43d1edd..624644701 100644 --- a/src/js/react/common/hooks/useAddressToCoordsQuery.ts +++ b/src/js/react/common/hooks/useAddressToCoordsQuery.ts @@ -32,13 +32,12 @@ const useAddressToCoordsQuery = async ( }), ); - const results: Array>> = - params.map((param) => { - const url = new URL(ServiceMap.EVENTS_URL); - url.search = param.toString(); + const results: Array>> = params.map((param) => { + const url = new URL(ServiceMap.EVENTS_URL); + url.search = param.toString(); - return fetch(url.toString()).then((response) => response.json()); - }); + return fetch(url.toString()).then((response) => response.json()); + }); const settled = await Promise.allSettled(results); const fulfilled = settled.filter( @@ -47,15 +46,10 @@ const useAddressToCoordsQuery = async ( ); const coordinates: Array<[number, number, string]> = ( - fulfilled as Array< - PromiseFulfilledResult> - > + fulfilled as Array>> ).map((result) => [ ...result.value.results[0].location.coordinates, - getNameTranslation( - result.value.results[0].name, - drupalSettings.path.currentLanguage, - ) || '', + getNameTranslation(result.value.results[0].name, drupalSettings.path.currentLanguage) || '', ]); return coordinates.length ? coordinates[0] : null; diff --git a/src/js/react/common/hooks/useOutsideClick.tsx b/src/js/react/common/hooks/useOutsideClick.tsx index b1cf460d9..f358a365e 100644 --- a/src/js/react/common/hooks/useOutsideClick.tsx +++ b/src/js/react/common/hooks/useOutsideClick.tsx @@ -4,9 +4,7 @@ import { type MutableRefObject, useCallback, useEffect } from 'react'; // biome-ignore lint/suspicious/noExplicitAny: @todo UHF-12501 // biome-ignore lint/complexity/noBannedTypes: @todo UHF-12501 const useOutsideClick = (ref: MutableRefObject, callback: Function) => { - const isChild = useCallback((event) => - ref.current?.contains(event.target as Node), - ); + const isChild = useCallback((event) => ref.current?.contains(event.target as Node)); useEffect(() => { const handleClick = (event: MouseEvent | FocusEvent) => { diff --git a/src/js/react/common/hooks/useScrollToResults.ts b/src/js/react/common/hooks/useScrollToResults.ts index aaa01208e..cf4f37753 100644 --- a/src/js/react/common/hooks/useScrollToResults.ts +++ b/src/js/react/common/hooks/useScrollToResults.ts @@ -1,9 +1,6 @@ import { type RefObject, useEffect } from 'react'; -const useScrollToResults = ( - ref: RefObject, - shouldScrollOnRender: boolean, -) => { +const useScrollToResults = (ref: RefObject, shouldScrollOnRender: boolean) => { useEffect(() => { const { current } = ref; diff --git a/src/js/searchHelper.js b/src/js/searchHelper.js index d1b4904e0..785e0b0e7 100644 --- a/src/js/searchHelper.js +++ b/src/js/searchHelper.js @@ -23,9 +23,7 @@ // Focus to the result count element. This is usually used in // views based searches. - const resultCountEl = context.querySelector( - '[class$="__count-container"]', - ); + const resultCountEl = context.querySelector('[class$="__count-container"]'); focusElement(resultCountEl); }, }; diff --git a/src/js/sidebarMenuToggle.js b/src/js/sidebarMenuToggle.js index 2697b0178..ffcde1ed3 100644 --- a/src/js/sidebarMenuToggle.js +++ b/src/js/sidebarMenuToggle.js @@ -7,9 +7,7 @@ const toggleSidebarMenuVisibility = (item, cssClass) => { item.classList.toggle(cssClass); toggleButton.setAttribute( 'aria-expanded', - toggleButton.getAttribute('aria-expanded') === 'true' - ? 'false' - : 'true', + toggleButton.getAttribute('aria-expanded') === 'true' ? 'false' : 'true', ); event.stopPropagation(); }); @@ -24,23 +22,16 @@ const toggleSidebarMenuVisibility = (item, cssClass) => { const sidebarNavigation = context.querySelector('.sidebar-navigation'); if (sidebarNavigation) { - const itemsWithChildren = sidebarNavigation.querySelectorAll( - '.menu__item--children', - ); + const itemsWithChildren = sidebarNavigation.querySelectorAll('.menu__item--children'); itemsWithChildren.forEach((item) => { toggleSidebarMenuVisibility(item, 'menu__item--open'); }); } // In case of section navigation find the section navigation. - const sectionNavigations = context.querySelectorAll( - '.sidebar-navigation--section-navigation', - ); + const sectionNavigations = context.querySelectorAll('.sidebar-navigation--section-navigation'); sectionNavigations.forEach((item) => { - toggleSidebarMenuVisibility( - item, - 'sidebar-navigation--section-navigation--open', - ); + toggleSidebarMenuVisibility(item, 'sidebar-navigation--section-navigation--open'); }); }, }; diff --git a/src/js/tabs.js b/src/js/tabs.js index 65b43f8c4..c438bdaf8 100644 --- a/src/js/tabs.js +++ b/src/js/tabs.js @@ -19,9 +19,7 @@ const tabParent = tab.closest('[data-drupal-selector="tabbed-content"]'); const tabsContentId = tab.getAttribute('aria-controls'); if (!tabsContentId) return; - const tabsContent = document.querySelector( - `[data-drupal-selector="${tabsContentId}"]`, - ); + const tabsContent = document.querySelector(`[data-drupal-selector="${tabsContentId}"]`); // First hide all tabs. hideEverything(tabParent); @@ -51,9 +49,7 @@ } function initiateTabs(activeTab, activeContent) { - const containers = document.querySelectorAll( - '[data-drupal-selector="tabbed-content"]', - ); + const containers = document.querySelectorAll('[data-drupal-selector="tabbed-content"]'); // Guard clause if no containers found if (!containers.length) return; @@ -71,12 +67,8 @@ } // Find the active tab elements. - const activeTabElement = document.querySelector( - `[data-drupal-selector="${activeTab}"]`, - ); - const activeContentElement = document.querySelector( - `[data-drupal-selector="${activeContent}"]`, - ); + const activeTabElement = document.querySelector(`[data-drupal-selector="${activeTab}"]`); + const activeContentElement = document.querySelector(`[data-drupal-selector="${activeContent}"]`); // Guard clause if elements not found if (!activeTabElement || !activeContentElement) { diff --git a/src/js/throbber.js b/src/js/throbber.js index c79336082..5e1e709b3 100644 --- a/src/js/throbber.js +++ b/src/js/throbber.js @@ -1,5 +1,4 @@ -Drupal.theme.ajaxProgressThrobber = () => - '
    '; +Drupal.theme.ajaxProgressThrobber = () => '
    '; Drupal.theme.ajaxProgressIndicatorFullscreen = () => '
    '; diff --git a/src/js/types/BooleanQuery.ts b/src/js/types/BooleanQuery.ts index dce129260..286b7ef0c 100644 --- a/src/js/types/BooleanQuery.ts +++ b/src/js/types/BooleanQuery.ts @@ -1,11 +1,6 @@ /** biome-ignore-all lint/suspicious/noExplicitAny: @todo UHF-12501 */ type BooleanQuery = { - bool: { - filter?: Array; - must?: Array; - should?: Array; - minimum_should_match?: number; - }; + bool: { filter?: Array; must?: Array; should?: Array; minimum_should_match?: number }; }; export default BooleanQuery; diff --git a/src/js/types/Result.ts b/src/js/types/Result.ts index fd5bb8d94..ee0acc8df 100644 --- a/src/js/types/Result.ts +++ b/src/js/types/Result.ts @@ -4,13 +4,7 @@ interface Result { _score: string; _source: Type; inner_hits: { - [key: string]: { - hits: { - total: { value: number; relation: string }; - max_score: number; - hits: Result[]; - }; - }; + [key: string]: { hits: { total: { value: number; relation: string }; max_score: number; hits: Result[] } }; }; } diff --git a/src/js/types/ServiceMap.ts b/src/js/types/ServiceMap.ts index ce95352d6..c34ec73b1 100644 --- a/src/js/types/ServiceMap.ts +++ b/src/js/types/ServiceMap.ts @@ -59,9 +59,4 @@ export type AdministrativeDivision = { units: number[]; }; -export type ServiceMapResponse = { - count: number; - next: string | null; - previous: string | null; - results: T[]; -}; +export type ServiceMapResponse = { count: number; next: string | null; previous: string | null; results: T[] }; diff --git a/src/js/types/drupal.d.ts b/src/js/types/drupal.d.ts index 77fcd9d5f..4c2c97e94 100644 --- a/src/js/types/drupal.d.ts +++ b/src/js/types/drupal.d.ts @@ -6,12 +6,6 @@ declare namespace Drupal { setAcceptedCategories: (categories: string[]) => void; }; function t(str: string, options?: object, context?: object); - function formatPlural( - count: string, - singular: string, - plural: string, - args?: object, - options?: object, - ); + function formatPlural(count: string, singular: string, plural: string, args?: object, options?: object); function theme(id: string); } diff --git a/src/js/types/drupalSettings.d.ts b/src/js/types/drupalSettings.d.ts index a97d160d5..30b1e79dd 100644 --- a/src/js/types/drupalSettings.d.ts +++ b/src/js/types/drupalSettings.d.ts @@ -17,9 +17,7 @@ declare namespace drupalSettings { field_remote_events: boolean; field_filter_keywords: { id: string; name: string }[]; hidePagination: boolean; - places: { - [key: string]: { id: string; name: { [key: string]: string } }; - }; + places: { [key: string]: { id: string; name: { [key: string]: string } } }; hideHeading: boolean; removeBloatingEvents: boolean; use_fixtures: boolean; @@ -33,11 +31,7 @@ declare namespace drupalSettings { seeAllNearYouLink: string; cardsWithBorders: boolean; }; - const helfi_react_search: { - elastic_proxy_url: string; - sentry_dsn_react: string; - hakuvahti_url_set: boolean; - }; + const helfi_react_search: { elastic_proxy_url: string; sentry_dsn_react: string; hakuvahti_url_set: boolean }; const helfi_rekry_job_search: { results_page_path: string; hakuvahti_tos_checkbox_label: string; diff --git a/theme-builder/biome.json b/theme-builder/biome.json index 0b2a92d22..784d51c43 100644 --- a/theme-builder/biome.json +++ b/theme-builder/biome.json @@ -35,7 +35,12 @@ "style": { "noUnusedTemplateLiteral": "warn", "useImportType": "warn" } } }, - "formatter": { "enabled": true, "expand": "never", "useEditorconfig": true }, + "formatter": { + "enabled": true, + "expand": "auto", + "lineWidth": 120, + "useEditorconfig": true + }, "javascript": { "formatter": { "quoteStyle": "single",