Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
embl.org
html-sites
embl-jobs-pages
Commits
c335d234
Commit
c335d234
authored
Sep 15, 2021
by
Nitin Jadhav
Browse files
various fixes
parent
0c46b7f2
Pipeline
#193908
passed with stages
in 4 minutes and 23 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
505 additions
and
280 deletions
+505
-280
src/app/App.jsx
src/app/App.jsx
+67
-64
src/app/AppContext.js
src/app/AppContext.js
+6
-0
src/component-templates/VFBreadcrumbs.jsx
src/component-templates/VFBreadcrumbs.jsx
+2
-2
src/component-templates/VFCard.jsx
src/component-templates/VFCard.jsx
+2
-2
src/component-templates/VFHero.jsx
src/component-templates/VFHero.jsx
+1
-1
src/component-templates/VFSearchBox.jsx
src/component-templates/VFSearchBox.jsx
+7
-1
src/components/EBICards.jsx
src/components/EBICards.jsx
+2
-2
src/components/alerts/Alerts.jsx
src/components/alerts/Alerts.jsx
+264
-173
src/components/content/work-at-embl/GroupLeaderRecruitment.jsx
...omponents/content/work-at-embl/GroupLeaderRecruitment.jsx
+74
-25
src/components/home/EMBLHome.jsx
src/components/home/EMBLHome.jsx
+60
-10
src/helpers/helpers.js
src/helpers/helpers.js
+8
-0
src/vf-components/vf-local-overrides/vf-local-overrides.scss
src/vf-components/vf-local-overrides/vf-local-overrides.scss
+12
-0
No files found.
src/app/App.jsx
View file @
c335d234
...
...
@@ -21,75 +21,78 @@ import { WorkAtEmbl } from "../components/content/work-at-embl/WorkAtEmbl";
import
{
EBIHome
}
from
"
../components/home/EBIHome
"
;
import
{
EMBLHome
}
from
"
../components/home/EMBLHome
"
;
import
"
./App.scss
"
;
import
{
AppContext
,
isEBISite
,
orgName
}
from
"
./AppContext
"
;
export
function
App
()
{
return
(
<
Router
basename
=
"jobs"
>
<
Metadata
/>
<
div
className
=
"vf-body"
>
<
Switch
>
<
Route
exact
path
=
"/"
component
=
{
EMBLHome
}
/>
<
Route
path
=
{
[
"
/position/:jobRef
"
]
}
component
=
{
JobDetails
}
/>
<
Route
path
=
"/apply"
component
=
{
Apply
}
/>
<
Route
path
=
"/partners"
component
=
{
Partners
}
/>
<
AppContext
.
Provider
value
=
{
(
isEBISite
,
orgName
)
}
>
<
Router
basename
=
"jobs"
>
<
Metadata
/>
<
div
className
=
"vf-body"
>
<
Switch
>
<
Route
exact
path
=
"/"
component
=
{
EMBLHome
}
/>
<
Route
path
=
{
[
"
/position/:jobRef
"
]
}
component
=
{
JobDetails
}
/>
<
Route
path
=
"/apply"
component
=
{
Apply
}
/>
<
Route
path
=
"/partners"
component
=
{
Partners
}
/>
<
Route
path
=
"/alerts/alert-email/:jobRef"
render
=
{
({
match
})
=>
(
<
EmailAlertRedirects
jobId
=
{
match
.
params
.
jobRef
}
/>
)
}
/>
<
Route
path
=
"/alerts"
component
=
{
Alerts
}
/>
<
Route
path
=
"/alerts/alert-email/:jobRef"
render
=
{
({
match
})
=>
(
<
EmailAlertRedirects
jobId
=
{
match
.
params
.
jobRef
}
/>
)
}
/>
<
Route
path
=
"/alerts"
component
=
{
Alerts
}
/>
<
Route
path
=
"/ebi/iframe"
component
=
{
EBIHome
}
/>
<
Route
path
=
"/hr-excellence-in-research"
component
=
{
HrExcellenceInResearch
}
/>
<
Route
path
=
"/science4refugees"
component
=
{
Science4Refugees
}
/>
<
Route
path
=
"/work-at-embl/group-leader-recruitment"
component
=
{
GroupLeaderRecruitment
}
/>
<
Route
exact
path
=
"/work-at-embl"
component
=
{
WorkAtEmbl
}
/>
<
Route
exact
path
=
"/work-at-embl/conditions-employment"
component
=
{
ConditionsEmployment
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/family-life"
component
=
{
FamilyLife
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/financial-support"
component
=
{
FinancialSupport
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/remuneration"
component
=
{
Remuneration
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/social-security"
component
=
{
SocialSecurity
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/training"
component
=
{
Training
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/visa-requirements"
component
=
{
VisaRequirement
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/working-hours-leave"
component
=
{
WorkingHoursLeave
}
/>
<
Route
path
=
"/ebi/iframe"
component
=
{
EBIHome
}
/>
<
Route
path
=
"/hr-excellence-in-research"
component
=
{
HrExcellenceInResearch
}
/>
<
Route
path
=
"/science4refugees"
component
=
{
Science4Refugees
}
/>
<
Route
path
=
"/work-at-embl/group-leader-recruitment"
component
=
{
GroupLeaderRecruitment
}
/>
<
Route
exact
path
=
"/work-at-embl"
component
=
{
WorkAtEmbl
}
/>
<
Route
exact
path
=
"/work-at-embl/conditions-employment"
component
=
{
ConditionsEmployment
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/family-life"
component
=
{
FamilyLife
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/financial-support"
component
=
{
FinancialSupport
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/remuneration"
component
=
{
Remuneration
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/social-security"
component
=
{
SocialSecurity
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/training"
component
=
{
Training
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/visa-requirements"
component
=
{
VisaRequirement
}
/>
<
Route
path
=
"/work-at-embl/conditions-employment/working-hours-leave"
component
=
{
WorkingHoursLeave
}
/>
{
/* default route */
}
<
Route
path
=
"*"
component
=
{
ErrorPage404
}
/>
</
Switch
>
</
div
>
</
Router
>
{
/* default route */
}
<
Route
path
=
"*"
component
=
{
ErrorPage404
}
/>
</
Switch
>
</
div
>
</
Router
>
</
AppContext
.
Provider
>
);
}
src/app/AppContext.js
0 → 100644
View file @
c335d234
import
{
createContext
}
from
"
react
"
;
import
{
getHostWebsite
}
from
"
../helpers/helpers
"
;
export
const
isEBISite
=
getHostWebsite
().
includes
(
"
ebi.ac.uk
"
);
export
const
orgName
=
isEBISite
?
"
EBI
"
:
"
EMBL-EBI
"
;
export
const
AppContext
=
createContext
({
isEBISite
,
orgName
});
src/component-templates/VFBreadcrumbs.jsx
View file @
c335d234
...
...
@@ -22,7 +22,7 @@ export function VFBreadcrumbs({ breadcrumbItems = [], relatedItems = [] }) {
})
}
</
ul
>
{
relatedItems
.
length
&&
(
{
relatedItems
.
length
?
(
<>
<
span
className
=
"vf-breadcrumbs__heading"
>
Related:
</
span
>
<
ul
className
=
"vf-breadcrumbs__list vf-breadcrumbs__list--related | vf-list vf-list--inline"
>
...
...
@@ -35,7 +35,7 @@ export function VFBreadcrumbs({ breadcrumbItems = [], relatedItems = [] }) {
))
}
</
ul
>
</>
)
}
)
:
null
}
</
nav
>
);
}
...
...
src/component-templates/VFCard.jsx
View file @
c335d234
...
...
@@ -66,9 +66,9 @@ export function VFCard({
);
}
VFCard
.
Container
=
function
VFCardContainer
({
children
})
{
VFCard
.
Container
=
function
VFCardContainer
({
children
,
id
=
""
})
{
return
(
<
section
className
=
"vf-card-container"
>
<
section
className
=
"vf-card-container"
id
=
{
id
}
>
<
div
className
=
"vf-card-container__inner"
>
{
children
}
</
div
>
</
section
>
);
...
...
src/component-templates/VFHero.jsx
View file @
c335d234
...
...
@@ -5,7 +5,7 @@ export default function VFHero({
heading
=
""
,
subheading
=
""
,
link_text
=
""
,
link_href
=
"
JavaScript:Void(0);
"
,
link_href
=
""
,
image_url
=
""
,
image_size
=
"
auto 28.5rem
"
,
})
{
...
...
src/component-templates/VFSearchBox.jsx
View file @
c335d234
...
...
@@ -11,7 +11,12 @@ export function VFSearchBox({ value, handleSearchTermUpdate }) {
},
[
value
]);
return
(
<
form
className
=
"vf-form | vf-search vf-search--inline"
>
<
form
className
=
"vf-form | vf-search vf-search--inline"
onSubmit
=
{
(
e
)
=>
{
e
.
preventDefault
();
}
}
>
<
div
className
=
"vf-container__inner"
style
=
{
{
width
:
"
100%
"
}
}
>
<
div
className
=
"vf-form__item | vf-search__item"
>
<
label
...
...
@@ -25,6 +30,7 @@ export function VFSearchBox({ value, handleSearchTermUpdate }) {
type
=
"search"
value
=
{
term
}
onChange
=
{
(
e
)
=>
{
// debugger;
setTerm
(
e
.
target
.
value
);
handleDebouncedUpdate
.
current
(
e
.
target
.
value
);
}
}
...
...
src/components/EBICards.jsx
View file @
c335d234
...
...
@@ -2,7 +2,7 @@ import { VFCard } from "../component-templates/VFCard";
export
function
EBICards
()
{
return
(
<
VFCard
.
Container
>
<
VFCard
.
Container
id
=
"about"
>
<
VFCard
card_image
=
"https://acxngcvroo.cloudimg.io/v7/https://www.embl.org/files/wp-content/uploads/ebi-jobs-campus-south-building.jpg?w=500&h=300&func=crop"
card_image__alt
=
"Aerial image of EMBL-EBI South building on campus"
...
...
@@ -14,7 +14,7 @@ export function EBICards() {
modifiers
=
"vf-card--bordered"
/>
<
VFCard
card_image
=
"https://
acxngcvroo.cloudimg.io/v7/https://wwwdev.ebi.ac.uk/sites/ebi.ac.uk/files/styles/large/public/groups/external_relations/images/Events/all-at-ebi_stepping_down_EBI
.jpg?w=500&h=300&func=crop"
card_image
=
"https://
www.embl.org/editorhub/wp-content/uploads/2021/05/AdobeStock_136016129-768x512
.jp
e
g?w=500&h=300&func=crop"
card_image__alt
=
"EMBL-EBI staff members"
card_heading
=
"Employee benefits"
card_subheading
=
""
...
...
src/components/alerts/Alerts.jsx
View file @
c335d234
import
{
locationsWithCountries
,
positionTypes
}
from
"
data/jobs-data.json
"
;
import
{
useRef
}
from
"
react
"
;
import
{
isEqual
}
from
"
lodash
"
;
import
{
useContext
,
useRef
,
useState
}
from
"
react
"
;
import
{
useForm
}
from
"
react-hook-form
"
;
import
{
AppContext
}
from
"
../../app/AppContext
"
;
import
{
VFBreadcrumbs
}
from
"
../../component-templates/VFBreadcrumbs
"
;
import
{
EMAIL_VALIDATION_REGEX
}
from
"
../../helpers/helpers
"
;
import
{
EmblFooter
}
from
"
../EmblFooter
"
;
import
{
EmblHeader
}
from
"
../EmblHeader
"
;
import
"
./Alerts.scss
"
;
const
locationsWithCountriesValues
=
Object
.
values
(
locationsWithCountries
);
const
positionTypesValues
=
Object
.
keys
(
positionTypes
);
/* Subscription-alerts page, uses react-hook-form */
export
function
Alerts
()
{
const
{
isEBISite
}
=
useContext
(
AppContext
);
const
formRef
=
useRef
();
const
{
register
,
handleSubmit
,
watch
,
formState
:
{
errors
},
setValue
,
}
=
useForm
({
defaultValues
:
{
loc
:
[
"
0
"
],
pos
:
[
"
0
"
],
loc
:
[],
pos
:
[],
},
});
const
[
subscriptionState
,
setSubscriptionState
]
=
useState
(
"
pending
"
);
const
onSubmit
=
()
=>
{
formRef
.
current
.
submit
();
// const formData = new FormData(formRef.current);
// const params = new URLSearchParams(formData);
// fetch(`https://www.embl.de/jobs/searchjobs/index.php?${params.toString()}`)
// .then(() => {
// setSubscriptionSuccess(true);
// })
// .catch(() => {
// setSubscriptionFailure(true);
// });
// formRef.current.submit();
const
formData
=
new
FormData
(
formRef
.
current
);
const
params
=
new
URLSearchParams
(
formData
);
// console.log("params", params);
fetch
(
`https://www.embl.de/jobs/searchjobs/index.php?
${
params
.
toString
()}
`
,
{
method
:
"
GET
"
,
mode
:
"
no-cors
"
,
}
)
.
then
(()
=>
{
setSubscriptionState
(
"
success
"
);
})
.
catch
(()
=>
{
setSubscriptionState
(
"
error
"
);
});
};
/*
...
...
@@ -38,181 +57,253 @@ export function Alerts() {
* object for spreading on the non-all checkboxes.
* Value is based on if the first element is "0" i.e. "All xxx" selected or not
* */
const
allLocationsValue
=
watch
(
"
loc
"
);
const
allLocationSelectedObjectForSpread
=
{
disabled
:
allLocationsValue
&&
allLocationsValue
[
0
]
===
"
0
"
,
};
const
isAllLocationsSelected
=
isEqual
(
allLocationsValue
,
locationsWithCountriesValues
);
const
allPosValue
=
watch
(
"
pos
"
);
const
allPosSelectedObjectForSpread
=
{
disabled
:
allPosValue
&&
allPosValue
[
0
]
===
"
0
"
,
};
const
isAllPositionsSelected
=
isEqual
(
allPosValue
,
positionTypesValues
);
return
(
<>
<
section
className
=
"vf-intro"
id
=
"an-id-for-anchor"
>
<
div
>
{
/* empty */
}
</
div
>
<
div
className
=
"vf-stack vf-stack--400"
>
<
h1
className
=
"vf-intro__heading "
>
EMBL Job alerts
</
h1
>
<
p
className
=
"vf-lede"
>
Get the latest postings in your inbox.
</
p
>
<
p
className
=
"vf-intro__text"
>
Configure your criteria and add your email address to configure your
alert.
{
"
"
}
</
p
>
</
div
>
</
section
>
{
/* form */
}
<
section
className
=
"vf-intro | embl-grid embl-grid--has-centered-content"
>
<
div
>
{
/* empty */
}
</
div
>
<
div
className
=
"vf-content"
>
<
form
action
=
"https://www.embl.de/jobs/searchjobs/index.php"
method
=
"GET"
className
=
"vf-form"
ref
=
{
formRef
}
onSubmit
=
{
handleSubmit
(
onSubmit
)
}
>
<
input
type
=
"hidden"
name
=
"newlang"
value
=
"1"
/>
<
label
htmlFor
=
"email_alert"
className
=
"vf-form__label"
>
Email address
</
label
>
<
input
type
=
"text"
{
...
register
(
"
email_alert
"
,
{
required
:
true
,
pattern
:
EMAIL_VALIDATION_REGEX
,
})
}
id
=
"email_alert"
className
=
{
`vf-form__input
${
errors
.
email_alert
&&
"
vf-form__input--invalid
"
}
`
}
placeholder
=
"email@youraddress.net"
/>
{
errors
.
email_alert
&&
(
<
p
className
=
"vf-form__helper vf-form__helper--error"
>
{
errors
.
email_alert
.
type
===
"
required
"
?
"
Email address is required.
"
:
"
Invalid email address.
"
}
</
p
>
<
EmblHeader
/>
<
VFBreadcrumbs
breadcrumbItems
=
{
[
{
title
:
"
EMBL Jobs
"
,
link
:
"
https://www.embl.org/jobs
"
},
{
title
:
"
Job alerts
"
},
]
}
/>
{
subscriptionState
===
"
success
"
&&
(
<
section
className
=
"vf-intro"
>
<
div
></
div
>
<
div
className
=
"vf-stack"
>
<
h1
className
=
"vf-intro__heading "
>
EMBL Job alerts
</
h1
>
<
p
className
=
"vf-lede"
>
Thank you for subscribing to a job alert!
</
p
>
<
p
className
=
"vf-intro__text"
>
We have sent you an email to confirm your subscription.
</
p
>
{
isEBISite
?
(
<
a
className
=
"vf-button vf-button--primary"
href
=
"https://www.ebi.ac.uk/careers/jobs"
>
View jobs at EMBL-EBI
</
a
>
)
:
(
<
a
className
=
"vf-button vf-button--primary"
href
=
"https://www.embl.org/jobs/"
>
View jobs at EMBL
</
a
>
)
}
</
div
>
</
section
>
)
}
{
subscriptionState
===
"
error
"
&&
(
<
section
className
=
"vf-intro"
>
<
div
></
div
>
<
br
/>
<
div
className
=
"vf-stack"
>
<
h1
className
=
"vf-intro__heading "
>
Error
</
h1
>
<
p
className
=
"vf-lede"
>
There was a technical error.
</
p
>
<
fieldset
className
=
"vf-form__fieldset vf-u-margin__bottom--800"
>
<
legend
className
=
"form-subtitle vf-form__legend"
>
Location
</
legend
>
<
p
className
=
"vf-intro__text"
>
This problem means that the service you are trying to access is
currently unavailable. Please try again later.
</
p
>
</
div
>
</
section
>
)
}
<
div
className
=
"grid"
>
<
div
className
=
"jobs_sel_all vf-form__item vf-form__item--checkbox"
>
<
input
type
=
"checkbox"
className
=
"vf-form__checkbox"
id
=
"sel_all_loc"
value
=
"0"
{
...
register
(
"
loc
"
)
}
/>
<
label
htmlFor
=
"sel_all_loc"
className
=
"vf-form__label"
>
All locations
</
label
>
</
div
>
{
subscriptionState
===
"
pending
"
&&
(
<>
<
section
className
=
"vf-intro"
id
=
"an-id-for-anchor"
>
<
div
>
{
/* empty */
}
</
div
>
<
ul
className
=
"vf-list"
>
{
Object
.
entries
(
locationsWithCountries
).
map
(
([
displayText
,
locationValue
])
=>
(
<
li
key
=
{
locationValue
}
className
=
"vf-form__item vf-form__item--checkbox"
<
div
className
=
"vf-stack vf-stack--400"
>
<
h1
className
=
"vf-intro__heading "
>
EMBL Job alerts
</
h1
>
<
p
className
=
"vf-lede"
>
Get the latest postings in your inbox.
</
p
>
<
p
className
=
"vf-intro__text"
>
Configure your criteria and add your email address to configure
your alert.
{
"
"
}
</
p
>
</
div
>
</
section
>
{
/* form */
}
<
section
className
=
"vf-intro | embl-grid embl-grid--has-centered-content"
>
<
div
>
{
/* empty */
}
</
div
>
<
div
className
=
"vf-content"
>
<
form
action
=
"https://www.embl.de/jobs/searchjobs/index.php"
method
=
"GET"
className
=
"vf-form"
ref
=
{
formRef
}
onSubmit
=
{
handleSubmit
(
onSubmit
)
}
>
<
input
type
=
"hidden"
name
=
"newlang"
value
=
"1"
/>
<
label
htmlFor
=
"email_alert"
className
=
"vf-form__label"
>
Email address
</
label
>
<
input
type
=
"text"
{
...
register
(
"
email_alert
"
,
{
required
:
true
,
pattern
:
EMAIL_VALIDATION_REGEX
,
})
}
id
=
"email_alert"
className
=
{
`vf-form__input
${
errors
.
email_alert
&&
"
vf-form__input--invalid
"
}
`
}
placeholder
=
"email@youraddress.net"
/>
{
errors
.
email_alert
&&
(
<
p
className
=
"vf-form__helper vf-form__helper--error"
>
{
errors
.
email_alert
.
type
===
"
required
"
?
"
Email address is required.
"
:
"
Invalid email address.
"
}
</
p
>
)
}
<
br
/>
<
fieldset
className
=
"vf-form__fieldset vf-u-margin__bottom--800"
>
<
legend
className
=
"form-subtitle vf-form__legend"
>
Location
</
legend
>
<
div
className
=
"vf-u-margin__top--200 vf-u-margin__bottom--400"
>
{
!
isAllLocationsSelected
&&
(
<
button
className
=
"vf-link link-button"
onClick
=
{
()
=>
{
setValue
(
"
loc
"
,
locationsWithCountriesValues
);
}
}
>
Select all locations
</
button
>
)
}
{
isAllLocationsSelected
&&
(
<
button
className
=
"vf-link link-button"
onClick
=
{
()
=>
{
setValue
(
"
loc
"
,
[]);
}
}
>
<
input
type
=
"checkbox"
className
=
"vf-form__checkbox"
id
=
{
"
loc
"
+
locationValue
}
value
=
{
locationValue
}
{
...
register
(
"
loc[]
"
)
}
{
...
allLocationSelectedObjectForSpread
}
/>
<
label
htmlFor
=
{
"
loc
"
+
locationValue
}
className
=
"vf-form__label"
>
{
displayText
}
</
label
>
</
li
>
)
)
}
</
ul
>
</
div
>
</
fieldset
>
<
fieldset
className
=
"fieldset-job vf-form__fieldset"
>
<
legend
className
=
"form-subtitle vf-form__legend"
>
Categories
</
legend
>
<
div
className
=
"grid"
>
<
div
className
=
"col-1-1 jobs_sel_all vf-form__item vf-form__item--checkbox"
>
Clear all locations
</
button
>
)
}
</
div
>
<
div
className
=
"grid"
>
<
ul
className
=
"vf-list"
>
{
Object
.
entries
(
locationsWithCountries
).
map
(
([
displayText
,
locationValue
])
=>
(
<
li
key
=
{
locationValue
}
className
=
"vf-form__item vf-form__item--checkbox"
>
<
input
type
=
"checkbox"
className
=
"vf-form__checkbox"
id
=
{
"
loc
"
+
locationValue
}
value
=
{
locationValue
}
{
...
register
(
"
loc[]
"
)
}
/>
<
label
htmlFor
=
{
"
loc
"
+
locationValue
}
className
=
"vf-form__label"
>
{
displayText
}
</
label
>
</
li
>
)
)
}
</
ul
>
</
div
>
</
fieldset
>
<
fieldset
className
=
"fieldset-job vf-form__fieldset"
>
<
legend
className
=
"form-subtitle vf-form__legend"
>
Categories
</
legend
>
<
div
className
=
"vf-u-margin__top--200 vf-u-margin__bottom--400"
>
{
!
isAllPositionsSelected
&&
(
<
button
className
=
"vf-link link-button"
onClick
=
{
()
=>
{
setValue
(
"
pos
"
,
positionTypesValues
);
}
}
>
Select all categories
</
button
>
)
}
{
isAllPositionsSelected
&&
(
<
button
className
=
"vf-link link-button"
onClick
=
{
()
=>
{
setValue
(
"
pos
"
,
[]);
}
}
>
Clear all categories