commit f30846093153db352e2b021d689127ef8396339e Author: STEINNI Date: Wed Aug 27 07:03:09 2025 +0000 unclean SPARC diff --git a/app/assets/html/mailing/tile.html b/app/assets/html/mailing/tile.html new file mode 100644 index 0000000..466515e --- /dev/null +++ b/app/assets/html/mailing/tile.html @@ -0,0 +1,42 @@ +
+
+
+
+

${name}

+

${statusLabel}

+
+ +
+
+
+
${pathChips}
+
+ Updated: ${lastUpdate}
+ by ${lastContributor} +
+
+
+
+
+
${kpis.nbRecipients ? kpis.nbRecipients.toLocaleString('fr-FR') : 0}
+
${ (typeof(kpis.nbPending)=='number') ? kpis.nbPending.toLocaleString('fr-FR') : kpis.nbPending }
+
${ (typeof(kpis.nbBounced)=='number') ? kpis.nbBounced.toLocaleString('fr-FR') : kpis.nbBounced }
+
${ (typeof(kpis.nbReached)=='number') ? kpis.nbReached.toLocaleString('fr-FR') : kpis.nbReached }
+
+
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/app/assets/images/cards/applicant-dashboard.jpg b/app/assets/images/cards/applicant-dashboard.jpg new file mode 100644 index 0000000..d7f9348 Binary files /dev/null and b/app/assets/images/cards/applicant-dashboard.jpg differ diff --git a/app/assets/images/cards/chalkboard.jpg b/app/assets/images/cards/chalkboard.jpg new file mode 100644 index 0000000..fd3af17 Binary files /dev/null and b/app/assets/images/cards/chalkboard.jpg differ diff --git a/app/assets/images/cards/disclaimer.jpg b/app/assets/images/cards/disclaimer.jpg new file mode 100644 index 0000000..26a3fbb Binary files /dev/null and b/app/assets/images/cards/disclaimer.jpg differ diff --git a/app/assets/images/cards/eic_purple_banner.png b/app/assets/images/cards/eic_purple_banner.png new file mode 100644 index 0000000..b4419e1 Binary files /dev/null and b/app/assets/images/cards/eic_purple_banner.png differ diff --git a/app/assets/images/cards/eicui-banner.jpg b/app/assets/images/cards/eicui-banner.jpg new file mode 100644 index 0000000..697a79d Binary files /dev/null and b/app/assets/images/cards/eicui-banner.jpg differ diff --git a/app/assets/images/cards/fasttracks-card.jpg b/app/assets/images/cards/fasttracks-card.jpg new file mode 100755 index 0000000..23efcd1 Binary files /dev/null and b/app/assets/images/cards/fasttracks-card.jpg differ diff --git a/app/assets/images/cards/healthcheck.jpg b/app/assets/images/cards/healthcheck.jpg new file mode 100755 index 0000000..5781d8e Binary files /dev/null and b/app/assets/images/cards/healthcheck.jpg differ diff --git a/app/assets/images/cards/help.jpg b/app/assets/images/cards/help.jpg new file mode 100644 index 0000000..616a72d Binary files /dev/null and b/app/assets/images/cards/help.jpg differ diff --git a/app/assets/images/cards/lab-sampler.jpg b/app/assets/images/cards/lab-sampler.jpg new file mode 100755 index 0000000..fb00de3 Binary files /dev/null and b/app/assets/images/cards/lab-sampler.jpg differ diff --git a/app/assets/images/cards/mass-mailer.jpg b/app/assets/images/cards/mass-mailer.jpg new file mode 100644 index 0000000..e7817df Binary files /dev/null and b/app/assets/images/cards/mass-mailer.jpg differ diff --git a/app/assets/images/cards/massMail-Details.jpg b/app/assets/images/cards/massMail-Details.jpg new file mode 100644 index 0000000..b7d0efc Binary files /dev/null and b/app/assets/images/cards/massMail-Details.jpg differ diff --git a/app/assets/images/cards/massMail-monitoring.jpg b/app/assets/images/cards/massMail-monitoring.jpg new file mode 100644 index 0000000..fa2e28d Binary files /dev/null and b/app/assets/images/cards/massMail-monitoring.jpg differ diff --git a/app/assets/images/cards/soe-banner.jpg b/app/assets/images/cards/soe-banner.jpg new file mode 100644 index 0000000..0844fef Binary files /dev/null and b/app/assets/images/cards/soe-banner.jpg differ diff --git a/app/assets/images/cards/styleguide.jpg b/app/assets/images/cards/styleguide.jpg new file mode 100755 index 0000000..ba5cefc Binary files /dev/null and b/app/assets/images/cards/styleguide.jpg differ diff --git a/app/assets/images/cards/submission-card.jpg b/app/assets/images/cards/submission-card.jpg new file mode 100644 index 0000000..676fac3 Binary files /dev/null and b/app/assets/images/cards/submission-card.jpg differ diff --git a/app/assets/images/cards/support.jpg b/app/assets/images/cards/support.jpg new file mode 100644 index 0000000..9b36a51 Binary files /dev/null and b/app/assets/images/cards/support.jpg differ diff --git a/app/assets/images/cards/templitorHeader.png b/app/assets/images/cards/templitorHeader.png new file mode 100644 index 0000000..89dceeb Binary files /dev/null and b/app/assets/images/cards/templitorHeader.png differ diff --git a/app/assets/images/cards/userprefs.jpg b/app/assets/images/cards/userprefs.jpg new file mode 100644 index 0000000..5dcff9c Binary files /dev/null and b/app/assets/images/cards/userprefs.jpg differ diff --git a/app/assets/images/logo-ec--en.svg b/app/assets/images/logo-ec--en.svg new file mode 100644 index 0000000..6995866 --- /dev/null +++ b/app/assets/images/logo-ec--en.svg @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/videobg.png b/app/assets/images/videobg.png new file mode 100644 index 0000000..09326c1 Binary files /dev/null and b/app/assets/images/videobg.png differ diff --git a/app/assets/json/global/app-menu-map.json b/app/assets/json/global/app-menu-map.json new file mode 100644 index 0000000..f7a85f5 --- /dev/null +++ b/app/assets/json/global/app-menu-map.json @@ -0,0 +1,195 @@ +[ + { + "label": "Bypass", + "icon": "icon-bolt", + "collapsed": true, + "items": [ + { + "label": "Monitoring", + "icon": "icon-dashboard", + "route": "/bypass", + "access": [ "BP_PO", "BP_HoU" ] + }, + { + "label": "EIC Fast Track", + "icon": "icon-dashboard", + "route": "/bypass/fast-tracks", + "access": [ "BP_SPOC_FastTrack" ] + }, + { + "label": "EIC Plug In", + "icon": "icon-dashboard", + "route": "/bypass/plugins", + "access": [ "BP_SPOC_Plugin" ] + }, + { + "label": "Guidelines", + "icon": "icon-help", + "route": "/bypass/guidelines", + "access": [ "BP_PO", "BP_HoU","BP_SPOC_Plugin","BP_SPOC_FastTrack" ] + } + ] + }, + { + "label": "My EIC", + "icon": "icon-home", + "collapsed": true, + "items": [ + { + "label": "Overview", + "icon": "icon-dashboard", + "route": "/applicant", + "access": [ "Org_Member" ] + } + ] + }, + { + "label": "ICMP", + "icon": "icon-company", + "items": [ + { + "label": "Monitoring", + "icon": "icon-dashboard", + "route": "/icmp", + "access": [ "PROJECT_PO", "PROJECT_FIO" ] + }, + { + "label": "Dashboard", + "icon": "icon-dashboard", + "route": "/icmp", + "access": [ "PROJECT_TechDDExpert" ] + } + ] + }, + { + "label": "SoE", + "icon": "icon-star-full", + "collapsed": true, + "items": [ + { + "label": "Overview", + "icon": "icon-dashboard", + "route": "/soe", + "access": [ "EIC_dev", "EIC_Admin", "SOE_National", "SOE_Admin" ] + } + ] + }, + { + "label": "Coachings", + "icon": "icon-coaching", + "collapsed": true, + "items": [ + { + "label": "Admin dashboard", + "icon": "icon-dashboard", + "route": "/coachings/admin", + "access": [ "EIC_Dev", "EIC_Admin" ] + }, + { + "label": "Coach dashboard", + "icon": "icon-dashboard", + "route": "/coachings/coach", + "access": [ "EIC_Dev", "EIC_Admin" ] + }, + { + "label": "Applicant coaching", + "icon": "icon-coaching", + "route": "/coachings/coaching/1234", + "access": [ "EIC_Dev", "EIC_Admin" ] + } + ] + }, + { + "label": "Dev tools", + "icon": "icon-cogs", + "collapsed": true, + "items": [ + { + "label": "System Health Check", + "icon": "icon-health", + "route": "/system/healthcheck", + "access": [ "EIC_Dev" ] + }, + { + "label": "App Style Guide", + "icon": "icon-image", + "route": "/system/styleguide", + "access": [ "EIC_Dev" ] + }, + { + "label": "EICUI Components", + "icon": "icon-cogs", + "route": "/system/eicui", + "access": [ "EIC_Dev" ] + } + ] + }, + { + "label": "Communication", + "icon": "icon-share", + "items": [ + { + "label": "Platform Control", + "icon": "icon-logoff", + "route": "/system/control", + "access": [ "EIC_Dev" ] + }, + { + "label": "Mailings", + "icon": "icon-envelope", + "route": "/mailings", + "access": [ "MAIL_Editor", "MAIL_Reviewer", "MAIL_Sender", "EIC_Dev", "EIC_Admin" ] + }, + { + "label": "Templates", + "icon": "icon-edit", + "route": "/templates", + "access": [ "TEMPLATE_Editor", "TEMPLATE_Reviewer", "EIC_Dev", "EIC_Admin" ] + } + ] + }, + { + "label": "Fun stuffs", + "icon": "icon-face-smile", + "collapsed": true, + "items": [ + { + "label": "CarmeloMatic 3000", + "icon": "icon-coaching", + "route": "/system/sampler", + "access": [ "EIC_Dev" ] + }, + { + "label": "Magic Chalkboard", + "icon": "icon-edit", + "route": "/system/chalkboard", + "access": [ "EIC_Dev" ] + }, + { + "label": "Data explorer", + "icon": "icon-servers", + "route": "/system/explorer", + "access": [ "EIC_Dev" ] + } + ] + }, + { + "label": "About", + "icon": "icon-info", + "collapsed": true, + "items": [ + { + "label": "Legal notice", + "icon": "icon-info", + "route": "/about/legalnotice", + "access": [ "*" ] + }, + { + "label": "Support", + "icon": "icon-help", + "route": "/about/support", + "access": [ "*" ] + } + ] + } +] diff --git a/app/assets/json/global/bypass/roleDelegations.json b/app/assets/json/global/bypass/roleDelegations.json new file mode 100644 index 0000000..c3b5588 --- /dev/null +++ b/app/assets/json/global/bypass/roleDelegations.json @@ -0,0 +1,23 @@ +[ + { + "master": "BP_PO", + "surrogates": [ + {"role": "BP_PO", "track": "ignore", "domain": "ignore"}, + {"role": "BP_HoU", "track": "ignore", "domain": "ignore"}, + {"role": "BP_SPOC_Plugin", "track": "daTai94ymStyRbQWybH3eDw", "domain": "set"}, + {"role": "BP_SPOC_FastTrack", "track": "d7xAg5kIhQYeDMB1H6eXnBg", "domain": "set"} + ] + }, + { + "master": "BP_SPOC_FastTrack", + "surrogates": [ + {"role": "BP_SPOC_FastTrack", "track": "inherit", "domain": "inherit"} + ] + }, + { + "master": "BP_SPOC_Plugin", + "surrogates": [ + {"role": "BP_SPOC_Plugin", "track": "inherit", "domain": "inherit"} + ] + } +] \ No newline at end of file diff --git a/app/assets/json/global/services.json b/app/assets/json/global/services.json new file mode 100644 index 0000000..4768783 --- /dev/null +++ b/app/assets/json/global/services.json @@ -0,0 +1,982 @@ +{ + "success": true, + "error": "", + "payload": [ + { + "resource": "services", + "actions": [ + { + "action": "getServices", + "availableMethod": { + "uri": "https://__host__/stable/apis/services", + "method": "GET" + } + } + ] + }, + { + "resource": "/files", + "actions": [ + { + "action": "get", + "availableMethod": { + "uri": "/files/{id}", + "method": "GET" + } + } + ] + }, + { + "resource": "company", + "actions": [ + { + "action": "revoke", + "availableMethod": { + "uri": "https://__host__/stable/bypass/company/{pic}/token", + "method": "DELETE" + } + }, + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/bypass/company/{pic}/token", + "method": "POST" + } + }, + { + "action": "grant", + "availableMethod": { + "uri": "https://__host__/stable/bypass/company/{pic}/token", + "method": "PUT" + } + } + ] + }, + { + "resource": "programs", + "actions": [ + { + "action": "removeProgram", + "availableMethod": { + "uri": "https://__host__/stable/bypass/programs", + "method": "DELETE" + } + }, + { + "action": "getPrograms", + "availableMethod": { + "uri": "https://__host__/stable/bypass/programs", + "method": "POST" + } + }, + { + "action": "addProgram", + "availableMethod": { + "uri": "https://__host__/stable/bypass/programs", + "method": "PUT" + } + } + ] + }, + { + "resource": "roles", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/bypass/roles", + "method": "GET" + } + } + ] + }, + { + "resource": "tokens", + "actions": [ + { + "action": "consume", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/consume", + "method": "POST" + } + }, + { + "action": "getSettings", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/settings", + "method": "POST" + } + }, + { + "action": "setSettings", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/settings", + "method": "PUT" + } + }, + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens", + "method": "POST" + } + }, + { + "action": "view", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/{tokenid}", + "method": "GET" + } + }, + { + "action": "assign", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/bypass", + "method": "PUT" + } + } + ] + }, + { + "resource": "XXXtokens", + "actions": [ + { + "action": "consume", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/consume", + "method": "POST" + } + }, + { + "action": "getSettings", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/settings", + "method": "POST" + } + }, + { + "action": "setSettings", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/settings", + "method": "PUT" + } + }, + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens", + "method": "POST" + } + }, + { + "action": "view", + "availableMethod": { + "uri": "https://__host__/stable/bypass/tokens/{tokenid}", + "method": "GET" + } + }, + { + "action": "assign", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/bypass", + "method": "PUT" + } + } + ] + }, + { + "resource": "users", + "actions": [ + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/users/search", + "method": "POST" + } + }, + { + "action": "revoke", + "availableMethod": { + "uri": "https://__host__/stable/bypass/users/{id}", + "method": "DELETE" + } + }, + { + "action": "get", + "availableMethod": { + "uri": "https://__host__/stable/bypass/users/{id}", + "method": "GET" + } + }, + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/bypass/users", + "method": "POST" + } + }, + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/bypass/users", + "method": "PUT" + } + } + ] + }, + { + "resource": "/S3Files", + "actions": [ + { + "action": "viewDocument", + "availableMethod": { + "uri": "https://__host__/stable/vod/source?file=", + "method": "GET" + } + }, + { + "action": "viewVideo", + "availableMethod": { + "uri": "https://__host__/stable/vod/manifest?file=", + "method": "GET" + } + }, + { + "action": "uploadPdf", + "availableMethod": { + "getSignedUrl": "https://__host__/stable/vod/source?file=", + "getSignedMethod": "PUT" + } + }, + { + "action": "uploadVideo", + "availableMethod": { + "getSignedUrl": "https://__host__/stable/vod/source?file=", + "getSignedMethod": "PUT" + } + }, + { + "action": "checkVideoConversion", + "availableMethod": { + "uri": "https://__host__/stable/vod/jobs", + "method": "POST" + } + } + ] + }, + { + "resource": "/organisations", + "actions": [ + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/organisations", + "method": "POST" + } + }, + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/organisations", + "method": "GET" + } + }, + { + "action": "apply", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}", + "actions": [ + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}", + "method": "GET" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/members", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members", + "method": "GET" + } + }, + { + "action": "grant", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "revoke", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "add", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/users/search", + "method": "POST" + } + } + ] + }, + { + "resource": "/organisations/{pic}/members/{uid}", + "actions": [ + { + "action": "grant", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "revoke", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/members/{uid}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/coachings", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/coachings", + "method": "GET" + } + }, + { + "action": "read", + "availableMethod": { + "uri": "https://eic__stage__.eismea.eu/mydashboard/mycoaching", + "method": "GET" + } + } + ] + }, + { + "resource": "/organisations/{pic}/proposals", + "actions": [ + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals", + "method": "POST" + } + }, + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals", + "method": "GET" + } + }, + { + "action": "apply", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/proposals/{pid}", + "actions": [ + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}", + "method": "GET" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}", + "method": "PUT" + } + }, + { + "action": "organisationUpdate", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}", + "method": "GET" + } + }, + { + "action": "clone", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals", + "method": "PUT" + } + }, + { + "action": "complain", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/complaint", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/proposals/{pid}/members", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/members", + "method": "GET" + } + }, + { + "action": "grant", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/members/{uid}", + "method": "PUT" + } + }, + { + "action": "revoke", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/members/{uid}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/proposals/{pid}/complaints", + "actions": [ + { + "action": "get", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/complaints", + "method": "GET" + } + }, + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/complaints", + "method": "PUT" + } + } + ] + }, + { + "resource": "/organisations/{pic}/proposals/{pid}/team", + "actions": [ + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/team", + "method": "PUT" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/team/{uid}", + "method": "PUT" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/organisations/{pic}/proposals/{pid}/team/{uid}", + "method": "DELETE" + } + } + ] + }, + { + "resource": "explorer", + "actions": [ + { + "action": "filters", + "availableMethod": { + "uri": "https://__host__/stable/storage/entities", + "method": "GET" + } + }, + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/storage/entities", + "method": "POST" + } + } + ] + }, + { + "resource": "/zammad/tickets", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/zammad/tickets", + "method": "GET" + } + }, + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/zammad/tickets", + "method": "POST" + } + }, + { + "action": "get", + "availableMethod": { + "uri": "https://__host__/stable/zammad/tickets/{id}", + "method": "GET" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/zammad/tickets/{id}/articles", + "method": "POST" + } + }, + { + "action": "download", + "availableMethod": { + "uri": "https://__host__/files/stable/zammad/tickets/{ticid}/articles/{artid}/attachments/{attid}", + "method": "GET" + } + + } + ] + }, + { + "resource": "/soe", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/soe", + "method": "GET" + } + }, + { + "action": "members", + "availableMethod": { + "uri": "https://__host__/stable/soe/members", + "method": "GET" + } + }, + { + "action": "project", + "availableMethod": { + "uri": "https://__host__/stable/soe/organisations/{pic}/projects/{projectId}/fundings", + "method": "GET" + } + + }, + { + "action": "create", + "availableMethod": { + "uri": "https://__host__/stable/soe/organisations/{pic}/projects/{projectId}/fundings", + "method": "PUT" + } + }, + { + "action": "funding", + "availableMethod": { + "uri": "https://__host__/stable/soe/organisations/{pic}/projects/{projectId}/fundings/{fundingId}", + "method": "GET" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/soe/organisations/{pic}/projects/{projectId}/fundings/{fundingId}", + "method": "DELETE" + } + }, + { + "action": "update", + "availableMethod": { + "uri": "https://__host__/stable/soe/organisations/{pic}/projects/{projectId}/fundings/{fundingId}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/icmp", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects", + "method": "POST" + } + }, + { + "action": "getProject", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}", + "method": "GET" + } + }, + { + "action": "getProjectDocuments", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}/documents", + "method": "GET" + } + }, + { + "action": "getProjectContributors", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}/contributors", + "method": "GET" + } + }, + { + "action": "getProjectNode", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}/{node}/{nodeId}", + "method": "GET" + } + }, + { + "action": "saveProjectNode", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}/{node}/{nodeId}", + "method": "PUT" + } + }, + { + "action": "saveProjectNodeComments", + "availableMethod": { + "uri": "https://__host__/stable/icmp/projects/{projectId}/{node}/{nodeId}/comments", + "method": "PUT" + } + } + ] + }, + { + "resource": "/mailing", + "actions": [ + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/mailing", + "method": "POST" + } + }, + { + "action": "save", + "availableMethod": { + "uri": "https://__host__/stable/mailing", + "method": "PUT" + } + }, + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}", + "method": "GET" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}", + "method": "DELETE" + } + }, + { + "action": "test", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/test", + "method": "PUT" + } + }, + { + "action": "schedule", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/mailing/folders", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/mailing/folders", + "method": "POST" + } + }, + { + "action": "add", + "availableMethod": { + "uri": "https://__host__/stable/mailing/folders", + "method": "PUT" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/mailing/folders", + "method": "DELETE" + } + } + ] + }, + { + "resource": "/mailing/{mid}/recipients", + "actions": [ + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/recipients", + "method": "GET" + } + } + ] + }, + { + "resource": "/mailing/{mid}/bounces", + "actions": [ + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/bounces", + "method": "GET" + } + } + ] + }, + { + "resource": "/mailing/{mid}/imports", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/imports", + "method": "GET" + } + }, + { + "action": "save", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/imports", + "method": "PUT" + } + }, + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/imports/{iid}", + "method": "GET" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/mailing/{mid}/imports", + "method": "DELETE" + } + } + ] + }, + { + "resource": "/templates", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/templitor", + "method": "POST" + } + }, + { + "action": "search", + "availableMethod": { + "uri": "https://__host__/stable/templitor", + "method": "POST" + } + }, + { + "action": "getImages", + "availableMethod": { + "uri": "https://__host__/stable/templitor/images", + "method": "POST" + } + }, + { + "action": "addImage", + "availableMethod": { + "uri": "https://__host__/stable/templitor/images", + "method": "PUT" + } + }, + { + "action": "deleteImage", + "availableMethod": { + "uri": "https://__host__/stable/templitor/images/{pid}", + "method": "DELETE" + } + }, + { + "action": "save", + "availableMethod": { + "uri": "https://__host__/stable/templitor", + "method": "PUT" + } + }, + { + "action": "read", + "availableMethod": { + "uri": "https://__host__/stable/templitor/{tid}", + "method": "GET" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/templitor/{tid}", + "method": "DELETE" + } + }, + { + "action": "testTemplateMail", + "availableMethod": { + "uri": "https://__host__/stable/templitor/{tid}", + "method": "PUT" + } + }, + { + "action": "uploadTplImage", + "availableMethod": { + "uri": "https://__host__/stable/public/{tplImgName}", + "method": "PUT" + } + } + ] + }, + { + "resource": "/templitor/folders", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/templitor/folders", + "method": "POST" + } + }, + { + "action": "add", + "availableMethod": { + "uri": "https://__host__/stable/templitor/folders", + "method": "PUT" + } + }, + { + "action": "delete", + "availableMethod": { + "uri": "https://__host__/stable/templitor/folders", + "method": "DELETE" + } + } + ] + }, + { + "resource": "/contactMgr", + "actions": [ + { + "action": "list", + "availableMethod": { + "uri": "https://__host__/stable/contactMgr", + "method": "GET" + } + }, + { + "action": "get", + "availableMethod": { + "uri": "https://__host__/stable/contactMgr/{qcid}", + "method": "GET" + } + }, + { + "action": "getFields", + "availableMethod": { + "uri": "https://__host__/stable/contactMgr/{qcid}/fields", + "method": "POST" + } + }, + { + "action": "execute", + "availableMethod": { + "uri": "https://__host__/stable/contactMgr/{qcid}", + "method": "PUT" + } + } + ] + } + ] +} diff --git a/app/assets/json/global/user-roles.json b/app/assets/json/global/user-roles.json new file mode 100644 index 0000000..6c2a6fd --- /dev/null +++ b/app/assets/json/global/user-roles.json @@ -0,0 +1,34 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "", + "updated": "2023-11-10 10:00:00", + "expires": "2024-11-10 23:59:00", + "content": [ + { + "label":"Administrators", + "id":"Admin", + "children": [ + {"label":"EIC Administrator","id":"EIC_Admin" }, + {"label":"EIC Developper","id":"EIC_Dev" } + ] + }, + { + "label":"Bypass", + "id":"Bypass", + "children": [ + {"label":"Head of unit","id":"BP_HoU" }, + {"label":"Project Officer","id":"BP_PO" }, + {"label":"SPOC Plugin","id":"BP_SPOC_Plugin" }, + {"label":"SPOC Fasttrack","id":"BP_SPOC_FastTrack" } + ] + }, + { + "label":"Applicants", + "id":"Applicants", + "children": [ + {"label":"Organisation member","id":"Org_Member" } + ] + } + ] +} diff --git a/app/assets/json/meta/accelerator-tracks.json b/app/assets/json/meta/accelerator-tracks.json new file mode 100644 index 0000000..d8017e4 --- /dev/null +++ b/app/assets/json/meta/accelerator-tracks.json @@ -0,0 +1,61 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "http://data.eic.eu/model/track", + "updated": "2023-03-23 14:03:12", + "expires": null, + "content": [ + { + "id": "daTai94ymStyRbQWybH3eDw", + "label": "EIC Plug In", + "children": [ + {"id": "ddMBYo64lQTOCNxJnpprx5A", "label": "Austria"}, + {"id": "dQDpO6LcNTLi3QN5kTiw0MA", "label": "Belgium"}, + {"id":"dAU-fpjd-RzWAdeqCnTo_hQ", "label": "Bulgaria"}, + {"id": "duCbnathTR6ORqUexphvcNA", "label": "Croatia"}, + {"id": "dgyso3mX6R4y3CJG7T0wm7Q", "label": "Cyprus"}, + {"id": "dWyQnwI9fRL69gZvonUD-3g", "label": "Czech Republic"}, + {"id": "dBeD1TDpIRMupaYJFrE15fA", "label": "Denmark"}, + {"id": "deaeC-g4zSU-lrQmD7RXTLA", "label": "Estonia"}, + {"id": "dzYncC5C_RPSG-I2W4xccBg", "label": "Finland"}, + {"id": "dqO7eNhkaTpi7-vrL7xbrLA", "label": "France"}, + {"id": "dETQuC1DCQOa1inlawb1LUw", "label": "Germany"}, + {"id": "dFY2sRS_0Q92Av7-_LfUDOg", "label": "Greece"}, + {"id": "d0FngG6GARSC-rRaqbpWhaw", "label": "Hungary"}, + {"id": "dwrwtGAwuSGGsqqB7T2lZUg", "label": "Ireland"}, + {"id": "ddUy-9-e-Tdyc4dxr2tVHkg", "label": "Italy"}, + {"id":"dGDsjdxxZQVefpIlHVPaWNg", "label": "Lithuania"}, + {"id": "dGlnFXv8aQzahaVjjnLTE4A", "label": "Malta"}, + {"id": "d1bssyFT7Tsa0smN7zkzG8w", "label": "The Netherlands"}, + {"id": "doZaFLUxUT_OvHkzH5_YBjA", "label": "Poland"}, + {"id": "dAyJVxePsRaubXqm1rWF9Fw", "label": "Portugal"}, + {"id": "dUTwpYqmOTWye1lfOkRFauw", "label": "Romania"}, + {"id": "dzeYoKXm8RjeBghutjHfQ_Q", "label": "Spain"}, + {"id": "dbmUbq_FsSViCsdZe46WVxA", "label": "Sweden"}, + {"id": "dCCbZtp4RQ2eQLydphtKJvg", "label": "Montenegro"}, + {"id": "dI816Ui0MSxWDygFzA_MVrw", "label": "Norway"}, + {"id": "dMl2qhvAjRUywduo6jCDyNQ", "label": "Türkiye"} + ] + }, + { + "id": "d7xAg5kIhQYeDMB1H6eXnBg", + "label": "EIC Fast Track", + "children": [ + {"id": "d-eit-climate-kic-FqkCw", "label": "Climate KIC"}, + {"id": "d-eit-digital-g-FhFqkCw", "label": "Digital KIC"}, + {"id": "d-eit-food-q9jg-FhFqkCw", "label": "Food KIC"}, + {"id": "d-eit-health-jg-FhFqkCw", "label": "Health KIC"}, + {"id": "d-eit-innoenergy-hFqkCw", "label": "InnoEnergy KIC"}, + {"id": "d-eit-manufacturing-kCw", "label": "Manufacturing KIC"}, + {"id": "d-eit-rawmaterials-qkCw", "label": "RawMaterials KIC"}, + {"id": "d-eit-urban-mobility-Cw", "label": "Urban Mobility KIC"}, + {"id": "d-eit-cultu-mobility-Cw", "label": "Culture & creativity KIC"}, + {"id": "d-eic-pathfinder-hFqkCw", "label": "EIC Pathfinder"}, + {"id": "d-eic-transition-ity-Cw", "label": "EIC Transition"}, + {"id": "d-eic-accelerator-ty-Cw", "label": "EIC Accelerator"}, + {"id": "d-eic-women-tech-eu-kCw", "label": "EIC Women Tech EU"}, + {"id": "dzDvMeuo7S-if5U-Jv_84xg", "label": "EUREKA"} + ] + } + ] +} diff --git a/app/assets/json/meta/coaching-countries.json b/app/assets/json/meta/coaching-countries.json new file mode 100644 index 0000000..681d276 --- /dev/null +++ b/app/assets/json/meta/coaching-countries.json @@ -0,0 +1,386 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "http://data.eic.eu/model/repository-items", + "updated": "2024-03-20 14:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { "id": "d3YaBxS-FR9quTjIP4Ln95Q", "label": "Europe", + "children": [ + { + "id": "dgttW8OjFQca9qLdbsdPxiQ", + "label": "Western Europe", + "children": [ + { "id": "de0icXyh9RJ-pJxq_EYFoBA", "label": "Austria" }, + { "id": "dgv1rlNSfRxG_RJPSgIGIXg", "label": "Belgium" }, + { "id": "dR7lH1oLpRTmgjpmsT944Eg", "label": "France" }, + { "id": "d6__9ZstZTTuwXEavH2xn-A", "label": "Germany" }, + { "id": "d54ANdkhKTN-WgywOaWDOLQ", "label": "Liechtenstein" }, + { "id": "dVyyoU6O_TRqKKAnDxz3V9g", "label": "Luxembourg" }, + { "id": "dTUabC-ZlQA6-4v1aOVE0Pw", "label": "Monaco" }, + { "id": "dW00nAY6nQda7i9OUhcdMAA", "label": "Netherlands" }, + { "id": "dpCfJoRWBS8-HTaWZUFI3Xw", "label": "Switzerland" }, + { "id": "dw7CcVRmGQXGoubV85QjYCw", "label": "United Kingdom" } + ] + }, + { + "id": "d5Rph-09tRdqCzo2QFUfxRA", + "label": "Northern Europe", + "children": [ + { "id": "dz14gfhmqS9GGUrB2Msi5lA", "label": "Åland Islands" }, + { "id": "dKk4Xc6JsQeSRPPizKEgsoQ", "label": "Denmark" }, + { "id": "dw6vY8DC2QquWjT5AhpzAYw", "label": "Estonia" }, + { "id": "doXELPKs1SPSwPZW6E6epqA", "label": "Faroe Islands" }, + { "id": "dD0KELKV9RG6S2ymN3_ilXg", "label": "Finland" }, + { "id": "dpptSvmNJRcCza5syycX2pQ", "label": "Guernsey" }, + { "id": "dY0Bn_KbMTXmV7J0XOO8wpw", "label": "Iceland" }, + { "id": "dY2W8OzxwSbqCVjgtSL1NvA", "label": "Ireland" }, + { "id": "dwOl3Vhs5TziZ5RKr-aIyEQ", "label": "Isle of Man" }, + { "id": "dsOHvxnnFSxevsZDqxbymcA", "label": "Jersey" }, + { "id": "d1GP9fSp3R-uH2zNX2GXwsQ", "label": "Latvia" }, + { "id": "dYqshhJd4TwSuOw3mFlLlJA", "label": "Lithuania" }, + { "id": "dD-cyDbPxTmGn6dts4cGY8g", "label": "Norway" }, + { "id": "dZKlGVwUcQ2aTe7VE09UjMA", "label": "Svalbard and Jan Mayen" }, + { "id": "dg2aWPdz8Qk-lue5t4UtSeg", "label": "Sweden" }, + { "id": "dV8v7gw6XRhm9W4pgkMkJCg", "label": "United Kingdom of Great Britain and Northern Ireland" + } + ] + }, + { + "id": "dg92-2rpcQBWU5Xvzc_ed5w", + "label": "Eastern Europe", + "children": [ + { "id": "drpruv1jNT66zUUhmcYF8Lw", "label": "Belarus" }, + { "id": "dUAIwLJ3MToGpprduRxL9Lw", "label": "Bulgaria" }, + { "id": "dnbomWOPnTLGl8ROfSNoH9w", "label": "Czech Republic" }, + { "id": "dDtT4nyPGRImjljcuBePRbQ", "label": "Hungary" }, + { "id": "d97umNcDmTzedJ-Dv6h5X7Q", "label": "Moldova (Republic of)" }, + { "id": "dMAdhjBnVSt-6TwlmSqd6CQ", "label": "Poland" }, + { "id": "dQyGSs8S5T_KzRipuuSE2TQ", "label": "Romania" }, + { "id": "dX-_mQ3eMRiOODv44hwFHjA", "label": "Russian Federation" }, + { "id": "dsio8MaIYRHCMEP9nm83uBQ", "label": "Slovakia" }, + { "id": "dM8h8uEWcTSWcGumrFC9wDA", "label": "Ukraine" } + ] + }, + { + "id": "d3Uq8HkK9SCmV3-9cyoNRbw", + "label": "Southern Europe", + "children": [ + { "id": "djCaD1C4hT0WbUfsQmHKjYw", "label": "Albania" }, + { "id": "dhom0u7wNSZ-vLUxtu8MyvA", "label": "Andorra" }, + { "id": "d13NG9DgqQtiLXuRytBkOHw", "label": "Bosnia and Herzegovina" }, + { "id": "d1YbsIXE4TFK4cfxcqiybww", "label": "Croatia" }, + { "id": "dnykwn_tNQG-HHmsYflkpEA", "label": "Gibraltar" }, + { "id": "d_CCTaaeRSFuLjCmAovKnMg", "label": "Greece" }, + { "id": "dVcXz_b_zTZ-6w7d6l03dRA", "label": "Holy See" }, + { "id": "dZNTDPf3lSBSlSHrQotbrdA", "label": "Italy" }, + { "id": "dXU3o8d3dQrqs8KS54lPvgg", "label": "Macedonia (the former Yugoslav Republic of)" }, + { "id": "d3mr3rQSOQf23IkGndOOROA", "label": "Malta" }, + { "id": "dNOZyp_brT_GcMBCWeJq0ZQ", "label": "Montenegro" }, + { "id": "dxLz0Vft1RE6C1CaDQYvy6Q", "label": "Portugal" }, + { "id": "dV2CETRPXQ2u9H2ixcW2_KQ", "label": "San Marino" }, + { "id": "dZFWnbTJgQcasq1xGbirPNw", "label": "Serbia" }, + { "id": "dRcyMt6R2QCeVW7QHQf5Dwg", "label": "Slovenia" }, + { "id": "dw9CIZ0vFR6-I1SeMlvMDFw", "label": "Spain" } + ] + } + ] + }, + { "id": "dxIYK0bK-T5220nRUTz8zrA", "label": "Africa", + "children": [ + { + "id": "d4wSH8cZKQbCBs_5ZT8kGaw", + "label": "Sub-Saharan Africa", + "children": [ + { "id": "ddAE3PbzzRKmJWUgAlG9_oA", "label": "Angola" }, + { "id": "d9McCYAxVTTq6yGAaXX8Bdw", "label": "Benin" }, + { "id": "d6mlBDfdmTQ6yTBvqBjBSaQ", "label": "Botswana" }, + { "id": "day1JDcIbRUW3y4FxLAtZfg", "label": "British Indian Ocean Territory" }, + { "id": "dr03rEDFYTsy0WitmFmlNXA", "label": "Burkina Faso" }, + { "id": "dgvU57aupQGiUUWRxhkLFDw", "label": "Burundi" }, + { "id": "df4DalrfvQXOWXJOVsfFvLA", "label": "Cabo Verde" }, + { "id": "d3Jh_mOJCTUWt64dX2b4maQ", "label": "Cameroon" }, + { "id": "d7LVOaYCbQQWOW_s8Jdh8AA", "label": "Central African Republic" }, + { "id": "dkUiSJ0nbT8OZVFNvD1nLMQ", "label": "Chad" }, + { "id": "ddyGl69WCT2m6LVNU4ukwEA", "label": "Comoros" }, + { "id": "d_s-lDnG7R-q278SqhreLEQ", "label": "Congo" }, + { "id": "ddX-iTMN_RwqTEB241hoViQ", "label": "Congo (Democratic Republic of the)" }, + { "id": "daUXdCV88Rkq780DQSqdfNw", "label": "Côte d'Ivoire" }, + { "id": "dOJF56bhJSS2iR6TE3IOhQw", "label": "Djibouti" }, + { "id": "dSRJjZFtpS6iwdht-CQw2UA", "label": "Equatorial Guinea" }, + { "id": "dvUQnTH4RRSiW9IdsC2ps2w", "label": "Eritrea" }, + { "id": "dBcm6iijMTty7yVigniWphg", "label": "Eswatini" }, + { "id": "dpnv7XkBPTby420ZOdSEGKA", "label": "Ethiopia" }, + { "id": "dkpPLqNVISk6mvopc2dMTbw", "label": "French Southern Territories" }, + { "id": "dpSpPvurmTtWNSq5kwpbdbQ", "label": "Gabon" }, + { "id": "ddLSh4pChS3q6ah4lLsbzDg", "label": "Gambia" }, + { "id": "d6gTY7iGeRZm5Zxu41tm-zQ", "label": "Ghana" }, + { "id": "dXqI4RXugRUu21SIjd1lZbQ", "label": "Guinea" }, + { "id": "dZ4r7lGzrQoqBqiaJzc1aZg", "label": "Guinea-Bissau" }, + { "id": "d53tGHYSAQdSyGLbkzN15Fw", "label": "Kenya" }, + { "id": "dQUdRYSRlRMCpVhIG1XXzfg", "label": "Lesotho" }, + { "id": "dgX5fJNMbT1eXnNczqT18xA", "label": "Liberia" }, + { "id": "dKRgi3f5iQUOCik1gGbQZCQ", "label": "Madagascar" }, + { "id": "d3l8GHAtPQ2yoE0Rqx0QK4w", "label": "Malawi" }, + { "id": "dLdbfRY-FSGyuQu4zkLCh1g", "label": "Mali" }, + { "id": "djhLXFkGRRICz8Y2unLYTvg", "label": "Mauritania" }, + { "id": "dFwoq3DOsSGSWi0wNze1s9A", "label": "Mauritius" }, + { "id": "dohJXOWEfR_WFjNNymjwP0Q", "label": "Mayotte" }, + { "id": "diKP5aTl-QlmEEUHpAx8QJw", "label": "Mozambique" }, + { "id": "dDKiK9bOcSiSv9jwz_AwtSQ", "label": "Namibia" }, + { "id": "dthTL98uPTMiBIUBS-pWdzQ", "label": "Niger" }, + { "id": "dRIsOiuzZRfC7x2FmlFksYw", "label": "Nigeria" }, + { "id": "dR8nGPoiJQuaHwgUSfkTdZg", "label": "Réunion" }, + { "id": "dI6Io1c3LRd2qz96zKfzmEw", "label": "Rwanda" }, + { "id": "d9UbPGLqqSViLWquwh4kJXg", "label": "Saint Helena, Ascension and Tristan da Cunha" }, + { "id": "ds7MFCx4kQDKAwBRe4KbZDg", "label": "Sao Tome and Principe" }, + { "id": "dF-qyK4ImQRuoUADE2cBo4g", "label": "Senegal" }, + { "id": "doDxKfNEwQpSv1qG4rAXfNQ", "label": "Seychelles" }, + { "id": "dYo3tmpoVSvq0Vru62ZIeMA", "label": "Sierra Leone" }, + { "id": "duD2kiyQxSCOYzpemsBUx1Q", "label": "Somalia" }, + { "id": "dDRPoafJmRbSNDo35tluh0Q", "label": "South Africa" }, + { "id": "dB0zecO7LTJKLVKJsTELlTg", "label": "South Sudan" }, + { "id": "dFlGAxG62SB66mHBcG_YVqw", "label": "Tanzania, United Republic of" }, + { "id": "dprGSrF0hSaiUTpoQSY2NXA", "label": "Togo" }, + { "id": "dN4GzPVULQ66om6ewQQLN9g", "label": "Uganda" }, + { "id": "diXfv3-9xTLaZNm_lZvqj9Q", "label": "Zambia" }, + { "id": "dStcvzn3PRqybHwYK0FhAbw", "label": "Zimbabwe" } + ] + }, + { + "id": "dBt1L9gScRbiwD-BKCh-MPg", + "label": "Northern Africa", + "children": [ + { "id": "dW2q0DrTySAmvf0g6iK_zfA", "label": "Algeria" }, + { "id": "dEC9y1R3tQHmdru9WuARmcg", "label": "Egypt" }, + { "id": "dV7EX39xMR0unLPGPlhLgYQ", "label": "Libya" }, + { "id": "d1xQ_5aAlSneR36igaBJQ-Q", "label": "Morocco" }, + { "id": "dXFw13SloSo6aTfw1k8mrPw", "label": "Sudan" }, + { "id": "ddp6OVEptTgmsu4MN7pBLFw", "label": "Tunisia" }, + { "id": "dgCGs0nf4QiaTlQ_NF8t-CQ", "label": "Western Sahara" } + ] + } + ] + }, + { "id": "d2k8AChmHQs2c7c2rflGyKQ", "label": "Americas", + "children": [ + { + "id": "dX1w1NJKnQFeQYIQzl6CPQQ", + "label": "Northern America", + "children": [ + { "id": "dBfPB-qjvTyuzsjLcghuX4Q", "label": "Bermuda" }, + { "id": "dOs9W4lXASfiW3iJo9-4G-w", "label": "Canada" }, + { "id": "dfJQ8Iq61TMGiwtcErV3iSg", "label": "Greenland" }, + { "id": "dxOGDbTjnRA-1GpcbHuYlTA", "label": "Saint Pierre and Miquelon" }, + { "id": "dHdbc4A01TgmImWHVaaCmDQ", "label": "United States of America" } + ] + }, + { + "id": "dZNXh8F1iT4WD-87l56xgFw", + "label": "Latin America and the Caribbean", + "children": [ + { "id": "dUe1ObDkySOeHTmnJVsVLNg", "label": "Anguilla" }, + { "id": "d6bvphUJWSsW8yQWpOh8e5A", "label": "Antigua and Barbuda" }, + { "id": "dkBLt37YuS0eMatLMBpqg8A", "label": "Argentina" }, + { "id": "dQkLYG3Z9QveZjQL79wsk2g", "label": "Aruba" }, + { "id": "dp6bSsp8dTfWXMnp42kfiSw", "label": "Bahamas" }, + { "id": "dQoj10yKBSbSJhxDlZeqFnA", "label": "Barbados" }, + { "id": "d7A-8gPecSIenAoyARbViXw", "label": "Belize" }, + { "id": "dodI12L3fS3yuvAuy1vPUMQ", "label": "Bolivia (Plurinational State of)" }, + { "id": "d6SQzxHQqSi-WAWpAmWlvgQ", "label": "Bonaire, Sint Eustatius and Saba" }, + { "id": "dv8CBDfFFT1eo5VsbW8ug8g", "label": "Bouvet Island" }, + { "id": "d3cnrWsPhSSmYlINNn233PA", "label": "Brazil" }, + { "id": "dPPxb3DF1SPK1GOrGSbAqEA", "label": "Cayman Islands" }, + { "id": "dcFFVEoKrS9SMtpfwYM7T0Q", "label": "Chile" }, + { "id": "d0_2U06z6RpmHRMt93QV9Rg", "label": "Colombia" }, + { "id": "dTlCRiKUPTAGIAs3z898VuQ", "label": "Costa Rica" }, + { "id": "dz6XKEazETCudod358aG6bw", "label": "Cuba" }, + { "id": "dqLrAT7oASz2dnb4e3ka2nA", "label": "Curaçao" }, + { "id": "dG2TleSijScWe91rJRLRmiQ", "label": "Dominica" }, + { "id": "depioeWI5TvCErimhR5QGaQ", "label": "Dominican Republic" }, + { "id": "d5JpF8f5wThKnj5zIBp8pCw", "label": "Ecuador" }, + { "id": "dwbHvs2TLT-WuzmFzr4nZBg", "label": "El Salvador" }, + { "id": "dkR7konK9TuS_tS2Z0FSanQ", "label": "Falkland Islands (Malvinas)" }, + { "id": "dbYulV0RGRcm6akZuIkUTEA", "label": "French Guiana" }, + { "id": "dHi_hRfNLRxiog5r3NX3_oA", "label": "Grenada" }, + { "id": "dC0UjTjmFQW2iZiZPuec5gA", "label": "Guadeloupe" }, + { "id": "dnucciaKXQx68_l5156G3YQ", "label": "Guatemala" }, + { "id": "dxn_y4gJ0Sb2PhSnmC1IFiw", "label": "Guyana" }, + { "id": "djrmx6Sr9SiGzmnhHH4Dx-Q", "label": "Haiti" }, + { "id": "dlN9mM-wVTBWMv8BCxORmKg", "label": "Honduras" }, + { "id": "dwvMOh-HKSum_OX39doo03A", "label": "Jamaica" }, + { "id": "djiIMP2fuQO2gouqBz4me3Q", "label": "Martinique" }, + { "id": "dLALEIYJDSpq47fB5632b5w", "label": "Mexico" }, + { "id": "dmHkoEZ9wS56utbcjZYJy1A", "label": "Montserrat" }, + { "id": "dkzGKpQRwRhOfdB-5FygcZw", "label": "Nicaragua" }, + { "id": "d5JSEz96tRW2Pq13iL7Mw2w", "label": "Panama" }, + { "id": "dsc5gzgvXRjuGNo60DHBXHA", "label": "Paraguay" }, + { "id": "dLmaSK8N2RNir_7ZMlK9pAw", "label": "Peru" }, + { "id": "dorQxoGcrR8qAg5lDLeRxlQ", "label": "Puerto Rico" }, + { "id": "d7nnDDuLKTx2hkYOGnflA0g", "label": "Saint Barthélemy" }, + { "id": "d-YBmT_ByTM28VXbuzBLXkA", "label": "Saint Kitts and Nevis" }, + { "id": "ddLtlcEKhS_-cDxMgEjyVhA", "label": "Saint Lucia" }, + { "id": "dDvQJz78USJiQyr61ef_Tdw", "label": "Saint Martin (French part)" }, + { "id": "dlEWVujIiS56NaEFI38wy7w", "label": "Saint Vincent and the Grenadines" }, + { "id": "dxRI3JSNkRK-9aY3rlNzZ-A", "label": "Sint Maarten (Dutch part)" }, + { "id": "dL1LDD2qvTpmYwzFWmgZnoQ", "label": "South Georgia and the South Sandwich Islands" }, + { "id": "ds_M4oGklQxGhaPr-8wovKA", "label": "Suriname" }, + { "id": "d3GDRgU6VSwCXafgpeNtkoA", "label": "Trinidad and Tobago" }, + { "id": "dlcuXUEbsT8GYpOSk9U3FfA", "label": "Turks and Caicos Islands" }, + { "id": "d-KzcV6D3SMWyE0C8g3BozA", "label": "Uruguay" }, + { "id": "dx7A2SbjHQd6r1CUk4_l8MA", "label": "Venezuela (Bolivarian Republic of)" }, + { "id": "dzwhfalEAQKa83e0k-fLn6A", "label": "Virgin Islands (British)" }, + { "id": "dyET0AspJRdqeNqxkH0x7qQ", "label": "Virgin Islands (U.S.)" } + ] + } + ] + }, + { + "id": "dDp0ScpagR1eRD4fdtA4G7g", + "label": "Oceania", + "children": [ + { + "id": "dA1frPHzVT_2m5YE_X4-c8w", + "label": "Polynesia", + "children": [ + { "id": "d6bLv8x-KTQef89O6rgkvlg", "label": "American Samoa" }, + { "id": "dV3KAANmzSTaycDpNonL71Q", "label": "Cook Islands" }, + { "id": "dSME-ojhFSKiiWuv6f-yX5w", "label": "French Polynesia" }, + { "id": "dM4bWXoilSgalhryB5g5gzw", "label": "Niue" }, + { "id": "dm-JmPUXESLm8JkXzS7C_rw", "label": "Pitcairn" }, + { "id": "dnR6XVWQ-QWyBfhRyLe2XEg", "label": "Samoa" }, + { "id": "dfpy6EbDHSau7tYbwgoDScQ", "label": "Tokelau" }, + { "id": "dmb1hV1_eTN6Lbd8Nk0481A", "label": "Tonga" }, + { "id": "dYevveZQqRQmLvZa5R1XykQ", "label": "Tuvalu" }, + { "id": "dsoZkPvxLQVeQt3GgOsc8uw", "label": "Wallis and Futuna" } + ] + }, + { + "id": "dHh25bcZnTiGKihOUhsFnYg", + "label": "Micronesia", + "children": [ + { "id": "dvWPI4bW1SEu_D0CfR9fSow", "label": "Guam" }, + { "id": "dBMAiScf8QAGooxwIPfoH-g", "label": "Kiribati" }, + { "id": "dfWOx9-JtQA6RitO64np0jA", "label": "Marshall Islands" }, + { "id": "djechgMEBR1S8RNpKdM2Ptw", "label": "Micronesia (Federated States of)" }, + { "id": "dAco2mlImQ2G7ZWQrOMcvAQ", "label": "Nauru" }, + { "id": "dhmM6Qek5R4yB_OThDO2DDA", "label": "Northern Mariana Islands" }, + { "id": "dxH22ra2ISnaX-uqI0Os7xQ", "label": "Palau" }, + { "id": "dhbEAsjLYR0mta_WRU7O8sA", "label": "United States Minor Outlying Islands" } + ] + }, + { + "id": "dnbCtbw_eTvSpazA4PIvAJQ", + "label": "Melanesia", + "children": [ + { "id": "dozK1ObMNRdSr37rCEN44FA", "label": "Fiji" }, + { "id": "dqgFsaeuUQLKOs2No45AH4Q", "label": "New Caledonia" }, + { "id": "ddvX80eb7S6GBKTKHzVzh7g", "label": "Papua New Guinea" }, + { "id": "dz3fYII7yTtOA7uwLegL3MA", "label": "Solomon Islands" }, + { "id": "dQNzHNAq1QaqUOr6FlZ0kAA", "label": "Vanuatu" } + ] + }, + { + "id": "dczluEjm3Sn-skzw-pKpwew", + "label": "Australia and New Zealand", + "children": [ + { "id": "d12w1jXCRT9WgTrdTBVWFUA", "label": "Australia" }, + { "id": "dKEKkMGyNTJKOXzxL7FCSPA", "label": "Christmas Island" }, + { "id": "dSs50XCz2R8CeUVKo6-kkgw", "label": "Cocos (Keeling) Islands" }, + { "id": "dPs3F4gebTqSDCERVTKcjJA", "label": "Heard Island and McDonald Islands" }, + { "id": "dg7qZF24RQ8mUB26a-rwmDQ", "label": "New Zealand" }, + { "id": "du1b0PVTISweYot_ml4MXrQ", "label": "Norfolk Island" } + ] + } + ] + }, + { + "id": "dTzlVhwApStqpxThPVysyvQ", + "label": "Asia", + "children": [ + { + "id": "d3w5gwKF-Rb6AeETVgz2I-w", + "label": "Eastern Asia", + "children": [ + { "id": "d8ngQyN4lTy2rLKKu8Iw3Qw", "label": "China" }, + { "id": "dUsymsssERWOtwcGawQEIVA", "label": "Hong Kong" }, + { "id": "dygNv_vxJTiibpiHggtfGzQ", "label": "Japan" }, + { "id": "d-Y0saKzpRciVo7W3EavJ0g", "label": "Korea (Democratic People's Republic of)" }, + { "id": "daUudxP12SyyM8456Lq7k9A", "label": "South Korea" }, + { "id": "dv3ix67CQQZKyivHMXSyX9g", "label": "Macao" }, + { "id": "diGbPzp-FSPm0FKVZcWftLA", "label": "Mongolia" }, + { "id": "d2Tj_EPFYSbCYVsiMeLuJ6g", "label": "Taiwan, Province of China" } + ] + }, + { + "id": "dWMpf73UITo2FODRywlSkHA", + "label": "Central Asia", + "children": [ + { "id": "dxX7oFONVQCWWMK6m_WdL3w", "label": "Kazakhstan" }, + { "id": "dUcJfqBsQSQW7JxpZ4JaVKg", "label": "Kyrgyzstan" }, + { "id": "dM3Er_O9wRyae6Dp_dFnq2w", "label": "Tajikistan" }, + { "id": "dvLJTbWn7TGey_jUlRXNgUA", "label": "Turkmenistan" }, + { "id": "dP-3xAyFzSi6YcmyRZyCafA", "label": "Uzbekistan" } + ] + }, + { + "id": "dwgup571UQ4upyc4q0bFH0g", + "label": "South-eastern Asia", + "children": [ + { "id": "dzp-pZetZRbiywT86_x_pOw", "label": "Brunei Darussalam" }, + { "id": "dSTM4lnpRRjqphj8raATT9g", "label": "Cambodia" }, + { "id": "d_L35GlyAQlK8PLJT_Gvd8Q", "label": "Indonesia" }, + { "id": "dlvnrcdUxQn2cXbjsgFp7Eg", "label": "Lao People's Democratic Republic" }, + { "id": "da66dTzAbTH2jiLZSLJCPuA", "label": "Malaysia" }, + { "id": "dk0MpJui3TpWKM-5AyFEaYA", "label": "Myanmar" }, + { "id": "dxB1omwZQQ1ipIbgubP1nyA", "label": "Philippines" }, + { "id": "dDiXCFQo-QhKq-EPerzTXGA", "label": "Singapore" }, + { "id": "dxMWr75qASl2Cww_flZJyKA", "label": "Thailand" }, + { "id": "dzk0rxdg2QbKN-gdSAhWlcw", "label": "Timor-Leste" }, + { "id": "d0mGRa-03Q3Sy2_6oRIy6QA", "label": "Viet Nam" } + ] + }, + { + "id": "dSnjV0XqaSzOlMSS8aMUr0A", + "label": "Western Asia", + "children": [ + { "id": "dLb98h7q6Q0SghZDHg-TNSQ", "label": "Armenia" }, + { "id": "diX39HNj5T8CCPqnqYLqLqQ", "label": "Azerbaijan" }, + { "id": "dqtdho952SbGxDldwTH_vzA", "label": "Bahrain" }, + { "id": "dJ0_I4sSYR3-zzFM2hFteZA", "label": "Cyprus" }, + { "id": "dxUI3NuM7Q_Ke7JxwQuYJaw", "label": "Georgia" }, + { "id": "dZIV40RfIRr-s2sFVKRljew", "label": "Iraq" }, + { "id": "dzS9eFMdDSS6qECnU67Bg-A", "label": "Israel" }, + { "id": "djhVY7dQfSFSA1ThanOp1vg", "label": "Jordan" }, + { "id": "dAKCdrYP1TkyA9Be3Dz27vA", "label": "Kuwait" }, + { "id": "d7MfT56c1S-y-uFOUj9lIWw", "label": "Lebanon" }, + { "id": "ddFtcgKlnRwmH8CHTp8vj6Q", "label": "Oman" }, + { "id": "d0Q_K8i33RXa7WOFWQn7NoA", "label": "Palestine, State of" }, + { "id": "dfqnG-hQxROmhcMi_cxGsJg", "label": "Qatar" }, + { "id": "dfUXSIaZCS--ZFLoVFFKNzQ", "label": "Saudi Arabia" }, + { "id": "d1R_e-XFRTM6Fxk2gM_buwA", "label": "Syrian Arab Republic" }, + { "id": "dSiY9O6tpScu_8vUJl2t5BQ", "label": "Turkey" }, + { "id": "dKHeAw2sCSGa_ojiN66SYnQ", "label": "United Arab Emirates" }, + { "id": "dY5Di_KA7QaGkTuQnDNAumQ", "label": "Yemen" } + ] + }, + { + "id": "dbrdehsFiS_GAEHqVZMkGaA", + "label": "Southern Asia", + "children": [ + { "id": "dKVpd_M0LSWO2FLD-rUsQNA", "label": "Afghanistan" }, + { "id": "dKqHbF6ViTvi3AJnd_5KI8g", "label": "Bangladesh" }, + { "id": "dMvRSqABZRZGchLi2EKMilA", "label": "Bhutan" }, + { "id": "d4N7YiwxjS5-XjpJ1S-OucA", "label": "India" }, + { "id": "daCmCoeIaSh-R5kVqBsPEPg", "label": "Iran (Islamic Republic of)" }, + { "id": "dFPZFbf4QSbiAf1DbTU3lsQ", "label": "Maldives" }, + { "id": "dJu0cU-ekT-iEd3Z4Nad5fw", "label": "Nepal" }, + { "id": "dFLs9erbtSKu6IQNLSVzS1A", "label": "Pakistan" }, + { "id": "dCIuNL6LdSkaZebmPuX-_iA", "label": "Sri Lanka" } + ] + } + ] + } + + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/eic-keywords.json b/app/assets/json/meta/eic-keywords.json new file mode 100644 index 0000000..4943575 --- /dev/null +++ b/app/assets/json/meta/eic-keywords.json @@ -0,0 +1,1429 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "43449105", + "label": "Agronomy", + "prop": { "parent": "43449075"} + }, + { + "id": "43449225", + "label": "Animal and Dairy science", + "prop": { "parent": "43449075"} + }, + { + "id": "43449414", + "label": "Aquaculture", + "prop": { "parent": "43449075"} + }, + { + "id": "43449450", + "label": "Aquatic biology, Hydrobiology", + "prop": { "parent": "43449075"} + }, + { + "id": "43452163", + "label": "Fishery", + "prop": { "parent": "43449075"} + }, + { + "id": "43452313", + "label": "Forestry", + "prop": { "parent": "43449075"} + }, + { + "id": "43453174", + "label": "Horticulture, viticulture", + "prop": { "parent": "43449075"} + }, + { + "id": "43453321", + "label": "Husbandry", + "prop": { "parent": "43449075"} + }, + { + "id": "43455598", + "label": "Paper and wood", + "prop": { "parent": "43449075"} + }, + { + "id": "43455898", + "label": "Plant breeding and plant protection", + "prop": { "parent": "43449075"} + }, + { + "id": "43456123", + "label": "Precision agriculture", + "prop": { "parent": "43449075"} + }, + { + "id": "43457548", + "label": "Soil management", + "prop": { "parent": "43449075"} + }, + { + "id": "31101601", + "label": "Biochemistry", + "prop": { "parent": "43449921"} + }, + { + "id": "43449675", + "label": "Bacteriology", + "prop": { "parent": "43449921"} + }, + { + "id": "43449780", + "label": "Bioeconomy", + "prop": { "parent": "43449921"} + }, + { + "id": "43449819", + "label": "Biohazards, biological containment, biosafety, biosecurity", + "prop": { "parent": "43449921"} + }, + { + "id": "43449822", + "label": "Bioinformatics", + "prop": { "parent": "43449921"} + }, + { + "id": "43449909", + "label": "Bioproducts (products that are manufactured using biological material as feedstock) biomaterials, bioplastics, biofuels, bioderived bulk and fine chemicals, bio-derived novel materials", + "prop": { "parent": "43449921"} + }, + { + "id": "43449912", + "label": "Bioremediation, biodegradation", + "prop": { "parent": "43449921"} + }, + { + "id": "43449924", + "label": "Biotechnology (non-medical), bioreactors, applied microbiology", + "prop": { "parent": "43449921"} + }, + { + "id": "43451115", + "label": "DNA synthesis, modification, repair, recombination, degradation", + "prop": { "parent": "43449921"} + }, + { + "id": "43452712", + "label": "Genetics and heredity", + "prop": { "parent": "43449921"} + }, + { + "id": "43453207", + "label": "Human biology", + "prop": { "parent": "43449921"} + }, + { + "id": "43454653", + "label": "Microbiology", + "prop": { "parent": "43449921"} + }, + { + "id": "43455034", + "label": "Neurochemistry and neuropharmacology", + "prop": { "parent": "43449921"} + }, + { + "id": "43455943", + "label": "Plant sciences, botany", + "prop": { "parent": "43449921"} + }, + { + "id": "43456657", + "label": "Reproductive biology", + "prop": { "parent": "43449921"} + }, + { + "id": "43457218", + "label": "Serology", + "prop": { "parent": "43449921"} + }, + { + "id": "43458334", + "label": "Tissue culture", + "prop": { "parent": "43449921"} + }, + { + "id": "43458937", + "label": "Zoology", + "prop": { "parent": "43449921"} + }, + { + "id": "43458994", + "label": "Bioprocessing technologies (industrial processes relying on biological agents to drive the process) biocatalysis, fermentation", + "prop": { "parent": "43449921"} + }, + { + "id": "43105506", + "label": "Glass, ceramics & construction material", + "prop": { "parent": "43450650"} + }, + { + "id": "43449471", + "label": "Architecture, smart buildings, smart cities, urban engineering", + "prop": { "parent": "43450650"} + }, + { + "id": "43450251", + "label": "Civil engineering, maritime/hydraulic engineering, geotechnics, waste treatment", + "prop": { "parent": "43450650"} + }, + { + "id": "43450641", + "label": "Construction engineering, Municipal and structural engineering", + "prop": { "parent": "43450650"} + }, + { + "id": "43454158", + "label": "Low/nearly zero &-energy positive buildings", + "prop": { "parent": "43450650"} + }, + { + "id": "43458595", + "label": "Urban studies (Planning and development)", + "prop": { "parent": "43450650"} + }, + { + "id": "43451100", + "label": "Distribution and logistics", + "prop": { "parent": "43450656"} + }, + { + "id": "43451431", + "label": "Electronic commerce (eCommerce)", + "prop": { "parent": "43450656"} + }, + { + "id": "43453180", + "label": "Household products", + "prop": { "parent": "43450656"} + }, + { + "id": "43454011", + "label": "Leisure products", + "prop": { "parent": "43450656"} + }, + { + "id": "43454014", + "label": "Leisure services", + "prop": { "parent": "43450656"} + }, + { + "id": "43455679", + "label": "Personal products and services", + "prop": { "parent": "43450656"} + }, + { + "id": "43456720", + "label": "Retail, wholesale or distribution", + "prop": { "parent": "43450656"} + }, + { + "id": "43457224", + "label": "Service innovation", + "prop": { "parent": "43450656"} + }, + { + "id": "43457950", + "label": "Supply chain management", + "prop": { "parent": "43450656"} + }, + { + "id": "43458250", + "label": "Textiles, apparel and luxury goods", + "prop": { "parent": "43450656"} + }, + { + "id": "43458349", + "label": "Tourism / Travel", + "prop": { "parent": "43450656"} + }, + { + "id": "31101619", + "label": "Environmental protection", + "prop": { "parent": "43451193"} + }, + { + "id": "43449564", + "label": "Atmospheric chemistry, atmospheric composition, air pollution", + "prop": { "parent": "43451193"} + }, + { + "id": "43450245", + "label": "Circular economy", + "prop": { "parent": "43451193"} + }, + { + "id": "43450284", + "label": "Climatology and climate change", + "prop": { "parent": "43451193"} + }, + { + "id": "43450899", + "label": "Decontamination and de-pollution", + "prop": { "parent": "43451193"} + }, + { + "id": "43451223", + "label": "Ecology", + "prop": { "parent": "43451193"} + }, + { + "id": "43451728", + "label": "Environmental and Green Technologies", + "prop": { "parent": "43451193"} + }, + { + "id": "43452190", + "label": "Flood forecasting", + "prop": { "parent": "43451193"} + }, + { + "id": "43452733", + "label": "Geographical information systems, cartography", + "prop": { "parent": "43451193"} + }, + { + "id": "43452736", + "label": "Geo-information and spatial data analysis", + "prop": { "parent": "43451193"} + }, + { + "id": "43452748", + "label": "Geology, tectonics, volcanology", + "prop": { "parent": "43451193"} + }, + { + "id": "43453351", + "label": "Hydrology", + "prop": { "parent": "43451193"} + }, + { + "id": "43454296", + "label": "Marine biology", + "prop": { "parent": "43451193"} + }, + { + "id": "43454311", + "label": "Marine ecosystems and processes", + "prop": { "parent": "43451193"} + }, + { + "id": "43454608", + "label": "Meteorology", + "prop": { "parent": "43451193"} + }, + { + "id": "43454695", + "label": "Mineralogy", + "prop": { "parent": "43451193"} + }, + { + "id": "43454965", + "label": "Natural resources exploration and exploitation", + "prop": { "parent": "43451193"} + }, + { + "id": "43458778", + "label": "Waste management", + "prop": { "parent": "43451193"} + }, + { + "id": "43458781", + "label": "Waste recycling", + "prop": { "parent": "43451193"} + }, + { + "id": "43458796", + "label": "Wastewater treatment", + "prop": { "parent": "43451193"} + }, + { + "id": "43458799", + "label": "Water", + "prop": { "parent": "43451193"} + }, + { + "id": "31101542", + "label": "Education", + "prop": { "parent": "31101428"} + }, + { + "id": "31101659", + "label": "Psychology", + "prop": { "parent": "31101428"} + }, + { + "id": "31101667", + "label": "Social Media", + "prop": { "parent": "31101428"} + }, + { + "id": "43449510", + "label": "Arts (arts, history of arts, performing arts, music)", + "prop": { "parent": "31101428"} + }, + { + "id": "43449702", + "label": "Behavioural change", + "prop": { "parent": "31101428"} + }, + { + "id": "43450812", + "label": "Cultural heritage, cultural memory", + "prop": { "parent": "31101428"} + }, + { + "id": "43450962", + "label": "Design innovation", + "prop": { "parent": "31101428"} + }, + { + "id": "43453519", + "label": "Informal education", + "prop": { "parent": "31101428"} + }, + { + "id": "43453573", + "label": "Innovation and diversity (e.g. gender)", + "prop": { "parent": "31101428"} + }, + { + "id": "43453924", + "label": "Languages and Literature", + "prop": { "parent": "31101428"} + }, + { + "id": "43454038", + "label": "Life long learning", + "prop": { "parent": "31101428"} + }, + { + "id": "43454485", + "label": "Media and communications", + "prop": { "parent": "31101428"} + }, + { + "id": "43457407", + "label": "Social issues", + "prop": { "parent": "31101428"} + }, + { + "id": "43458148", + "label": "Teaching materials", + "prop": { "parent": "31101428"} + }, + { + "id": "43449750", + "label": "Biodiesel", + "prop": { "parent": "43451548"} + }, + { + "id": "43449789", + "label": "Bioenergy", + "prop": { "parent": "43451548"} + }, + { + "id": "43449801", + "label": "Biofuels", + "prop": { "parent": "43451548"} + }, + { + "id": "43449804", + "label": "Biogas", + "prop": { "parent": "43451548"} + }, + { + "id": "43449855", + "label": "Biomass", + "prop": { "parent": "43451548"} + }, + { + "id": "43449882", + "label": "Biomethane", + "prop": { "parent": "43451548"} + }, + { + "id": "43451124", + "label": "Domestic appliances", + "prop": { "parent": "43451548"} + }, + { + "id": "43451395", + "label": "Electricity Transmission/Distribution", + "prop": { "parent": "43451548"} + }, + { + "id": "43451404", + "label": "Electrochemistry, batteries and fuel cells", + "prop": { "parent": "43451548"} + }, + { + "id": "43451563", + "label": "Energy Economics", + "prop": { "parent": "43451548"} + }, + { + "id": "43451572", + "label": "Energy Efficiency", + "prop": { "parent": "43451548"} + }, + { + "id": "43451608", + "label": "Energy management", + "prop": { "parent": "43451548"} + }, + { + "id": "43451641", + "label": "Energy systems (production, distribution, application)", + "prop": { "parent": "43451548"} + }, + { + "id": "43451644", + "label": "Energy systems, smart energy, smart grids, wireless energy transfer", + "prop": { "parent": "43451548"} + }, + { + "id": "43452382", + "label": "Fuel Production & Distribution", + "prop": { "parent": "43451548"} + }, + { + "id": "43453348", + "label": "Hydrogen", + "prop": { "parent": "43451548"} + }, + { + "id": "43454164", + "label": "Low/zero carbon communities", + "prop": { "parent": "43451548"} + }, + { + "id": "43454950", + "label": "Natural gas", + "prop": { "parent": "43451548"} + }, + { + "id": "43455796", + "label": "Photovoltaics", + "prop": { "parent": "43451548"} + }, + { + "id": "43456642", + "label": "Renewable energy sources", + "prop": { "parent": "43451548"} + }, + { + "id": "43457581", + "label": "Solar cooling", + "prop": { "parent": "43451548"} + }, + { + "id": "43457593", + "label": "Solar Thermal", + "prop": { "parent": "43451548"} + }, + { + "id": "31101558", + "label": "Manufacturing and processing", + "prop": { "parent": "43451650"} + }, + { + "id": "43448901", + "label": "Acoustics", + "prop": { "parent": "43451650"} + }, + { + "id": "43449579", + "label": "Audio engineering, reliability analysis", + "prop": { "parent": "43451650"} + }, + { + "id": "43449618", + "label": "Automation and control systems", + "prop": { "parent": "43451650"} + }, + { + "id": "43450179", + "label": "Chemical engineering, technical chemistry", + "prop": { "parent": "43451650"} + }, + { + "id": "43450488", + "label": "Communication engineering and systems telecommunications", + "prop": { "parent": "43451650"} + }, + { + "id": "43450683", + "label": "Control engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43451374", + "label": "Electrical and electronic engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43451422", + "label": "Electromagnetism", + "prop": { "parent": "43451650"} + }, + { + "id": "43451425", + "label": "Electromechanical engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43451479", + "label": "Electronics, photonics", + "prop": { "parent": "43451650"} + }, + { + "id": "43452838", + "label": "Graphene, layered material", + "prop": { "parent": "43451650"} + }, + { + "id": "43453453", + "label": "Industrial bioengineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43454413", + "label": "Materials engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43454458", + "label": "Mechanical engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43454590", + "label": "Metallurgy", + "prop": { "parent": "43451650"} + }, + { + "id": "43454641", + "label": "Metrology and measurement", + "prop": { "parent": "43451650"} + }, + { + "id": "43454644", + "label": "Micro (system) engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43454947", + "label": "Nanotechnology, nano-materials, nano engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43455151", + "label": "Novel Materials", + "prop": { "parent": "43451650"} + }, + { + "id": "43455274", + "label": "Ocean engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43455421", + "label": "Optics (including laser optics and quantum optics)", + "prop": { "parent": "43451650"} + }, + { + "id": "43455457", + "label": "Organic electronics", + "prop": { "parent": "43451650"} + }, + { + "id": "43455784", + "label": "Photonics", + "prop": { "parent": "43451650"} + }, + { + "id": "43456075", + "label": "Porous Materials", + "prop": { "parent": "43451650"} + }, + { + "id": "43456219", + "label": "Production technology, process engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43456264", + "label": "Propulsion systems engineering", + "prop": { "parent": "43451650"} + }, + { + "id": "43456819", + "label": "Robotics", + "prop": { "parent": "43451650"} + }, + { + "id": "43457179", + "label": "Semiconductors", + "prop": { "parent": "43451650"} + }, + { + "id": "43457605", + "label": "Solid state materials", + "prop": { "parent": "43451650"} + }, + { + "id": "43457941", + "label": "Superconductivity", + "prop": { "parent": "43451650"} + }, + { + "id": "43458310", + "label": "Thermodynamics", + "prop": { "parent": "43451650"} + }, + { + "id": "43449063", + "label": "Agricultural products", + "prop": { "parent": "43452211"} + }, + { + "id": "43449951", + "label": "Brewers", + "prop": { "parent": "43452211"} + }, + { + "id": "43451094", + "label": "Distillers and vintners", + "prop": { "parent": "43452211"} + }, + { + "id": "43452208", + "label": "Food additives", + "prop": { "parent": "43452211"} + }, + { + "id": "43452223", + "label": "Food contamination", + "prop": { "parent": "43452211"} + }, + { + "id": "43452229", + "label": "Food packaging", + "prop": { "parent": "43452211"} + }, + { + "id": "43452232", + "label": "Food preservation", + "prop": { "parent": "43452211"} + }, + { + "id": "43452238", + "label": "Food quality", + "prop": { "parent": "43452211"} + }, + { + "id": "43452241", + "label": "Food safety", + "prop": { "parent": "43452211"} + }, + { + "id": "43452247", + "label": "Food storage", + "prop": { "parent": "43452211"} + }, + { + "id": "43452250", + "label": "Food technology", + "prop": { "parent": "43452211"} + }, + { + "id": "43457113", + "label": "Secure food chain and wealth products", + "prop": { "parent": "43452211"} + }, + { + "id": "43457473", + "label": "Soft drinks", + "prop": { "parent": "43452211"} + }, + { + "id": "43449036", + "label": "Ageing", + "prop": { "parent": "31101580"} + }, + { + "id": "43449852", + "label": "Biomarkers", + "prop": { "parent": "31101580"} + }, + { + "id": "43450086", + "label": "Cardiac and Cardiovascular systems", + "prop": { "parent": "31101580"} + }, + { + "id": "43450320", + "label": "Clinical medicine", + "prop": { "parent": "31101580"} + }, + { + "id": "43450761", + "label": "Critical care medicine and Emergency medicine", + "prop": { "parent": "31101580"} + }, + { + "id": "43450941", + "label": "Dentistry, oral surgery and medicine", + "prop": { "parent": "31101580"} + }, + { + "id": "43450950", + "label": "Dermatology and venereal diseases", + "prop": { "parent": "31101580"} + }, + { + "id": "43451019", + "label": "Diagnostic tools (e.g. genetic, imaging)", + "prop": { "parent": "31101580"} + }, + { + "id": "43451166", + "label": "Drugs", + "prop": { "parent": "31101580"} + }, + { + "id": "43451353", + "label": "eHealth", + "prop": { "parent": "31101580"} + }, + { + "id": "43451539", + "label": "Endocrinology and metabolism (including diabetes, hormones)", + "prop": { "parent": "31101580"} + }, + { + "id": "43452664", + "label": "Gene therapy", + "prop": { "parent": "31101580"} + }, + { + "id": "43452769", + "label": "Geriatrics and gerontology", + "prop": { "parent": "31101580"} + }, + { + "id": "43453006", + "label": "Healthcare system", + "prop": { "parent": "31101580"} + }, + { + "id": "43453009", + "label": "Health-related biotechnology", + "prop": { "parent": "31101580"} + }, + { + "id": "43453249", + "label": "Human genetics", + "prop": { "parent": "31101580"} + }, + { + "id": "43453411", + "label": "Immunology", + "prop": { "parent": "31101580"} + }, + { + "id": "43453510", + "label": "Infectious diseases", + "prop": { "parent": "31101580"} + }, + { + "id": "43454506", + "label": "Medical devices", + "prop": { "parent": "31101580"} + }, + { + "id": "43455037", + "label": "Neurodegenerative disorders", + "prop": { "parent": "31101580"} + }, + { + "id": "43455247", + "label": "Obstetrics and gynaecology", + "prop": { "parent": "31101580"} + }, + { + "id": "43455337", + "label": "Oncology", + "prop": { "parent": "31101580"} + }, + { + "id": "43455385", + "label": "Ophthalmology", + "prop": { "parent": "31101580"} + }, + { + "id": "43455502", + "label": "Orthopaedics", + "prop": { "parent": "31101580"} + }, + { + "id": "43455571", + "label": "Paediatrics", + "prop": { "parent": "31101580"} + }, + { + "id": "43455631", + "label": "Pathology", + "prop": { "parent": "31101580"} + }, + { + "id": "43455634", + "label": "Patient care", + "prop": { "parent": "31101580"} + }, + { + "id": "43455697", + "label": "Personalised treatment", + "prop": { "parent": "31101580"} + }, + { + "id": "43455745", + "label": "Pharmacology and pharmacy", + "prop": { "parent": "31101580"} + }, + { + "id": "43456348", + "label": "Psychiatry", + "prop": { "parent": "31101580"} + }, + { + "id": "43456504", + "label": "Radiology, nuclear medicine and medical imaging", + "prop": { "parent": "31101580"} + }, + { + "id": "43456594", + "label": "Rehabilitation", + "prop": { "parent": "31101580"} + }, + { + "id": "43456708", + "label": "Respiratory systems", + "prop": { "parent": "31101580"} + }, + { + "id": "43456738", + "label": "Rheumatology", + "prop": { "parent": "31101580"} + }, + { + "id": "43456873", + "label": "Robotics for healthcare", + "prop": { "parent": "31101580"} + }, + { + "id": "43457974", + "label": "Surgery", + "prop": { "parent": "31101580"} + }, + { + "id": "43458352", + "label": "Toxicology", + "prop": { "parent": "31101580"} + }, + { + "id": "43458418", + "label": "Transplantation", + "prop": { "parent": "31101580"} + }, + { + "id": "43458616", + "label": "Urology and nephrology", + "prop": { "parent": "31101580"} + }, + { + "id": "43458634", + "label": "Vaccines", + "prop": { "parent": "31101580"} + }, + { + "id": "43458709", + "label": "Virology", + "prop": { "parent": "31101580"} + }, + { + "id": "43458895", + "label": "Wellbeing", + "prop": { "parent": "31101580"} + }, + { + "id": "42849476", + "label": "Artificial intelligence", + "prop": { "parent": "43453531"} + }, + { + "id": "42849479", + "label": "Blockchain and Distributed Ledger Technology (DLT)", + "prop": { "parent": "43453531"} + }, + { + "id": "42849515", + "label": "Internet of Things, embedded systems, pervasive systems", + "prop": { "parent": "43453531"} + }, + { + "id": "43318244", + "label": "Big data", + "prop": { "parent": "43453531"} + }, + { + "id": "43318301", + "label": "Extended Reality (XR)", + "prop": { "parent": "43453531"} + }, + { + "id": "43448949", + "label": "Advanced computing", + "prop": { "parent": "43453531"} + }, + { + "id": "43449162", + "label": "Algorithms and complexity", + "prop": { "parent": "43453531"} + }, + { + "id": "43449969", + "label": "BTT5 unmanned aircraft (Drone)", + "prop": { "parent": "43453531"} + }, + { + "id": "43450344", + "label": "Cloud computing", + "prop": { "parent": "43453531"} + }, + { + "id": "43450494", + "label": "Communication networks, media, information society", + "prop": { "parent": "43453531"} + }, + { + "id": "43450509", + "label": "Communication technology, high-frequency technology", + "prop": { "parent": "43453531"} + }, + { + "id": "43450560", + "label": "Computational engineering", + "prop": { "parent": "43453531"} + }, + { + "id": "43450584", + "label": "Computer graphics", + "prop": { "parent": "43453531"} + }, + { + "id": "43450590", + "label": "Computer hardware and architecture", + "prop": { "parent": "43453531"} + }, + { + "id": "43450593", + "label": "Computer sciences, information science and bioinformatics", + "prop": { "parent": "43453531"} + }, + { + "id": "43450788", + "label": "Cryptology, security, privacy, quantum crypto", + "prop": { "parent": "43453531"} + }, + { + "id": "43450827", + "label": "Cyber-physical systems", + "prop": { "parent": "43453531"} + }, + { + "id": "43450830", + "label": "Cybersecurity", + "prop": { "parent": "43453531"} + }, + { + "id": "43450875", + "label": "Data protection and privacy", + "prop": { "parent": "43453531"} + }, + { + "id": "43451037", + "label": "Digital games, gamification, applied games, serious games", + "prop": { "parent": "43453531"} + }, + { + "id": "43451046", + "label": "Digital services", + "prop": { "parent": "43453531"} + }, + { + "id": "43451368", + "label": "E-learning, user modelling, collaborative systems", + "prop": { "parent": "43453531"} + }, + { + "id": "43452076", + "label": "Fifth generation cellular network technology (5G)", + "prop": { "parent": "43453531"} + }, + { + "id": "43452136", + "label": "Fintech (Financial technology)", + "prop": { "parent": "43453531"} + }, + { + "id": "43453213", + "label": "Human computer interaction and interface, visualization and natural language processing", + "prop": { "parent": "43453531"} + }, + { + "id": "43453714", + "label": "Interaction, Multimodal, Brain-Computer-Interfaces, Assistive Technologies", + "prop": { "parent": "43453531"} + }, + { + "id": "43453789", + "label": "Internet Services & Applications", + "prop": { "parent": "43453531"} + }, + { + "id": "43454191", + "label": "Machine learning, statistical data processing and applications using signal processing (e.g. speech, image, video)", + "prop": { "parent": "43453531"} + }, + { + "id": "43455019", + "label": "Networks (communication networks, sensor networks, networks of robots, etc.)", + "prop": { "parent": "43453531"} + }, + { + "id": "43455046", + "label": "Neuroimaging and computational neuroscience", + "prop": { "parent": "43453531"} + }, + { + "id": "43455346", + "label": "Ontologies, neural networks, genetic programming, fuzzy logic", + "prop": { "parent": "43453531"} + }, + { + "id": "43457044", + "label": "Scientific computing, simulation and modelling tools", + "prop": { "parent": "43453531"} + }, + { + "id": "43457488", + "label": "Software engineering, operating systems, computer languages", + "prop": { "parent": "43453531"} + }, + { + "id": "43458880", + "label": "Web and information systems, database systems, information retrieval and digital libraries, data fusion", + "prop": { "parent": "43453531"} + }, + { + "id": "43450029", + "label": "Business model innovation", + "prop": { "parent": "43456414"} + }, + { + "id": "43450704", + "label": "Corporate Social responsibility", + "prop": { "parent": "43456414"} + }, + { + "id": "43453285", + "label": "Human resource management", + "prop": { "parent": "43456414"} + }, + { + "id": "43455355", + "label": "Open data", + "prop": { "parent": "43456414"} + }, + { + "id": "43455367", + "label": "Open innovation", + "prop": { "parent": "43456414"} + }, + { + "id": "43456381", + "label": "Public administration innovation", + "prop": { "parent": "43456414"} + }, + { + "id": "43457404", + "label": "Social innovation", + "prop": { "parent": "43456414"} + }, + { + "id": "43450212", + "label": "Chemical, Biological, Radiological and Nuclear (CBRN) protection and decontamination equipment", + "prop": { "parent": "43457125"} + }, + { + "id": "43450749", + "label": "Crisis management", + "prop": { "parent": "43457125"} + }, + { + "id": "43450764", + "label": "Critical infrastructure, emergency systems, security, safety engineering", + "prop": { "parent": "43457125"} + }, + { + "id": "43450977", + "label": "Detection technology", + "prop": { "parent": "43457125"} + }, + { + "id": "43451977", + "label": "Explosives removal", + "prop": { "parent": "43457125"} + }, + { + "id": "43452277", + "label": "Forensic technologies, others", + "prop": { "parent": "43457125"} + }, + { + "id": "43453378", + "label": "Identification", + "prop": { "parent": "43457125"} + }, + { + "id": "43453543", + "label": "Information Security Technologies", + "prop": { "parent": "43457125"} + }, + { + "id": "43453795", + "label": "Interoperable secured communications (Security systems architecture)", + "prop": { "parent": "43457125"} + }, + { + "id": "43454986", + "label": "Navigation, guidance, control and tracking", + "prop": { "parent": "43457125"} + }, + { + "id": "43455022", + "label": "Networks and information security systems", + "prop": { "parent": "43457125"} + }, + { + "id": "43456276", + "label": "Protection", + "prop": { "parent": "43457125"} + }, + { + "id": "43456756", + "label": "Risk management", + "prop": { "parent": "43457125"} + }, + { + "id": "43457095", + "label": "Search and detection", + "prop": { "parent": "43457125"} + }, + { + "id": "43457980", + "label": "Surveillance", + "prop": { "parent": "43457125"} + }, + { + "id": "43451199", + "label": "Earth Observation / Services and applications", + "prop": { "parent": "43457608"} + }, + { + "id": "43452175", + "label": "Flight Dynamics / Position, Navigation, and Timing", + "prop": { "parent": "43457608"} + }, + { + "id": "43452787", + "label": "Global Satellite Navigation System (GNSS) / Services & Applications", + "prop": { "parent": "43457608"} + }, + { + "id": "43453633", + "label": "Instrumentation - telescopes, detectors and techniques", + "prop": { "parent": "43457608"} + }, + { + "id": "43453960", + "label": "Launchers", + "prop": { "parent": "43457608"} + }, + { + "id": "43455331", + "label": "On-Board Data Systems", + "prop": { "parent": "43457608"} + }, + { + "id": "43455442", + "label": "Orbital transportation and re-entry systems", + "prop": { "parent": "43457608"} + }, + { + "id": "43456624", + "label": "Remote sensing", + "prop": { "parent": "43457608"} + }, + { + "id": "43456732", + "label": "RF Payload and Systems", + "prop": { "parent": "43457608"} + }, + { + "id": "43456996", + "label": "Satellites and Probes", + "prop": { "parent": "43457608"} + }, + { + "id": "43457626", + "label": "Space data exploitation", + "prop": { "parent": "43457608"} + }, + { + "id": "43457629", + "label": "Space Debris", + "prop": { "parent": "43457608"} + }, + { + "id": "43457689", + "label": "Space services and products", + "prop": { "parent": "43457608"} + }, + { + "id": "43457725", + "label": "Spacecraft", + "prop": { "parent": "43457608"} + }, + { + "id": "43457953", + "label": "Supporting Propulsion Technologies and Tools", + "prop": { "parent": "43457608"} + }, + { + "id": "43458214", + "label": "Telecommunications", + "prop": { "parent": "43457608"} + }, + { + "id": "43449132", + "label": "Aircraft Avionics, Systems & Equipment AVS", + "prop": { "parent": "43458424"} + }, + { + "id": "43449141", + "label": "Airports APT", + "prop": { "parent": "43458424"} + }, + { + "id": "43449609", + "label": "Automation", + "prop": { "parent": "43458424"} + }, + { + "id": "43449627", + "label": "Automotive", + "prop": { "parent": "43458424"} + }, + { + "id": "43454125", + "label": "Logistics", + "prop": { "parent": "43458424"} + }, + { + "id": "43454335", + "label": "Maritime and infrastructure", + "prop": { "parent": "43458424"} + }, + { + "id": "43454356", + "label": "Maritime transport", + "prop": { "parent": "43458424"} + }, + { + "id": "43454899", + "label": "Multimodality", + "prop": { "parent": "43458424"} + }, + { + "id": "43455010", + "label": "Network infrastructures", + "prop": { "parent": "43458424"} + }, + { + "id": "43456261", + "label": "Propulsion PRO", + "prop": { "parent": "43458424"} + }, + { + "id": "43456513", + "label": "Rail infrastructure", + "prop": { "parent": "43458424"} + }, + { + "id": "43456534", + "label": "Rail Transport", + "prop": { "parent": "43458424"} + }, + { + "id": "43456783", + "label": "Road infrastructure", + "prop": { "parent": "43458424"} + }, + { + "id": "43456789", + "label": "Road transport", + "prop": { "parent": "43458424"} + }, + { + "id": "43457059", + "label": "Sea vessels", + "prop": { "parent": "43458424"} + }, + { + "id": "43458037", + "label": "Sustainable transport", + "prop": { "parent": "43458424"} + }, + { + "id": "43458430", + "label": "Transport Aviation / Air traffic management (ATM)", + "prop": { "parent": "43458424"} + }, + { + "id": "43458442", + "label": "Transport engineering", + "prop": { "parent": "43458424"} + }, + { + "id": "43458601", + "label": "Urban transport", + "prop": { "parent": "43458424"} + }, + { + "id": "43458655", + "label": "Vehicle Technology / Mobility", + "prop": { "parent": "43458424"} + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/global-countries.json b/app/assets/json/meta/global-countries.json new file mode 100755 index 0000000..ded92be --- /dev/null +++ b/app/assets/json/meta/global-countries.json @@ -0,0 +1,200 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://eic.test.eismea.eu/mydashboard/REST/selectors/static/Countries.json", + "updated": "2022-12-01 15:32:12", + "expires": null, + "content": [ + { + "id": "AL", + "label": "Albania" + }, + { + "id": "AT", + "label": "Austria", + "prop": { "EU": true } + }, + { + "id": "BE", + "label": "Belgium", + "prop": { "EU": true } + }, + { + "id": "BA", + "label": "Bosnia and Herzegovina" + }, + { + "id": "BG", + "label": "Bulgaria", + "prop": { "EU": true } + }, + { + "id": "HR", + "label": "Croatia", + "prop": { "EU": true } + }, + { + "id": "CY", + "label": "Cyprus", + "prop": { "EU": true } + }, + { + "id": "CZ", + "label": "Czech Republic", + "prop": { "EU": true } + }, + { + "id": "DK", + "label": "Denmark", + "prop": { "EU": true } + }, + { + "id": "EE", + "label": "Estonia", + "prop": { "EU": true } + }, + { + "id": "FI", + "label": "Finland", + "prop": { "EU": true } + }, + { + "id": "FR", + "label": "France", + "prop": { "EU": true } + }, + { + "id": "DE", + "label": "Germany", + "prop": { "EU": true } + }, + { + "id": "FO", + "label": "Faroe Islands" + }, + { + "id": "GR", + "label": "Greece", + "prop": { "EU": true } + }, + { + "id": "HU", + "label": "Hungary", + "prop": { "EU": true } + }, + { + "id": "IS", + "label": "Iceland" + }, + { + "id": "IE", + "label": "Ireland", + "prop": { "EU": true } + }, + { + "id": "IL", + "label": "Israel" + }, + { + "id": "IT", + "label": "Italy", + "prop": { "EU": true } + }, + { + "id": "LV", + "label": "Latvia", + "prop": { "EU": true } + }, + { + "id": "LT", + "label": "Lithuania", + "prop": { "EU": true } + }, + { + "id": "LU", + "label": "Luxembourg", + "prop": { "EU": true } + }, + { + "id": "MK", + "label": "Macedonia" + }, + { + "id": "MT", + "label": "Malta", + "prop": { "EU": true } + }, + { + "id": "MD", + "label": "Moldova" + }, + { + "id": "ME", + "label": "Montenegro" + }, + { + "id": "NL", + "label": "Netherlands", + "prop": { "EU": true } + }, + { + "id": "NO", + "label": "Norway" + }, + { + "id": "PL", + "label": "Poland", + "prop": { "EU": true } + }, + { + "id": "PT", + "label": "Portugal", + "prop": { "EU": true } + }, + { + "id": "RO", + "label": "Romania", + "prop": { "EU": true } + }, + { + "id": "RS", + "label": "Serbia" + }, + { + "id": "SK", + "label": "Slovakia", + "prop": { "EU": true } + }, + { + "id": "SI", + "label": "Slovenia", + "prop": { "EU": true } + }, + { + "id": "ES", + "label": "Spain", + "prop": { "EU": true } + }, + { + "id": "SE", + "label": "Sweden", + "prop": { "EU": true } + }, + { + "id": "CH", + "label": "Switzerland" + }, + { + "id": "TR", + "label": "Türkiye" + }, + { + "id": "UK", + "label": "United Kingdom" + }, + { + "id": "UA", + "label": "Ukraine" + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/icmp-techdd-statuses.json b/app/assets/json/meta/icmp-techdd-statuses.json new file mode 100644 index 0000000..1aa398a --- /dev/null +++ b/app/assets/json/meta/icmp-techdd-statuses.json @@ -0,0 +1,45 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "updated", + "label": "Drafting" + }, + { + "id": "submitted", + "label": "integrity check" + }, + { + "id": "reviewing", + "label": "Reviewed" + }, + { + "id": "rejected", + "label": "reopened" + }, + { + "id": "pending-review", + "label": "consultation" + }, + { + "id": "reviewed", + "label": "consulted" + }, + { + "id": "validated", + "label": "completed" + }, + { + "id": "cancelled", + "label": "aborted" + }, + { + "id": "aborted", + "label": "aborted" + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/keywords-ccm2.json b/app/assets/json/meta/keywords-ccm2.json new file mode 100644 index 0000000..befe1fe --- /dev/null +++ b/app/assets/json/meta/keywords-ccm2.json @@ -0,0 +1,1236 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "43449075", + "label": "43449075", + "children": [ + { + "id":"43449105", + "label":"Agronomy" + }, + { + "id":"43449225", + "label":"Animal and Dairy science" + }, + { + "id":"43449414", + "label":"Aquaculture" + }, + { + "id":"43449450", + "label":"Aquatic biology, Hydrobiology" + }, + { + "id":"43452163", + "label":"Fishery" + }, + { + "id":"43452313", + "label":"Forestry" + }, + { + "id":"43453174", + "label":"Horticulture, viticulture" + }, + { + "id":"43453321", + "label":"Husbandry" + }, + { + "id":"43455598", + "label":"Paper and wood" + }, + { + "id":"43455898", + "label":"Plant breeding and plant protection" + }, + { + "id":"43456123", + "label":"Precision agriculture" + }, + { + "id":"43457548", + "label":"Soil management" + } + ] + }, + { + "id": "43449921", + "label": "43449921", + "children": [ + { + "id":"31101601", + "label":"Biochemistry" + }, + { + "id":"43449675", + "label":"Bacteriology" + }, + { + "id":"43449780", + "label":"Bioeconomy" + }, + { + "id":"43449819", + "label":"Biohazards, biological containment, biosafety, biosecurity" + }, + { + "id":"43449822", + "label":"Bioinformatics" + }, + { + "id":"43449909", + "label":"Bioproducts (products that are manufactured using biological material as feedstock) biomaterials, bioplastics, biofuels, bioderived bulk and fine chemicals, bio-derived novel materials" + }, + { + "id":"43449912", + "label":"Bioremediation, biodegradation" + }, + { + "id":"43449924", + "label":"Biotechnology (non-medical), bioreactors, applied microbiology" + }, + { + "id":"43451115", + "label":"DNA synthesis, modification, repair, recombination, degradation" + }, + { + "id":"43452712", + "label":"Genetics and heredity" + }, + { + "id":"43453207", + "label":"Human biology" + }, + { + "id":"43454653", + "label":"Microbiology" + }, + { + "id":"43455034", + "label":"Neurochemistry and neuropharmacology" + }, + { + "id":"43455943", + "label":"Plant sciences, botany" + }, + { + "id":"43456657", + "label":"Reproductive biology" + }, + { + "id":"43457218", + "label":"Serology" + }, + { + "id":"43458334", + "label":"Tissue culture" + }, + { + "id":"43458937", + "label":"Zoology" + }, + { + "id":"43458994", + "label":"Bioprocessing technologies (industrial processes relying on biological agents to drive the process) biocatalysis, fermentation" + } + ] + }, + { + "id": "43450650", + "label": "43450650", + "children": [ + { + "id":"43105506", + "label":"Glass, ceramics & construction material" + }, + { + "id":"43449471", + "label":"Architecture, smart buildings, smart cities, urban engineering" + }, + { + "id":"43450251", + "label":"Civil engineering, maritime/hydraulic engineering, geotechnics, waste treatment" + }, + { + "id":"43450641", + "label":"Construction engineering, Municipal and structural engineering" + }, + { + "id":"43454158", + "label":"Low/nearly zero &-energy positive buildings" + }, + { + "id":"43458595", + "label":"Urban studies (Planning and development)" + } + ] + }, + { + "id": "43450656", + "label": "43450656", + "children": [ + { + "id":"43451100", + "label":"Distribution and logistics", + "parent":"43450656" + }, + { + "id":"43451431", + "label":"Electronic commerce (eCommerce)" + }, + { + "id":"43453180", + "label":"Household products" + }, + { + "id":"43454011", + "label":"Leisure products" + }, + { + "id":"43454014", + "label":"Leisure services" + }, + { + "id":"43455679", + "label":"Personal products and services" + }, + { + "id":"43456720", + "label":"Retail, wholesale or distribution" + }, + { + "id":"43457224", + "label":"Service innovation" + }, + { + "id":"43457950", + "label":"Supply chain management" + }, + { + "id":"43458250", + "label":"Textiles, apparel and luxury goods" + }, + { + "id":"43458349", + "label":"Tourism / Travel" + } + ] + }, + { + "id": "43451193", + "label": "43451193", + "children": [ + { + "id":"31101619", + "label":"Environmental protection" + }, + { + "id":"43449564", + "label":"Atmospheric chemistry, atmospheric composition, air pollution" + }, + { + "id":"43450245", + "label":"Circular economy" + }, + { + "id":"43450284", + "label":"Climatology and climate change" + }, + { + "id":"43450899", + "label":"Decontamination and de-pollution" + }, + { + "id":"43451223", + "label":"Ecology" + }, + { + "id":"43451728", + "label":"Environmental and Green Technologies" + }, + { + "id":"43452190", + "label":"Flood forecasting" + }, + { + "id":"43452733", + "label":"Geographical information systems, cartography" + }, + { + "id":"43452736", + "label":"Geo-information and spatial data analysis" + }, + { + "id":"43452748", + "label":"Geology, tectonics, volcanology" + }, + { + "id":"43453351", + "label":"Hydrology" + }, + { + "id":"43454296", + "label":"Marine biology" + }, + { + "id":"43454311", + "label":"Marine ecosystems and processes" + }, + { + "id":"43454608", + "label":"Meteorology" + }, + { + "id":"43454695", + "label":"Mineralogy" + }, + { + "id":"43454965", + "label":"Natural resources exploration and exploitation" + }, + { + "id":"43458778", + "label":"Waste management" + }, + { + "id":"43458781", + "label":"Waste recycling" + }, + { + "id":"43458796", + "label":"Wastewater treatment" + }, + { + "id":"43458799", + "label":"Water" + } + ] + }, + { + "id": "31101428", + "label": "31101428", + "children": [ + { + "id":"31101542", + "label":"Education" + }, + { + "id":"31101659", + "label":"Psychology" + }, + { + "id":"31101667", + "label":"Social Media" + }, + { + "id":"43449510", + "label":"Arts (arts, history of arts, performing arts, music)" + }, + { + "id":"43449702", + "label":"Behavioural change" + }, + { + "id":"43450812", + "label":"Cultural heritage, cultural memory" + }, + { + "id":"43450962", + "label":"Design innovation" + }, + { + "id":"43453519", + "label":"Informal education" + }, + { + "id":"43453573", + "label":"Innovation and diversity (e.g. gender)" + }, + { + "id":"43453924", + "label":"Languages and Literature" + }, + { + "id":"43454038", + "label":"Life long learning" + }, + { + "id":"43454485", + "label":"Media and communications" + }, + { + "id":"43457407", + "label":"Social issues" + }, + { + "id":"43458148", + "label":"Teaching materials" + } + ] + }, + { + "id": "43451548", + "label": "43451548", + "children": [ + { + "id":"43449750", + "label":"Biodiesel" + }, + { + "id":"43449789", + "label":"Bioenergy" + }, + { + "id":"43449801", + "label":"Biofuels" + }, + { + "id":"43449804", + "label":"Biogas" + }, + { + "id":"43449855", + "label":"Biomass" + }, + { + "id":"43449882", + "label":"Biomethane" + }, + { + "id":"43451124", + "label":"Domestic appliances" + }, + { + "id":"43451395", + "label":"Electricity Transmission/Distribution" + }, + { + "id":"43451404", + "label":"Electrochemistry, batteries and fuel cells" + }, + { + "id":"43451563", + "label":"Energy Economics" + }, + { + "id":"43451572", + "label":"Energy Efficiency" + }, + { + "id":"43451608", + "label":"Energy management" + }, + { + "id":"43451641", + "label":"Energy systems (production, distribution, application)" + }, + { + "id":"43451644", + "label":"Energy systems, smart energy, smart grids, wireless energy transfer" + }, + { + "id":"43452382", + "label":"Fuel Production & Distribution" + }, + { + "id":"43453348", + "label":"Hydrogen" + }, + { + "id":"43454164", + "label":"Low/zero carbon communities" + }, + { + "id":"43454950", + "label":"Natural gas" + }, + { + "id":"43455796", + "label":"Photovoltaics" + }, + { + "id":"43456642", + "label":"Renewable energy sources" + }, + { + "id":"43457581", + "label":"Solar cooling" + }, + { + "id":"43457593", + "label":"Solar Thermal" + } + ] + }, + { + "id": "43451650", + "label": "43451650", + "children": [ + { + "id":"31101558", + "label":"Manufacturing and processing" + }, + { + "id":"43448901", + "label":"Acoustics" + }, + { + "id":"43449579", + "label":"Audio engineering, reliability analysis" + }, + { + "id":"43449618", + "label":"Automation and control systems" + }, + { + "id":"43450179", + "label":"Chemical engineering, technical chemistry" + }, + { + "id":"43450488", + "label":"Communication engineering and systems telecommunications" + }, + { + "id":"43450683", + "label":"Control engineering" + }, + { + "id":"43451374", + "label":"Electrical and electronic engineering" + }, + { + "id":"43451422", + "label":"Electromagnetism" + }, + { + "id":"43451425", + "label":"Electromechanical engineering" + }, + { + "id":"43451479", + "label":"Electronics, photonics" + }, + { + "id":"43452838", + "label":"Graphene, layered material" + }, + { + "id":"43453453", + "label":"Industrial bioengineering" + }, + { + "id":"43454413", + "label":"Materials engineering" + }, + { + "id":"43454458", + "label":"Mechanical engineering" + }, + { + "id":"43454590", + "label":"Metallurgy" + }, + { + "id":"43454641", + "label":"Metrology and measurement" + }, + { + "id":"43454644", + "label":"Micro (system) engineering" + }, + { + "id":"43454947", + "label":"Nanotechnology, nano-materials, nano engineering" + }, + { + "id":"43455151", + "label":"Novel Materials" + }, + { + "id":"43455274", + "label":"Ocean engineering" + }, + { + "id":"43455421", + "label":"Optics (including laser optics and quantum optics)" + }, + { + "id":"43455457", + "label":"Organic electronics" + }, + { + "id":"43455784", + "label":"Photonics" + }, + { + "id":"43456075", + "label":"Porous Materials" + }, + { + "id":"43456219", + "label":"Production technology, process engineering" + }, + { + "id":"43456264", + "label":"Propulsion systems engineering" + }, + { + "id":"43456819", + "label":"Robotics" + }, + { + "id":"43457179", + "label":"Semiconductors" + }, + { + "id":"43457605", + "label":"Solid state materials" + }, + { + "id":"43457941", + "label":"Superconductivity" + }, + { + "id":"43458310", + "label":"Thermodynamics" + } + ] + }, + { + "id": "43452211", + "label": "43452211", + "children": [ + { + "id":"43449063", + "label":"Agricultural products" + }, + { + "id":"43449951", + "label":"Brewers" + }, + { + "id":"43451094", + "label":"Distillers and vintners" + }, + { + "id":"43452208", + "label":"Food additives" + }, + { + "id":"43452223", + "label":"Food contamination" + }, + { + "id":"43452229", + "label":"Food packaging" + }, + { + "id":"43452232", + "label":"Food preservation" + }, + { + "id":"43452238", + "label":"Food quality" + }, + { + "id":"43452241", + "label":"Food safety" + }, + { + "id":"43452247", + "label":"Food storage" + }, + { + "id":"43452250", + "label":"Food technology" + }, + { + "id":"43457113", + "label":"Secure food chain and wealth products" + }, + { + "id":"43457473", + "label":"Soft drinks" + } + ] + }, + { + "id": "31101580", + "label": "31101580", + "children": [ + { + "id":"43449036", + "label":"Ageing" + }, + { + "id":"43449852", + "label":"Biomarkers" + }, + { + "id":"43450086", + "label":"Cardiac and Cardiovascular systems" + }, + { + "id":"43450320", + "label":"Clinical medicine" + }, + { + "id":"43450761", + "label":"Critical care medicine and Emergency medicine" + }, + { + "id":"43450941", + "label":"Dentistry, oral surgery and medicine" + }, + { + "id":"43450950", + "label":"Dermatology and venereal diseases" + }, + { + "id":"43451019", + "label":"Diagnostic tools (e.g. genetic, imaging)" + }, + { + "id":"43451166", + "label":"Drugs" + }, + { + "id":"43451353", + "label":"eHealth" + }, + { + "id":"43451539", + "label":"Endocrinology and metabolism (including diabetes, hormones)" + }, + { + "id":"43452664", + "label":"Gene therapy" + }, + { + "id":"43452769", + "label":"Geriatrics and gerontology" + }, + { + "id":"43453006", + "label":"Healthcare system" + }, + { + "id":"43453009", + "label":"Health-related biotechnology" + }, + { + "id":"43453249", + "label":"Human genetics" + }, + { + "id":"43453411", + "label":"Immunology" + }, + { + "id":"43453510", + "label":"Infectious diseases" + }, + { + "id":"43454506", + "label":"Medical devices" + }, + { + "id":"43455037", + "label":"Neurodegenerative disorders" + }, + { + "id":"43455247", + "label":"Obstetrics and gynaecology" + }, + { + "id":"43455337", + "label":"Oncology" + }, + { + "id":"43455385", + "label":"Ophthalmology" + }, + { + "id":"43455502", + "label":"Orthopaedics" + }, + { + "id":"43455571", + "label":"Paediatrics" + }, + { + "id":"43455631", + "label":"Pathology" + }, + { + "id":"43455634", + "label":"Patient care" + }, + { + "id":"43455697", + "label":"Personalised treatment" + }, + { + "id":"43455745", + "label":"Pharmacology and pharmacy" + }, + { + "id":"43456348", + "label":"Psychiatry" + }, + { + "id":"43456504", + "label":"Radiology, nuclear medicine and medical imaging" + }, + { + "id":"43456594", + "label":"Rehabilitation" + }, + { + "id":"43456708", + "label":"Respiratory systems" + }, + { + "id":"43456738", + "label":"Rheumatology" + }, + { + "id":"43456873", + "label":"Robotics for healthcare" + }, + { + "id":"43457974", + "label":"Surgery" + }, + { + "id":"43458352", + "label":"Toxicology" + }, + { + "id":"43458418", + "label":"Transplantation" + }, + { + "id":"43458616", + "label":"Urology and nephrology" + }, + { + "id":"43458634", + "label":"Vaccines" + }, + { + "id":"43458709", + "label":"Virology" + }, + { + "id":"43458895", + "label":"Wellbeing" + } + ] + }, + { + "id": "43453531", + "label": "43453531", + "children": [ + { + "id":"42849476", + "label":"Artificial intelligence" + }, + { + "id":"42849479", + "label":"Blockchain and Distributed Ledger Technology (DLT)" + }, + { + "id":"42849515", + "label":"Internet of Things, embedded systems, pervasive systems" + }, + { + "id":"43318244", + "label":"Big data" + }, + { + "id":"43318301", + "label":"Extended Reality (XR)" + }, + { + "id":"43448949", + "label":"Advanced computing" + }, + { + "id":"43449162", + "label":"Algorithms and complexity" + }, + { + "id":"43449969", + "label":"BTT5 unmanned aircraft (Drone)" + }, + { + "id":"43450344", + "label":"Cloud computing" + }, + { + "id":"43450494", + "label":"Communication networks, media, information society" + }, + { + "id":"43450509", + "label":"Communication technology, high-frequency technology" + }, + { + "id":"43450560", + "label":"Computational engineering" + }, + { + "id":"43450584", + "label":"Computer graphics" + }, + { + "id":"43450590", + "label":"Computer hardware and architecture" + }, + { + "id":"43450593", + "label":"Computer sciences, information science and bioinformatics" + }, + { + "id":"43450788", + "label":"Cryptology, security, privacy, quantum crypto" + }, + { + "id":"43450827", + "label":"Cyber-physical systems" + }, + { + "id":"43450830", + "label":"Cybersecurity" + }, + { + "id":"43450875", + "label":"Data protection and privacy" + }, + { + "id":"43451037", + "label":"Digital games, gamification, applied games, serious games" + }, + { + "id":"43451046", + "label":"Digital services" + }, + { + "id":"43451368", + "label":"E-learning, user modelling, collaborative systems" + }, + { + "id":"43452076", + "label":"Fifth generation cellular network technology (5G)" + }, + { + "id":"43452136", + "label":"Fintech (Financial technology)" + }, + { + "id":"43453213", + "label":"Human computer interaction and interface, visualization and natural language processing" + }, + { + "id":"43453714", + "label":"Interaction, Multimodal, Brain-Computer-Interfaces, Assistive Technologies" + }, + { + "id":"43453789", + "label":"Internet Services & Applications" + }, + { + "id":"43454191", + "label":"Machine learning, statistical data processing and applications using signal processing (e.g. speech, image, video)" + }, + { + "id":"43455019", + "label":"Networks (communication networks, sensor networks, networks of robots, etc.)" + }, + { + "id":"43455046", + "label":"Neuroimaging and computational neuroscience" + }, + { + "id":"43455346", + "label":"Ontologies, neural networks, genetic programming, fuzzy logic" + }, + { + "id":"43457044", + "label":"Scientific computing, simulation and modelling tools" + }, + { + "id":"43457488", + "label":"Software engineering, operating systems, computer languages" + }, + { + "id":"43458880", + "label":"Web and information systems, database systems, information retrieval and digital libraries, data fusion" + } + ] + }, + { + "id": "43456414", + "label": "43456414", + "children": [ + { + "id":"43450029", + "label":"Business model innovation" + }, + { + "id":"43450704", + "label":"Corporate Social responsibility" + }, + { + "id":"43453285", + "label":"Human resource management" + }, + { + "id":"43455355", + "label":"Open data" + }, + { + "id":"43455367", + "label":"Open innovation" + }, + { + "id":"43456381", + "label":"Public administration innovation" + }, + { + "id":"43457404", + "label":"Social innovation" + } + ] + }, + { + "id": "43457125", + "label": "43457125", + "children": [ + { + "id":"43450212", + "label":"Chemical, Biological, Radiological and Nuclear (CBRN) protection and decontamination equipment" + }, + { + "id":"43450749", + "label":"Crisis management" + }, + { + "id":"43450764", + "label":"Critical infrastructure, emergency systems, security, safety engineering" + }, + { + "id":"43450977", + "label":"Detection technology" + }, + { + "id":"43451977", + "label":"Explosives removal" + }, + { + "id":"43452277", + "label":"Forensic technologies, others" + }, + { + "id":"43453378", + "label":"Identification" + }, + { + "id":"43453543", + "label":"Information Security Technologies" + }, + { + "id":"43453795", + "label":"Interoperable secured communications (Security systems architecture)" + }, + { + "id":"43454986", + "label":"Navigation, guidance, control and tracking" + }, + { + "id":"43455022", + "label":"Networks and information security systems" + }, + { + "id":"43456276", + "label":"Protection" + }, + { + "id":"43456756", + "label":"Risk management" + }, + { + "id":"43457095", + "label":"Search and detection" + }, + { + "id":"43457980", + "label":"Surveillance" + } + ] + }, + { + "id": "43457608", + "label": "43457608", + "children": [ + { + "id":"43451199", + "label":"Earth Observation / Services and applications" + }, + { + "id":"43452175", + "label":"Flight Dynamics / Position, Navigation, and Timing" + }, + { + "id":"43452787", + "label":"Global Satellite Navigation System (GNSS) / Services & Applications" + }, + { + "id":"43453633", + "label":"Instrumentation - telescopes, detectors and techniques" + }, + { + "id":"43453960", + "label":"Launchers" + }, + { + "id":"43455331", + "label":"On-Board Data Systems" + }, + { + "id":"43455442", + "label":"Orbital transportation and re-entry systems" + }, + { + "id":"43456624", + "label":"Remote sensing" + }, + { + "id":"43456732", + "label":"RF Payload and Systems" + }, + { + "id":"43456996", + "label":"Satellites and Probes" + }, + { + "id":"43457626", + "label":"Space data exploitation" + }, + { + "id":"43457629", + "label":"Space Debris" + }, + { + "id":"43457689", + "label":"Space services and products" + }, + { + "id":"43457725", + "label":"Spacecraft" + }, + { + "id":"43457953", + "label":"Supporting Propulsion Technologies and Tools" + }, + { + "id":"43458214", + "label":"Telecommunications" + } + ] + }, + { + "id": "43458424", + "label": "43458424", + "children": [ + { + "id":"43449132", + "label":"Aircraft Avionics, Systems & Equipment AVS" + }, + { + "id":"43449141", + "label":"Airports APT" + }, + { + "id":"43449609", + "label":"Automation" + }, + { + "id":"43449627", + "label":"Automotive" + }, + { + "id":"43454125", + "label":"Logistics" + }, + { + "id":"43454335", + "label":"Maritime and infrastructure" + }, + { + "id":"43454356", + "label":"Maritime transport" + }, + { + "id":"43454899", + "label":"Multimodality" + }, + { + "id":"43455010", + "label":"Network infrastructures" + }, + { + "id":"43456261", + "label":"Propulsion PRO" + }, + { + "id":"43456513", + "label":"Rail infrastructure" + }, + { + "id":"43456534", + "label":"Rail Transport" + }, + { + "id":"43456783", + "label":"Road infrastructure" + }, + { + "id":"43456789", + "label":"Road transport" + }, + { + "id":"43457059", + "label":"Sea vessels" + }, + { + "id":"43458037", + "label":"Sustainable transport" + }, + { + "id":"43458430", + "label":"Transport Aviation / Air traffic management (ATM)" + }, + { + "id":"43458442", + "label":"Transport engineering" + }, + { + "id":"43458601", + "label":"Urban transport" + }, + { + "id":"43458655", + "label":"Vehicle Technology / Mobility" + } + ] + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/organisation-functions.json b/app/assets/json/meta/organisation-functions.json new file mode 100644 index 0000000..3a8679b --- /dev/null +++ b/app/assets/json/meta/organisation-functions.json @@ -0,0 +1,765 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://accelerator.eismea.eu/a/diagnostic/form?diagnosticId=26963", + "updated": "2023-05-05 12:32:12", + "expires": null, + "content": [ + {"id": "CEO Chief executive Officer", "label": "CEO Chief executive Officer"}, + {"id": "CFO Chief Financial Officer", "label": "CFO Chief Financial Officer"}, + {"id": "CCO Chief Commercial Officer", "label": "CCO Chief Commercial Officer"}, + {"id": "COO Chief Operating Officer", "label": "COO Chief Operating Officer"}, + {"id": "CSO Chief Scientist Officer", "label": "CSO Chief Scientist Officer"}, + {"id": "CTO Chief Technological Officer", "label": "CTO Chief Technological Officer"}, + {"id": "CMO Chief Medical Officer", "label": "CMO Chief Medical Officer"}, + {"id": "CLO Chief Legal Officer", "label": "CLO Chief Legal Officer"}, + {"id": "CMO Chief Marketing Officer", "label": "CMO Chief Marketing Officer"}, + {"id": "CDO Chief Strategy Officer", "label": "CDO Chief Strategy Officer"}, + {"id": "CCO Chief Compliance Officer", "label": "CCO Chief Compliance Officer"}, + {"id": "Chief Strategy Officer", "label": "Chief Strategy Officer"}, + {"id": "Business Chief", "label": "Business Chief"}, + {"id": "Business President", "label": "Business President"}, + {"id": "Business VP", "label": "Business VP"}, + {"id": "Business Director", "label": "Business Director"}, + {"id": "Business General Manager", "label": "Business General Manager"}, + {"id": "Business Head of Department", "label": "Business Head of Department"}, + {"id": "Business Manager", "label": "Business Manager"}, + {"id": "Business Officer", "label": "Business Officer"}, + {"id": "Business Developer", "label": "Business Developer"}, + {"id": "Business Analyst", "label": "Business Analyst"}, + {"id": "Business Leader", "label": "Business Leader"}, + {"id": "Business Advisor", "label": "Business Advisor"}, + {"id": "Business Consultant", "label": "Business Consultant"}, + {"id": "Business Expert", "label": "Business Expert"}, + {"id": "Business Controller", "label": "Business Controller"}, + {"id": "Marketing Chief", "label": "Marketing Chief"}, + {"id": "Marketing President", "label": "Marketing President"}, + {"id": "Marketing VP", "label": "Marketing VP"}, + {"id": "Marketing Director", "label": "Marketing Director"}, + {"id": "Marketing General Manager", "label": "Marketing General Manager"}, + {"id": "Marketing Head of Department", "label": "Marketing Head of Department"}, + {"id": "Marketing Manager", "label": "Marketing Manager"}, + {"id": "Marketing Officer", "label": "Marketing Officer"}, + {"id": "Marketing Developer", "label": "Marketing Developer"}, + {"id": "Marketing Analyst", "label": "Marketing Analyst"}, + {"id": "Marketing Leader", "label": "Marketing Leader"}, + {"id": "Marketing Advisor", "label": "Marketing Advisor"}, + {"id": "Marketing Consultant", "label": "Marketing Consultant"}, + {"id": "Marketing Expert", "label": "Marketing Expert"}, + {"id": "Marketing Controller", "label": "Marketing Controller"}, + {"id": "Commercial Chief", "label": "Commercial Chief"}, + {"id": "Commercial President", "label": "Commercial President"}, + {"id": "Commercial VP", "label": "Commercial VP"}, + {"id": "Commercial Director", "label": "Commercial Director"}, + {"id": "Commercial General Manager", "label": "Commercial General Manager"}, + {"id": "Commercial Head of Department", "label": "Commercial Head of Department"}, + {"id": "Commercial Manager", "label": "Commercial Manager"}, + {"id": "Commercial Officer", "label": "Commercial Officer"}, + {"id": "Commercial Developer", "label": "Commercial Developer"}, + {"id": "Commercial Analyst", "label": "Commercial Analyst"}, + {"id": "Commercial Leader", "label": "Commercial Leader"}, + {"id": "Commercial Advisor", "label": "Commercial Advisor"}, + {"id": "Commercial Consultant", "label": "Commercial Consultant"}, + {"id": "Commercial Expert", "label": "Commercial Expert"}, + {"id": "Commercial Controller", "label": "Commercial Controller"}, + {"id": "Sales Chief", "label": "Sales Chief"}, + {"id": "Sales President", "label": "Sales President"}, + {"id": "Sales VP", "label": "Sales VP"}, + {"id": "Sales Director", "label": "Sales Director"}, + {"id": "Sales General Manager", "label": "Sales General Manager"}, + {"id": "Sales Head of Department", "label": "Sales Head of Department"}, + {"id": "Sales Manager", "label": "Sales Manager"}, + {"id": "Sales Officer", "label": "Sales Officer"}, + {"id": "Sales Developer", "label": "Sales Developer"}, + {"id": "Sales Analyst", "label": "Sales Analyst"}, + {"id": "Sales Leader", "label": "Sales Leader"}, + {"id": "Sales Advisor", "label": "Sales Advisor"}, + {"id": "Sales Consultant", "label": "Sales Consultant"}, + {"id": "Sales Expert", "label": "Sales Expert"}, + {"id": "Sales Controller", "label": "Sales Controller"}, + {"id": "Public Affairs Chief", "label": "Public Affairs Chief"}, + {"id": "Public Affairs President", "label": "Public Affairs President"}, + {"id": "Public Affairs VP", "label": "Public Affairs VP"}, + {"id": "Public Affairs Director", "label": "Public Affairs Director"}, + {"id": "Public Affairs General Manager", "label": "Public Affairs General Manager"}, + {"id": "Public Affairs Head of Department", "label": "Public Affairs Head of Department"}, + {"id": "Public Affairs Manager", "label": "Public Affairs Manager"}, + {"id": "Public Affairs Officer", "label": "Public Affairs Officer"}, + {"id": "Public Affairs Developer", "label": "Public Affairs Developer"}, + {"id": "Public Affairs Analyst", "label": "Public Affairs Analyst"}, + {"id": "Public Affairs Leader", "label": "Public Affairs Leader"}, + {"id": "Public Affairs Advisor", "label": "Public Affairs Advisor"}, + {"id": "Public Affairs Consultant", "label": "Public Affairs Consultant"}, + {"id": "Public Affairs Expert", "label": "Public Affairs Expert"}, + {"id": "Public Affairs Controller", "label": "Public Affairs Controller"}, + {"id": "Public Relations Chief", "label": "Public Relations Chief"}, + {"id": "Public Relations President", "label": "Public Relations President"}, + {"id": "Public Relations VP", "label": "Public Relations VP"}, + {"id": "Public Relations Director", "label": "Public Relations Director"}, + {"id": "Public Relations General Manager", "label": "Public Relations General Manager"}, + {"id": "Public Relations Head of Department", "label": "Public Relations Head of Department"}, + {"id": "Public Relations Manager", "label": "Public Relations Manager"}, + {"id": "Public Relations Officer", "label": "Public Relations Officer"}, + {"id": "Public Relations Developer", "label": "Public Relations Developer"}, + {"id": "Public Relations Analyst", "label": "Public Relations Analyst"}, + {"id": "Public Relations Leader", "label": "Public Relations Leader"}, + {"id": "Public Relations Advisor", "label": "Public Relations Advisor"}, + {"id": "Public Relations Consultant", "label": "Public Relations Consultant"}, + {"id": "Public Relations Expert", "label": "Public Relations Expert"}, + {"id": "Public Relations Controller", "label": "Public Relations Controller"}, + {"id": "Regulatory affairs Chief", "label": "Regulatory affairs Chief"}, + {"id": "Regulatory affairs President", "label": "Regulatory affairs President"}, + {"id": "Regulatory affairs VP", "label": "Regulatory affairs VP"}, + {"id": "Regulatory affairs Director", "label": "Regulatory affairs Director"}, + {"id": "Regulatory affairs General Manager", "label": "Regulatory affairs General Manager"}, + {"id": "Regulatory affairs Head of Department", "label": "Regulatory affairs Head of Department"}, + {"id": "Regulatory affairs Manager", "label": "Regulatory affairs Manager"}, + {"id": "Regulatory affairs Officer", "label": "Regulatory affairs Officer"}, + {"id": "Regulatory affairs Developer", "label": "Regulatory affairs Developer"}, + {"id": "Regulatory affairs Analyst", "label": "Regulatory affairs Analyst"}, + {"id": "Regulatory affairs Leader", "label": "Regulatory affairs Leader"}, + {"id": "Regulatory affairs Advisor", "label": "Regulatory affairs Advisor"}, + {"id": "Regulatory affairs Consultant", "label": "Regulatory affairs Consultant"}, + {"id": "Regulatory affairs Expert", "label": "Regulatory affairs Expert"}, + {"id": "Regulatory affairs Controller", "label": "Regulatory affairs Controller"}, + {"id": "Certification Chief", "label": "Certification Chief"}, + {"id": "Certification President", "label": "Certification President"}, + {"id": "Certification VP", "label": "Certification VP"}, + {"id": "Certification Director", "label": "Certification Director"}, + {"id": "Certification General Manager", "label": "Certification General Manager"}, + {"id": "Certification Head of Department", "label": "Certification Head of Department"}, + {"id": "Certification Manager", "label": "Certification Manager"}, + {"id": "Certification Officer", "label": "Certification Officer"}, + {"id": "Certification Developer", "label": "Certification Developer"}, + {"id": "Certification Analyst", "label": "Certification Analyst"}, + {"id": "Certification Leader", "label": "Certification Leader"}, + {"id": "Certification Advisor", "label": "Certification Advisor"}, + {"id": "Certification Consultant", "label": "Certification Consultant"}, + {"id": "Certification Expert", "label": "Certification Expert"}, + {"id": "Certification Controller", "label": "Certification Controller"}, + {"id": "Lawyer Chief", "label": "Lawyer Chief"}, + {"id": "Lawyer President", "label": "Lawyer President"}, + {"id": "Lawyer VP", "label": "Lawyer VP"}, + {"id": "Lawyer Director", "label": "Lawyer Director"}, + {"id": "Lawyer General Manager", "label": "Lawyer General Manager"}, + {"id": "Lawyer Head of Department", "label": "Lawyer Head of Department"}, + {"id": "Lawyer Manager", "label": "Lawyer Manager"}, + {"id": "Lawyer Officer", "label": "Lawyer Officer"}, + {"id": "Lawyer Developer", "label": "Lawyer Developer"}, + {"id": "Lawyer Analyst", "label": "Lawyer Analyst"}, + {"id": "Lawyer Leader", "label": "Lawyer Leader"}, + {"id": "Lawyer Advisor", "label": "Lawyer Advisor"}, + {"id": "Lawyer Consultant", "label": "Lawyer Consultant"}, + {"id": "Lawyer Expert", "label": "Lawyer Expert"}, + {"id": "Lawyer Controller", "label": "Lawyer Controller"}, + {"id": "Community Chief", "label": "Community Chief"}, + {"id": "Community President", "label": "Community President"}, + {"id": "Community VP", "label": "Community VP"}, + {"id": "Community Director", "label": "Community Director"}, + {"id": "Community General Manager", "label": "Community General Manager"}, + {"id": "Community Head of Department", "label": "Community Head of Department"}, + {"id": "Community Manager", "label": "Community Manager"}, + {"id": "Community Officer", "label": "Community Officer"}, + {"id": "Community Developer", "label": "Community Developer"}, + {"id": "Community Analyst", "label": "Community Analyst"}, + {"id": "Community Leader", "label": "Community Leader"}, + {"id": "Community Advisor", "label": "Community Advisor"}, + {"id": "Community Consultant", "label": "Community Consultant"}, + {"id": "Community Expert", "label": "Community Expert"}, + {"id": "Community Controller", "label": "Community Controller"}, + {"id": "Legal Chief", "label": "Legal Chief"}, + {"id": "Legal President", "label": "Legal President"}, + {"id": "Legal VP", "label": "Legal VP"}, + {"id": "Legal Director", "label": "Legal Director"}, + {"id": "Legal General Manager", "label": "Legal General Manager"}, + {"id": "Legal Head of Department", "label": "Legal Head of Department"}, + {"id": "Legal Manager", "label": "Legal Manager"}, + {"id": "Legal Officer", "label": "Legal Officer"}, + {"id": "Legal Developer", "label": "Legal Developer"}, + {"id": "Legal Analyst", "label": "Legal Analyst"}, + {"id": "Legal Leader", "label": "Legal Leader"}, + {"id": "Legal Advisor", "label": "Legal Advisor"}, + {"id": "Legal Consultant", "label": "Legal Consultant"}, + {"id": "Legal Expert", "label": "Legal Expert"}, + {"id": "Legal Controller", "label": "Legal Controller"}, + {"id": "Accounting Chief", "label": "Accounting Chief"}, + {"id": "Accounting President", "label": "Accounting President"}, + {"id": "Accounting VP", "label": "Accounting VP"}, + {"id": "Accounting Director", "label": "Accounting Director"}, + {"id": "Accounting General Manager", "label": "Accounting General Manager"}, + {"id": "Accounting Head of Department", "label": "Accounting Head of Department"}, + {"id": "Accounting Manager", "label": "Accounting Manager"}, + {"id": "Accounting Officer", "label": "Accounting Officer"}, + {"id": "Accounting Developer", "label": "Accounting Developer"}, + {"id": "Accounting Analyst", "label": "Accounting Analyst"}, + {"id": "Accounting Leader", "label": "Accounting Leader"}, + {"id": "Accounting Advisor", "label": "Accounting Advisor"}, + {"id": "Accounting Consultant", "label": "Accounting Consultant"}, + {"id": "Accounting Expert", "label": "Accounting Expert"}, + {"id": "Accounting Controller", "label": "Accounting Controller"}, + {"id": "Finance Chief", "label": "Finance Chief"}, + {"id": "Finance President", "label": "Finance President"}, + {"id": "Finance VP", "label": "Finance VP"}, + {"id": "Finance Director", "label": "Finance Director"}, + {"id": "Finance General Manager", "label": "Finance General Manager"}, + {"id": "Finance Head of Department", "label": "Finance Head of Department"}, + {"id": "Finance Manager", "label": "Finance Manager"}, + {"id": "Finance Officer", "label": "Finance Officer"}, + {"id": "Finance Developer", "label": "Finance Developer"}, + {"id": "Finance Analyst", "label": "Finance Analyst"}, + {"id": "Finance Leader", "label": "Finance Leader"}, + {"id": "Finance Advisor", "label": "Finance Advisor"}, + {"id": "Finance Consultant", "label": "Finance Consultant"}, + {"id": "Finance Expert", "label": "Finance Expert"}, + {"id": "Finance Controller", "label": "Finance Controller"}, + {"id": "Government affairs Chief", "label": "Government affairs Chief"}, + {"id": "Government affairs President", "label": "Government affairs President"}, + {"id": "Government affairs VP", "label": "Government affairs VP"}, + {"id": "Government affairs Director", "label": "Government affairs Director"}, + {"id": "Government affairs General Manager", "label": "Government affairs General Manager"}, + {"id": "Government affairs Head of Department", "label": "Government affairs Head of Department"}, + {"id": "Government affairs Manager", "label": "Government affairs Manager"}, + {"id": "Government affairs Officer", "label": "Government affairs Officer"}, + {"id": "Government affairs Developer", "label": "Government affairs Developer"}, + {"id": "Government affairs Analyst", "label": "Government affairs Analyst"}, + {"id": "Government affairs Leader", "label": "Government affairs Leader"}, + {"id": "Government affairs Advisor", "label": "Government affairs Advisor"}, + {"id": "Government affairs Consultant", "label": "Government affairs Consultant"}, + {"id": "Government affairs Expert", "label": "Government affairs Expert"}, + {"id": "Government affairs Controller", "label": "Government affairs Controller"}, + {"id": "Strategy Chief", "label": "Strategy Chief"}, + {"id": "Strategy President", "label": "Strategy President"}, + {"id": "Strategy VP", "label": "Strategy VP"}, + {"id": "Strategy Director", "label": "Strategy Director"}, + {"id": "Strategy General Manager", "label": "Strategy General Manager"}, + {"id": "Strategy Head of Department", "label": "Strategy Head of Department"}, + {"id": "Strategy Manager", "label": "Strategy Manager"}, + {"id": "Strategy Officer", "label": "Strategy Officer"}, + {"id": "Strategy Developer", "label": "Strategy Developer"}, + {"id": "Strategy Analyst", "label": "Strategy Analyst"}, + {"id": "Strategy Leader", "label": "Strategy Leader"}, + {"id": "Strategy Advisor", "label": "Strategy Advisor"}, + {"id": "Strategy Consultant", "label": "Strategy Consultant"}, + {"id": "Strategy Expert", "label": "Strategy Expert"}, + {"id": "Strategy Controller", "label": "Strategy Controller"}, + {"id": "Communication Chief", "label": "Communication Chief"}, + {"id": "Communication President", "label": "Communication President"}, + {"id": "Communication VP", "label": "Communication VP"}, + {"id": "Communication Director", "label": "Communication Director"}, + {"id": "Communication General Manager", "label": "Communication General Manager"}, + {"id": "Communication Head of Department", "label": "Communication Head of Department"}, + {"id": "Communication Manager", "label": "Communication Manager"}, + {"id": "Communication Officer", "label": "Communication Officer"}, + {"id": "Communication Developer", "label": "Communication Developer"}, + {"id": "Communication Analyst", "label": "Communication Analyst"}, + {"id": "Communication Leader", "label": "Communication Leader"}, + {"id": "Communication Advisor", "label": "Communication Advisor"}, + {"id": "Communication Consultant", "label": "Communication Consultant"}, + {"id": "Communication Expert", "label": "Communication Expert"}, + {"id": "Communication Controller", "label": "Communication Controller"}, + {"id": "Product Chief", "label": "Product Chief"}, + {"id": "Product President", "label": "Product President"}, + {"id": "Product VP", "label": "Product VP"}, + {"id": "Product Director", "label": "Product Director"}, + {"id": "Product General Manager", "label": "Product General Manager"}, + {"id": "Product Head of Department", "label": "Product Head of Department"}, + {"id": "Product Manager", "label": "Product Manager"}, + {"id": "Product Officer", "label": "Product Officer"}, + {"id": "Product Developer", "label": "Product Developer"}, + {"id": "Product Analyst", "label": "Product Analyst"}, + {"id": "Product Leader", "label": "Product Leader"}, + {"id": "Product Advisor", "label": "Product Advisor"}, + {"id": "Product Consultant", "label": "Product Consultant"}, + {"id": "Product Expert", "label": "Product Expert"}, + {"id": "Product Controller", "label": "Product Controller"}, + {"id": "Service Chief", "label": "Service Chief"}, + {"id": "Service President", "label": "Service President"}, + {"id": "Service VP", "label": "Service VP"}, + {"id": "Service Director", "label": "Service Director"}, + {"id": "Service General Manager", "label": "Service General Manager"}, + {"id": "Service Head of Department", "label": "Service Head of Department"}, + {"id": "Service Manager", "label": "Service Manager"}, + {"id": "Service Officer", "label": "Service Officer"}, + {"id": "Service Developer", "label": "Service Developer"}, + {"id": "Service Analyst", "label": "Service Analyst"}, + {"id": "Service Leader", "label": "Service Leader"}, + {"id": "Service Advisor", "label": "Service Advisor"}, + {"id": "Service Consultant", "label": "Service Consultant"}, + {"id": "Service Expert", "label": "Service Expert"}, + {"id": "Service Controller", "label": "Service Controller"}, + {"id": "Process Chief", "label": "Process Chief"}, + {"id": "Process President", "label": "Process President"}, + {"id": "Process VP", "label": "Process VP"}, + {"id": "Process Director", "label": "Process Director"}, + {"id": "Process General Manager", "label": "Process General Manager"}, + {"id": "Process Head of Department", "label": "Process Head of Department"}, + {"id": "Process Manager", "label": "Process Manager"}, + {"id": "Process Officer", "label": "Process Officer"}, + {"id": "Process Developer", "label": "Process Developer"}, + {"id": "Process Analyst", "label": "Process Analyst"}, + {"id": "Process Leader", "label": "Process Leader"}, + {"id": "Process Advisor", "label": "Process Advisor"}, + {"id": "Process Consultant", "label": "Process Consultant"}, + {"id": "Process Expert", "label": "Process Expert"}, + {"id": "Process Controller", "label": "Process Controller"}, + {"id": "Production Chief", "label": "Production Chief"}, + {"id": "Production President", "label": "Production President"}, + {"id": "Production VP", "label": "Production VP"}, + {"id": "Production Director", "label": "Production Director"}, + {"id": "Production General Manager", "label": "Production General Manager"}, + {"id": "Production Head of Department", "label": "Production Head of Department"}, + {"id": "Production Manager", "label": "Production Manager"}, + {"id": "Production Officer", "label": "Production Officer"}, + {"id": "Production Developer", "label": "Production Developer"}, + {"id": "Production Analyst", "label": "Production Analyst"}, + {"id": "Production Leader", "label": "Production Leader"}, + {"id": "Production Advisor", "label": "Production Advisor"}, + {"id": "Production Consultant", "label": "Production Consultant"}, + {"id": "Production Expert", "label": "Production Expert"}, + {"id": "Production Controller", "label": "Production Controller"}, + {"id": "Manufacturing Chief", "label": "Manufacturing Chief"}, + {"id": "Manufacturing President", "label": "Manufacturing President"}, + {"id": "Manufacturing VP", "label": "Manufacturing VP"}, + {"id": "Manufacturing Director", "label": "Manufacturing Director"}, + {"id": "Manufacturing General Manager", "label": "Manufacturing General Manager"}, + {"id": "Manufacturing Head of Department", "label": "Manufacturing Head of Department"}, + {"id": "Manufacturing Manager", "label": "Manufacturing Manager"}, + {"id": "Manufacturing Officer", "label": "Manufacturing Officer"}, + {"id": "Manufacturing Developer", "label": "Manufacturing Developer"}, + {"id": "Manufacturing Analyst", "label": "Manufacturing Analyst"}, + {"id": "Manufacturing Leader", "label": "Manufacturing Leader"}, + {"id": "Manufacturing Advisor", "label": "Manufacturing Advisor"}, + {"id": "Manufacturing Consultant", "label": "Manufacturing Consultant"}, + {"id": "Manufacturing Expert", "label": "Manufacturing Expert"}, + {"id": "Manufacturing Controller", "label": "Manufacturing Controller"}, + {"id": "Quality Chief", "label": "Quality Chief"}, + {"id": "Quality President", "label": "Quality President"}, + {"id": "Quality VP", "label": "Quality VP"}, + {"id": "Quality Director", "label": "Quality Director"}, + {"id": "Quality General Manager", "label": "Quality General Manager"}, + {"id": "Quality Head of Department", "label": "Quality Head of Department"}, + {"id": "Quality Manager", "label": "Quality Manager"}, + {"id": "Quality Officer", "label": "Quality Officer"}, + {"id": "Quality Developer", "label": "Quality Developer"}, + {"id": "Quality Analyst", "label": "Quality Analyst"}, + {"id": "Quality Leader", "label": "Quality Leader"}, + {"id": "Quality Advisor", "label": "Quality Advisor"}, + {"id": "Quality Consultant", "label": "Quality Consultant"}, + {"id": "Quality Expert", "label": "Quality Expert"}, + {"id": "Quality Controller", "label": "Quality Controller"}, + {"id": "Customer Success Chief", "label": "Customer Success Chief"}, + {"id": "Customer Success President", "label": "Customer Success President"}, + {"id": "Customer Success VP", "label": "Customer Success VP"}, + {"id": "Customer Success Director", "label": "Customer Success Director"}, + {"id": "Customer Success General Manager", "label": "Customer Success General Manager"}, + {"id": "Customer Success Head of Department", "label": "Customer Success Head of Department"}, + {"id": "Customer Success Manager", "label": "Customer Success Manager"}, + {"id": "Customer Success Officer", "label": "Customer Success Officer"}, + {"id": "Customer Success Developer", "label": "Customer Success Developer"}, + {"id": "Customer Success Analyst", "label": "Customer Success Analyst"}, + {"id": "Customer Success Leader", "label": "Customer Success Leader"}, + {"id": "Customer Success Advisor", "label": "Customer Success Advisor"}, + {"id": "Customer Success Consultant", "label": "Customer Success Consultant"}, + {"id": "Customer Success Expert", "label": "Customer Success Expert"}, + {"id": "Customer Success Controller", "label": "Customer Success Controller"}, + {"id": "Innovation Chief", "label": "Innovation Chief"}, + {"id": "Innovation President", "label": "Innovation President"}, + {"id": "Innovation VP", "label": "Innovation VP"}, + {"id": "Innovation Director", "label": "Innovation Director"}, + {"id": "Innovation General Manager", "label": "Innovation General Manager"}, + {"id": "Innovation Head of Department", "label": "Innovation Head of Department"}, + {"id": "Innovation Manager", "label": "Innovation Manager"}, + {"id": "Innovation Officer", "label": "Innovation Officer"}, + {"id": "Innovation Developer", "label": "Innovation Developer"}, + {"id": "Innovation Analyst", "label": "Innovation Analyst"}, + {"id": "Innovation Leader", "label": "Innovation Leader"}, + {"id": "Innovation Advisor", "label": "Innovation Advisor"}, + {"id": "Innovation Consultant", "label": "Innovation Consultant"}, + {"id": "Innovation Expert", "label": "Innovation Expert"}, + {"id": "Innovation Controller", "label": "Innovation Controller"}, + {"id": "Innovator Chief", "label": "Innovator Chief"}, + {"id": "Innovator President", "label": "Innovator President"}, + {"id": "Innovator VP", "label": "Innovator VP"}, + {"id": "Innovator Director", "label": "Innovator Director"}, + {"id": "Innovator General Manager", "label": "Innovator General Manager"}, + {"id": "Innovator Head of Department", "label": "Innovator Head of Department"}, + {"id": "Innovator Manager", "label": "Innovator Manager"}, + {"id": "Innovator Officer", "label": "Innovator Officer"}, + {"id": "Innovator Developer", "label": "Innovator Developer"}, + {"id": "Innovator Analyst", "label": "Innovator Analyst"}, + {"id": "Innovator Leader", "label": "Innovator Leader"}, + {"id": "Innovator Advisor", "label": "Innovator Advisor"}, + {"id": "Innovator Consultant", "label": "Innovator Consultant"}, + {"id": "Innovator Expert", "label": "Innovator Expert"}, + {"id": "Innovator Controller", "label": "Innovator Controller"}, + {"id": "Intellectual Property Chief", "label": "Intellectual Property Chief"}, + {"id": "Intellectual Property President", "label": "Intellectual Property President"}, + {"id": "Intellectual Property VP", "label": "Intellectual Property VP"}, + {"id": "Intellectual Property Director", "label": "Intellectual Property Director"}, + {"id": "Intellectual Property General Manager", "label": "Intellectual Property General Manager"}, + {"id": "Intellectual Property Head of Department", "label": "Intellectual Property Head of Department"}, + {"id": "Intellectual Property Manager", "label": "Intellectual Property Manager"}, + {"id": "Intellectual Property Officer", "label": "Intellectual Property Officer"}, + {"id": "Intellectual Property Developer", "label": "Intellectual Property Developer"}, + {"id": "Intellectual Property Analyst", "label": "Intellectual Property Analyst"}, + {"id": "Intellectual Property Leader", "label": "Intellectual Property Leader"}, + {"id": "Intellectual Property Advisor", "label": "Intellectual Property Advisor"}, + {"id": "Intellectual Property Consultant", "label": "Intellectual Property Consultant"}, + {"id": "Intellectual Property Expert", "label": "Intellectual Property Expert"}, + {"id": "Intellectual Property Controller", "label": "Intellectual Property Controller"}, + {"id": "External Partnership Chief", "label": "External Partnership Chief"}, + {"id": "External Partnership President", "label": "External Partnership President"}, + {"id": "External Partnership VP", "label": "External Partnership VP"}, + {"id": "External Partnership Director", "label": "External Partnership Director"}, + {"id": "External Partnership General Manager", "label": "External Partnership General Manager"}, + {"id": "External Partnership Head of Department", "label": "External Partnership Head of Department"}, + {"id": "External Partnership Manager", "label": "External Partnership Manager"}, + {"id": "External Partnership Officer", "label": "External Partnership Officer"}, + {"id": "External Partnership Developer", "label": "External Partnership Developer"}, + {"id": "External Partnership Analyst", "label": "External Partnership Analyst"}, + {"id": "External Partnership Leader", "label": "External Partnership Leader"}, + {"id": "External Partnership Advisor", "label": "External Partnership Advisor"}, + {"id": "External Partnership Consultant", "label": "External Partnership Consultant"}, + {"id": "External Partnership Expert", "label": "External Partnership Expert"}, + {"id": "External Partnership Controller", "label": "External Partnership Controller"}, + {"id": "Engineer Chief", "label": "Engineer Chief"}, + {"id": "Engineer President", "label": "Engineer President"}, + {"id": "Engineer VP", "label": "Engineer VP"}, + {"id": "Engineer Director", "label": "Engineer Director"}, + {"id": "Engineer General Manager", "label": "Engineer General Manager"}, + {"id": "Engineer Head of Department", "label": "Engineer Head of Department"}, + {"id": "Engineer Manager", "label": "Engineer Manager"}, + {"id": "Engineer Officer", "label": "Engineer Officer"}, + {"id": "Engineer Developer", "label": "Engineer Developer"}, + {"id": "Engineer Analyst", "label": "Engineer Analyst"}, + {"id": "Engineer Leader", "label": "Engineer Leader"}, + {"id": "Engineer Advisor", "label": "Engineer Advisor"}, + {"id": "Engineer Consultant", "label": "Engineer Consultant"}, + {"id": "Engineer Expert", "label": "Engineer Expert"}, + {"id": "Engineer Controller", "label": "Engineer Controller"}, + {"id": "Technician Chief", "label": "Technician Chief"}, + {"id": "Technician President", "label": "Technician President"}, + {"id": "Technician VP", "label": "Technician VP"}, + {"id": "Technician Director", "label": "Technician Director"}, + {"id": "Technician General Manager", "label": "Technician General Manager"}, + {"id": "Technician Head of Department", "label": "Technician Head of Department"}, + {"id": "Technician Manager", "label": "Technician Manager"}, + {"id": "Technician Officer", "label": "Technician Officer"}, + {"id": "Technician Developer", "label": "Technician Developer"}, + {"id": "Technician Analyst", "label": "Technician Analyst"}, + {"id": "Technician Leader", "label": "Technician Leader"}, + {"id": "Technician Advisor", "label": "Technician Advisor"}, + {"id": "Technician Consultant", "label": "Technician Consultant"}, + {"id": "Technician Expert", "label": "Technician Expert"}, + {"id": "Technician Controller", "label": "Technician Controller"}, + {"id": "Collaborative projects Chief", "label": "Collaborative projects Chief"}, + {"id": "Collaborative projects President", "label": "Collaborative projects President"}, + {"id": "Collaborative projects VP", "label": "Collaborative projects VP"}, + {"id": "Collaborative projects Director", "label": "Collaborative projects Director"}, + {"id": "Collaborative projects General Manager", "label": "Collaborative projects General Manager"}, + {"id": "Collaborative projects Head of Department", "label": "Collaborative projects Head of Department"}, + {"id": "Collaborative projects Manager", "label": "Collaborative projects Manager"}, + {"id": "Collaborative projects Officer", "label": "Collaborative projects Officer"}, + {"id": "Collaborative projects Developer", "label": "Collaborative projects Developer"}, + {"id": "Collaborative projects Analyst", "label": "Collaborative projects Analyst"}, + {"id": "Collaborative projects Leader", "label": "Collaborative projects Leader"}, + {"id": "Collaborative projects Advisor", "label": "Collaborative projects Advisor"}, + {"id": "Collaborative projects Consultant", "label": "Collaborative projects Consultant"}, + {"id": "Collaborative projects Expert", "label": "Collaborative projects Expert"}, + {"id": "Collaborative projects Controller", "label": "Collaborative projects Controller"}, + {"id": "Technology Transfer Chief", "label": "Technology Transfer Chief"}, + {"id": "Technology Transfer President", "label": "Technology Transfer President"}, + {"id": "Technology Transfer VP", "label": "Technology Transfer VP"}, + {"id": "Technology Transfer Director", "label": "Technology Transfer Director"}, + {"id": "Technology Transfer General Manager", "label": "Technology Transfer General Manager"}, + {"id": "Technology Transfer Head of Department", "label": "Technology Transfer Head of Department"}, + {"id": "Technology Transfer Manager", "label": "Technology Transfer Manager"}, + {"id": "Technology Transfer Officer", "label": "Technology Transfer Officer"}, + {"id": "Technology Transfer Developer", "label": "Technology Transfer Developer"}, + {"id": "Technology Transfer Analyst", "label": "Technology Transfer Analyst"}, + {"id": "Technology Transfer Leader", "label": "Technology Transfer Leader"}, + {"id": "Technology Transfer Advisor", "label": "Technology Transfer Advisor"}, + {"id": "Technology Transfer Consultant", "label": "Technology Transfer Consultant"}, + {"id": "Technology Transfer Expert", "label": "Technology Transfer Expert"}, + {"id": "Technology Transfer Controller", "label": "Technology Transfer Controller"}, + {"id": "Research Support Chief", "label": "Research Support Chief"}, + {"id": "Research Support President", "label": "Research Support President"}, + {"id": "Research Support VP", "label": "Research Support VP"}, + {"id": "Research Support Director", "label": "Research Support Director"}, + {"id": "Research Support General Manager", "label": "Research Support General Manager"}, + {"id": "Research Support Head of Department", "label": "Research Support Head of Department"}, + {"id": "Research Support Manager", "label": "Research Support Manager"}, + {"id": "Research Support Officer", "label": "Research Support Officer"}, + {"id": "Research Support Developer", "label": "Research Support Developer"}, + {"id": "Research Support Analyst", "label": "Research Support Analyst"}, + {"id": "Research Support Leader", "label": "Research Support Leader"}, + {"id": "Research Support Advisor", "label": "Research Support Advisor"}, + {"id": "Research Support Consultant", "label": "Research Support Consultant"}, + {"id": "Research Support Expert", "label": "Research Support Expert"}, + {"id": "Research Support Controller", "label": "Research Support Controller"}, + {"id": "Digital Chief", "label": "Digital Chief"}, + {"id": "Digital President", "label": "Digital President"}, + {"id": "Digital VP", "label": "Digital VP"}, + {"id": "Digital Director", "label": "Digital Director"}, + {"id": "Digital General Manager", "label": "Digital General Manager"}, + {"id": "Digital Head of Department", "label": "Digital Head of Department"}, + {"id": "Digital Manager", "label": "Digital Manager"}, + {"id": "Digital Officer", "label": "Digital Officer"}, + {"id": "Digital Developer", "label": "Digital Developer"}, + {"id": "Digital Analyst", "label": "Digital Analyst"}, + {"id": "Digital Leader", "label": "Digital Leader"}, + {"id": "Digital Advisor", "label": "Digital Advisor"}, + {"id": "Digital Consultant", "label": "Digital Consultant"}, + {"id": "Digital Expert", "label": "Digital Expert"}, + {"id": "Digital Controller", "label": "Digital Controller"}, + {"id": "Data Chief", "label": "Data Chief"}, + {"id": "Data President", "label": "Data President"}, + {"id": "Data VP", "label": "Data VP"}, + {"id": "Data Director", "label": "Data Director"}, + {"id": "Data General Manager", "label": "Data General Manager"}, + {"id": "Data Head of Department", "label": "Data Head of Department"}, + {"id": "Data Manager", "label": "Data Manager"}, + {"id": "Data Officer", "label": "Data Officer"}, + {"id": "Data Developer", "label": "Data Developer"}, + {"id": "Data Analyst", "label": "Data Analyst"}, + {"id": "Data Leader", "label": "Data Leader"}, + {"id": "Data Advisor", "label": "Data Advisor"}, + {"id": "Data Consultant", "label": "Data Consultant"}, + {"id": "Data Expert", "label": "Data Expert"}, + {"id": "Data Controller", "label": "Data Controller"}, + {"id": "Data Protection Chief", "label": "Data Protection Chief"}, + {"id": "Data Protection President", "label": "Data Protection President"}, + {"id": "Data Protection VP", "label": "Data Protection VP"}, + {"id": "Data Protection Director", "label": "Data Protection Director"}, + {"id": "Data Protection General Manager", "label": "Data Protection General Manager"}, + {"id": "Data Protection Head of Department", "label": "Data Protection Head of Department"}, + {"id": "Data Protection Manager", "label": "Data Protection Manager"}, + {"id": "Data Protection Officer", "label": "Data Protection Officer"}, + {"id": "Data Protection Developer", "label": "Data Protection Developer"}, + {"id": "Data Protection Analyst", "label": "Data Protection Analyst"}, + {"id": "Data Protection Leader", "label": "Data Protection Leader"}, + {"id": "Data Protection Advisor", "label": "Data Protection Advisor"}, + {"id": "Data Protection Consultant", "label": "Data Protection Consultant"}, + {"id": "Data Protection Expert", "label": "Data Protection Expert"}, + {"id": "Data Protection Controller", "label": "Data Protection Controller"}, + {"id": "Clinical Chief", "label": "Clinical Chief"}, + {"id": "Clinical President", "label": "Clinical President"}, + {"id": "Clinical VP", "label": "Clinical VP"}, + {"id": "Clinical Director", "label": "Clinical Director"}, + {"id": "Clinical General Manager", "label": "Clinical General Manager"}, + {"id": "Clinical Head of Department", "label": "Clinical Head of Department"}, + {"id": "Clinical Manager", "label": "Clinical Manager"}, + {"id": "Clinical Officer", "label": "Clinical Officer"}, + {"id": "Clinical Developer", "label": "Clinical Developer"}, + {"id": "Clinical Analyst", "label": "Clinical Analyst"}, + {"id": "Clinical Leader", "label": "Clinical Leader"}, + {"id": "Clinical Advisor", "label": "Clinical Advisor"}, + {"id": "Clinical Consultant", "label": "Clinical Consultant"}, + {"id": "Clinical Expert", "label": "Clinical Expert"}, + {"id": "Clinical Controller", "label": "Clinical Controller"}, + {"id": "Medical Chief", "label": "Medical Chief"}, + {"id": "Medical President", "label": "Medical President"}, + {"id": "Medical VP", "label": "Medical VP"}, + {"id": "Medical Director", "label": "Medical Director"}, + {"id": "Medical General Manager", "label": "Medical General Manager"}, + {"id": "Medical Head of Department", "label": "Medical Head of Department"}, + {"id": "Medical Manager", "label": "Medical Manager"}, + {"id": "Medical Officer", "label": "Medical Officer"}, + {"id": "Medical Developer", "label": "Medical Developer"}, + {"id": "Medical Analyst", "label": "Medical Analyst"}, + {"id": "Medical Leader", "label": "Medical Leader"}, + {"id": "Medical Advisor", "label": "Medical Advisor"}, + {"id": "Medical Consultant", "label": "Medical Consultant"}, + {"id": "Medical Expert", "label": "Medical Expert"}, + {"id": "Medical Controller", "label": "Medical Controller"}, + {"id": "Key Opinion Leader Chief", "label": "Key Opinion Leader Chief"}, + {"id": "Key Opinion Leader President", "label": "Key Opinion Leader President"}, + {"id": "Key Opinion Leader VP", "label": "Key Opinion Leader VP"}, + {"id": "Key Opinion Leader Director", "label": "Key Opinion Leader Director"}, + {"id": "Key Opinion Leader General Manager", "label": "Key Opinion Leader General Manager"}, + {"id": "Key Opinion Leader Head of Department", "label": "Key Opinion Leader Head of Department"}, + {"id": "Key Opinion Leader Manager", "label": "Key Opinion Leader Manager"}, + {"id": "Key Opinion Leader Officer", "label": "Key Opinion Leader Officer"}, + {"id": "Key Opinion Leader Developer", "label": "Key Opinion Leader Developer"}, + {"id": "Key Opinion Leader Analyst", "label": "Key Opinion Leader Analyst"}, + {"id": "Key Opinion Leader Leader", "label": "Key Opinion Leader Leader"}, + {"id": "Key Opinion Leader Advisor", "label": "Key Opinion Leader Advisor"}, + {"id": "Key Opinion Leader Consultant", "label": "Key Opinion Leader Consultant"}, + {"id": "Key Opinion Leader Expert", "label": "Key Opinion Leader Expert"}, + {"id": "Key Opinion Leader Controller", "label": "Key Opinion Leader Controller"}, + {"id": "Researcher Chief", "label": "Researcher Chief"}, + {"id": "Researcher President", "label": "Researcher President"}, + {"id": "Researcher VP", "label": "Researcher VP"}, + {"id": "Researcher Director", "label": "Researcher Director"}, + {"id": "Researcher General Manager", "label": "Researcher General Manager"}, + {"id": "Researcher Head of Department", "label": "Researcher Head of Department"}, + {"id": "Researcher Manager", "label": "Researcher Manager"}, + {"id": "Researcher Officer", "label": "Researcher Officer"}, + {"id": "Researcher Developer", "label": "Researcher Developer"}, + {"id": "Researcher Analyst", "label": "Researcher Analyst"}, + {"id": "Researcher Leader", "label": "Researcher Leader"}, + {"id": "Researcher Advisor", "label": "Researcher Advisor"}, + {"id": "Researcher Consultant", "label": "Researcher Consultant"}, + {"id": "Researcher Expert", "label": "Researcher Expert"}, + {"id": "Researcher Controller", "label": "Researcher Controller"}, + {"id": "Investigator Chief", "label": "Investigator Chief"}, + {"id": "Investigator President", "label": "Investigator President"}, + {"id": "Investigator VP", "label": "Investigator VP"}, + {"id": "Investigator Director", "label": "Investigator Director"}, + {"id": "Investigator General Manager", "label": "Investigator General Manager"}, + {"id": "Investigator Head of Department", "label": "Investigator Head of Department"}, + {"id": "Investigator Manager", "label": "Investigator Manager"}, + {"id": "Investigator Officer", "label": "Investigator Officer"}, + {"id": "Investigator Developer", "label": "Investigator Developer"}, + {"id": "Investigator Analyst", "label": "Investigator Analyst"}, + {"id": "Investigator Leader", "label": "Investigator Leader"}, + {"id": "Investigator Advisor", "label": "Investigator Advisor"}, + {"id": "Investigator Consultant", "label": "Investigator Consultant"}, + {"id": "Investigator Expert", "label": "Investigator Expert"}, + {"id": "Investigator Controller", "label": "Investigator Controller"}, + {"id": "PhD Chief", "label": "PhD Chief"}, + {"id": "PhD President", "label": "PhD President"}, + {"id": "PhD VP", "label": "PhD VP"}, + {"id": "PhD Director", "label": "PhD Director"}, + {"id": "PhD General Manager", "label": "PhD General Manager"}, + {"id": "PhD Head of Department", "label": "PhD Head of Department"}, + {"id": "PhD Manager", "label": "PhD Manager"}, + {"id": "PhD Officer", "label": "PhD Officer"}, + {"id": "PhD Developer", "label": "PhD Developer"}, + {"id": "PhD Analyst", "label": "PhD Analyst"}, + {"id": "PhD Leader", "label": "PhD Leader"}, + {"id": "PhD Advisor", "label": "PhD Advisor"}, + {"id": "PhD Consultant", "label": "PhD Consultant"}, + {"id": "PhD Expert", "label": "PhD Expert"}, + {"id": "PhD Controller", "label": "PhD Controller"}, + {"id": "Inventor Chief", "label": "Inventor Chief"}, + {"id": "Inventor President", "label": "Inventor President"}, + {"id": "Inventor VP", "label": "Inventor VP"}, + {"id": "Inventor Director", "label": "Inventor Director"}, + {"id": "Inventor General Manager", "label": "Inventor General Manager"}, + {"id": "Inventor Head of Department", "label": "Inventor Head of Department"}, + {"id": "Inventor Manager", "label": "Inventor Manager"}, + {"id": "Inventor Officer", "label": "Inventor Officer"}, + {"id": "Inventor Developer", "label": "Inventor Developer"}, + {"id": "Inventor Analyst", "label": "Inventor Analyst"}, + {"id": "Inventor Leader", "label": "Inventor Leader"}, + {"id": "Inventor Advisor", "label": "Inventor Advisor"}, + {"id": "Inventor Consultant", "label": "Inventor Consultant"}, + {"id": "Inventor Expert", "label": "Inventor Expert"}, + {"id": "Inventor Controller", "label": "Inventor Controller"}, + {"id": "Scientist Chief", "label": "Scientist Chief"}, + {"id": "Scientist President", "label": "Scientist President"}, + {"id": "Scientist VP", "label": "Scientist VP"}, + {"id": "Scientist Director", "label": "Scientist Director"}, + {"id": "Scientist General Manager", "label": "Scientist General Manager"}, + {"id": "Scientist Head of Department", "label": "Scientist Head of Department"}, + {"id": "Scientist Manager", "label": "Scientist Manager"}, + {"id": "Scientist Officer", "label": "Scientist Officer"}, + {"id": "Scientist Developer", "label": "Scientist Developer"}, + {"id": "Scientist Analyst", "label": "Scientist Analyst"}, + {"id": "Scientist Leader", "label": "Scientist Leader"}, + {"id": "Scientist Advisor", "label": "Scientist Advisor"}, + {"id": "Scientist Consultant", "label": "Scientist Consultant"}, + {"id": "Scientist Expert", "label": "Scientist Expert"}, + {"id": "Scientist Controller", "label": "Scientist Controller"}, + {"id": "Technology Development Chief", "label": "Technology Development Chief"}, + {"id": "Technology Development President", "label": "Technology Development President"}, + {"id": "Technology Development VP", "label": "Technology Development VP"}, + {"id": "Technology Development Director", "label": "Technology Development Director"}, + {"id": "Technology Development General Manager", "label": "Technology Development General Manager"}, + {"id": "Technology Development Head of Department", "label": "Technology Development Head of Department"}, + {"id": "Technology Development Manager", "label": "Technology Development Manager"}, + {"id": "Technology Development Officer", "label": "Technology Development Officer"}, + {"id": "Technology Development Developer", "label": "Technology Development Developer"}, + {"id": "Technology Development Analyst", "label": "Technology Development Analyst"}, + {"id": "Technology Development Leader", "label": "Technology Development Leader"}, + {"id": "Technology Development Advisor", "label": "Technology Development Advisor"}, + {"id": "Technology Development Consultant", "label": "Technology Development Consultant"}, + {"id": "Technology Development Expert", "label": "Technology Development Expert"}, + {"id": "Technology Development Controller", "label": "Technology Development Controller"}, + {"id": "Business Development Chief", "label": "Business Development Chief"}, + {"id": "Business Development President", "label": "Business Development President"}, + {"id": "Business Development VP", "label": "Business Development VP"}, + {"id": "Business Development Director", "label": "Business Development Director"}, + {"id": "Business Development General Manager", "label": "Business Development General Manager"}, + {"id": "Business Development Head of Department", "label": "Business Development Head of Department"}, + {"id": "Business Development Manager", "label": "Business Development Manager"}, + {"id": "Business Development Officer", "label": "Business Development Officer"}, + {"id": "Business Development Developer", "label": "Business Development Developer"}, + {"id": "Business Development Analyst", "label": "Business Development Analyst"}, + {"id": "Business Development Leader", "label": "Business Development Leader"}, + {"id": "Business Development Advisor", "label": "Business Development Advisor"}, + {"id": "Business Development Consultant", "label": "Business Development Consultant"}, + {"id": "Business Development Expert", "label": "Business Development Expert"}, + {"id": "Business Development Controller", "label": "Business Development Controller"}, + {"id": "Software Architect", "label": "Software Architect"}, + {"id": "Software Chief", "label": "Software Chief"}, + {"id": "Software President", "label": "Software President"}, + {"id": "Software VP", "label": "Software VP"}, + {"id": "Software Director", "label": "Software Director"}, + {"id": "Software General Manager", "label": "Software General Manager"}, + {"id": "Software Head of Department", "label": "Software Head of Department"}, + {"id": "Software Director", "label": "Software Director"}, + {"id": "Software Manager", "label": "Software Manager"}, + {"id": "Software Officer", "label": "Software Officer"}, + {"id": "Software Developer", "label": "Software Developer"}, + {"id": "Software Analyst", "label": "Software Analyst"}, + {"id": "Software Leader", "label": "Software Leader"}, + {"id": "Software Advisor", "label": "Software Advisor"}, + {"id": "Software Consultant", "label": "Software Consultant"}, + {"id": "Software Expert", "label": "Software Expert"}, + {"id": "Software Controller", "label": "Software Controller"}, + {"id": "Director Ownership", "label": "Director Ownership"}, + {"id": "Supply Chain Chief", "label": "Supply Chain Chief"}, + {"id": "Supply Chain President", "label": "Supply Chain President"}, + {"id": "Supply Chain VP", "label": "Supply Chain VP"}, + {"id": "Supply Chain Director", "label": "Supply Chain Director"}, + {"id": "Supply Chain General Manager", "label": "Supply Chain General Manager"}, + {"id": "Supply Chain Head of Department", "label": "Supply Chain Head of Department"}, + {"id": "Supply Chain Manager", "label": "Supply Chain Manager"}, + {"id": "Supply Chain Officer", "label": "Supply Chain Officer"}, + {"id": "Supply Chain Developer", "label": "Supply Chain Developer"}, + {"id": "Supply Chain Analyst", "label": "Supply Chain Analyst"}, + {"id": "Supply Chain Leader", "label": "Supply Chain Leader"}, + {"id": "Supply Chain Advisor", "label": "Supply Chain Advisor"}, + {"id": "Supply Chain Consultant", "label": "Supply Chain Consultant"}, + {"id": "Supply Chain Expert", "label": "Supply Chain Expert"}, + {"id": "Supply Chain Controller", "label": "Supply Chain Controller"}, + {"id": "Human Resources Chief", "label": "Human Resources Chief"}, + {"id": "Human Resources President", "label": "Human Resources President"}, + {"id": "Human Resources VP", "label": "Human Resources VP"}, + {"id": "Human Resources Director", "label": "Human Resources Director"}, + {"id": "Human Resources General Manager", "label": "Human Resources General Manager"}, + {"id": "Human Resources Head of Department", "label": "Human Resources Head of Department"}, + {"id": "Human Resources Manager", "label": "Human Resources Manager"}, + {"id": "Human Resources Officer", "label": "Human Resources Officer"}, + {"id": "Human Resources Developer", "label": "Human Resources Developer"}, + {"id": "Human Resources Analyst", "label": "Human Resources Analyst"}, + {"id": "Human Resources Leader", "label": "Human Resources Leader"}, + {"id": "Human Resources Advisor", "label": "Human Resources Advisor"}, + {"id": "Human Resources Consultant", "label": "Human Resources Consultant"}, + {"id": "Human Resources Expert", "label": "Human Resources Expert"}, + {"id": "Human Resources Controller", "label": "Human Resources Controller"}, + {"id": "Logistics Chief", "label": "Logistics Chief"}, + {"id": "Logistics President", "label": "Logistics President"}, + {"id": "Logistics VP", "label": "Logistics VP"}, + {"id": "Logistics Director", "label": "Logistics Director"}, + {"id": "Logistics General Manager", "label": "Logistics General Manager"}, + {"id": "Logistics Head of Department", "label": "Logistics Head of Department"}, + {"id": "Logistics Manager", "label": "Logistics Manager"}, + {"id": "Logistics Officer", "label": "Logistics Officer"}, + {"id": "Logistics Developer", "label": "Logistics Developer"}, + {"id": "Logistics Analyst", "label": "Logistics Analyst"}, + {"id": "Logistics Leader", "label": "Logistics Leader"}, + {"id": "Logistics Advisor", "label": "Logistics Advisor"}, + {"id": "Logistics Consultant", "label": "Logistics Consultant"}, + {"id": "Logistics Expert", "label": "Logistics Expert"}, + {"id": "Logistics Controller", "label": "Logistics Controller"}, + {"id": "Laboratory Assistant", "label": "Laboratory Assistant"}, + {"id": "Student Analyst", "label": "Student Analyst"}, + {"id": "Student Consultant", "label": "Student Consultant"}, + {"id": "Student Developer", "label": "Student Developer"}, + {"id": "Student Director", "label": "Student Director"}, + {"id": "Student Leader", "label": "Student Leader"} + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/organisation-genders.json b/app/assets/json/meta/organisation-genders.json new file mode 100644 index 0000000..17ecce0 --- /dev/null +++ b/app/assets/json/meta/organisation-genders.json @@ -0,0 +1,21 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "M", + "label": "Mister" + }, + { + "id": "F", + "label": "Miss" + }, + { + "id": "I", + "label": "I rather not say" + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/project-funding-instruments.json b/app/assets/json/meta/project-funding-instruments.json new file mode 100644 index 0000000..5c86c50 --- /dev/null +++ b/app/assets/json/meta/project-funding-instruments.json @@ -0,0 +1,62 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "dxa-tyJdaSpa5i2E8lO4ePQ", + "label": "SME Instrument" + }, + { + "id": "d9l6-quCkT-aKguoO8jAkBQ", + "label": "Fast Track to Innovation" + }, + { + "id": "dvxAKO-bETAC1VhfXQWASsA", + "label": "Future and Emerging Technologies - Open" + }, + { + "id": "dtf7GvyXoTOyA4-i_N2FrHA", + "label": "Enterprise Europe Network" + }, + { + "id": "dVN9fqX-wTg-osqrKnPBPeA", + "label": "EIC Accelerator" + }, + { + "id": "dbluVfV5HSLC6GgMBI98fTg", + "label": "EIC Pathfinder" + }, + { + "id": "dgi0QLaR3RhKs0TwLeseCrg", + "label": "EIC Transition" + }, + { + "id": "dL1tPaeXdSZOChaQxniUlLg", + "label": "European Innovation Ecosystems" + }, + { + "id": "d0EysoYbGSiu87Fd_GYcJ1w", + "label": "European Institute of Innovation & Technology" + }, + { + "id": "dtqcjwMq-R0yNkj9CBWay_A", + "label": "EIC Prizes" + }, + { + "id": "djGk1DzGcQN-He0e5z2nXBQ", + "label": "EIC Boosters" + }, + { + "id": "derOiWoHrSSa0uNpvJPB31A", + "label": "EIC Scaling Club" + }, + { + "id": "db5POvgHGRqK6rvq8xr-Ycg", + "label": "EIC STEP" + } + + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/project-funding-types.json b/app/assets/json/meta/project-funding-types.json new file mode 100644 index 0000000..156200f --- /dev/null +++ b/app/assets/json/meta/project-funding-types.json @@ -0,0 +1,25 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "diNtoRDr0TamOTyF2DIMaDA", + "label": "Grant only" + }, + { + "id": "di4eFlmYnTjSiJqphaIAHVA", + "label": "Blended" + }, + { + "id": "dXmTz1EglTTeo320gbQbzww", + "label": "Grant first" + }, + { + "id": "dhf-KzmiqRPSREMVOHxLozw", + "label": "Investment only" + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/sample.json b/app/assets/json/meta/sample.json new file mode 100755 index 0000000..b71bb8c --- /dev/null +++ b/app/assets/json/meta/sample.json @@ -0,0 +1,33 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "id": "", + "label": "" + }, + { + "id": "", + "label": "", + "children": [ + { + "id": "", + "label": "" + } + ] + }, + { + "id": "", + "label": "", + "prop": { + "url": "", + "description": "", + "icon": "", + "alt-value": "" + } + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/soe-fundings.json b/app/assets/json/meta/soe-fundings.json new file mode 100644 index 0000000..61675fd --- /dev/null +++ b/app/assets/json/meta/soe-fundings.json @@ -0,0 +1,33 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2024-04-19 14:12:12", + "expires": "2024-04-19 14:12:12", + "content": [ + { + "id": "dbBSto19RQIej9gZmIwyHGg", + "label": "ERDF" + }, + { + "id": "deSFYMEbaR7OLKjOUBOiuRA", + "label": "Recovery and resilience Facility (RRF)" + }, + { + "id": "dwBtwkyKCSFS2zJ6C9n9GGQ", + "label": "National funds" + }, + { + "id": "dGMU0jqh4SGi8SKcnX6WHLQ", + "label": "Regional funds" + }, + { + "id": "dnoR32eh_TRqu7rWrzNWq8Q", + "label": "Private" + }, + { + "id": "dTVTpQG-KRzej86IwE0v7TA", + "label": "Other" + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/submission-countries.json b/app/assets/json/meta/submission-countries.json new file mode 100644 index 0000000..dea39a2 --- /dev/null +++ b/app/assets/json/meta/submission-countries.json @@ -0,0 +1,64 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2022-11-15 20:32:12", + "expires": "2023-11-15 20:32:12", + "content": [ + { + "label":"European Union", + "id":"EU", + "children": [ + {"label":"Austria","id":"AT", "prop": { "EU": true }}, + {"label":"Belgium","id":"BE", "prop": { "EU": true }}, + {"label":"Bulgaria","id":"BG", "prop": { "EU": true }}, + {"label":"Cyprus","id":"CY", "prop": { "EU": true }}, + {"label":"Czech Republic","id":"CZ", "prop": { "EU": true }}, + {"label":"Germany","id":"DE", "prop": { "EU": true }}, + {"label":"Denmark","id":"DK", "prop": { "EU": true }}, + {"label":"Estonia","id":"EE", "prop": { "EU": true }}, + {"label":"France","id":"FR", "prop": { "EU": true }}, + {"label":"Spain","id":"ES", "prop": { "EU": true }}, + {"label":"Finland","id":"FI", "prop": { "EU": true }}, + {"label":"Greece","id":"GR", "prop": { "EU": true }}, + {"label":"Croatia","id":"HR", "prop": { "EU": true }}, + {"label":"Hungary","id":"HU", "prop": { "EU": true }}, + {"label":"Ireland","id":"IE", "prop": { "EU": true }}, + {"label":"Italy","id":"IT", "prop": { "EU": true }}, + {"label":"Lithuania","id":"LT", "prop": { "EU": true }}, + {"label":"Luxembourg","id":"LU", "prop": { "EU": true }}, + {"label":"Latvia","id":"LV", "prop": { "EU": true }}, + {"label":"Malta","id":"MT", "prop": { "EU": true }}, + {"label":"Netherlands","id":"NL", "prop": { "EU": true }}, + {"label":"Poland","id":"PL", "prop": { "EU": true }}, + {"label":"Portugal","id":"PT", "prop": { "EU": true }}, + {"label":"Romania","id":"RO", "prop": { "EU": true }}, + {"label":"Sweden","id":"SE", "prop": { "EU": true }}, + {"label":"Slovenia","id":"SI", "prop": { "EU": true }}, + {"label":"Slovakia","id":"SK", "prop": { "EU": true }} + ] + }, + { + "label":"Other", + "id":"Other", + "children": [ + {"label":"Albania","id":"AL", "prop": { "EU": false }}, + {"label":"Armenia","id":"AM", "prop": { "EU": false }}, + {"label":"Bosnia and Herzegovina","id":"BA", "prop": { "EU": false }}, + {"label":"Faroe Islands","id":"FO", "prop": { "EU": false }}, + {"label":"Georgia","id":"GE", "prop": { "EU": false }}, + {"label":"Iceland","id":"IS", "prop": { "EU": false }}, + {"label":"Israel","id":"IL", "prop": { "EU": false }}, + {"label":"Moldova","id":"MD", "prop": { "EU": false }}, + {"label":"Montenegro","id":"ME", "prop": { "EU": false }}, + {"label":"North Macedonia","id":"MK", "prop": { "EU": false }}, + {"label":"Norway","id":"NO", "prop": { "EU": false }}, + {"label":"Serbia","id":"RS", "prop": { "EU": false }}, + {"label":"Tunisia","id":"TN", "prop": { "EU": false }}, + {"label":"Turkiye","id":"TR", "prop": { "EU": false }}, + {"label":"Ukraine","id":"UA", "prop": { "EU": false }}, + {"label":"United Kingdom","id":"GB", "prop": { "EU": false }} + ] + } + ] +} \ No newline at end of file diff --git a/app/assets/json/meta/templates-tokens-lists.json b/app/assets/json/meta/templates-tokens-lists.json new file mode 100644 index 0000000..f8f450f --- /dev/null +++ b/app/assets/json/meta/templates-tokens-lists.json @@ -0,0 +1,40 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2025-02-10 10:32:12", + "expires": "2027-02-10 10:32:12", + "content": [ + { + "label":"TechDD", + "id":"mkl-TechDD-tokens", + "children": [ + {"label":"personEmail","id":"personEmail"}, + {"label":"personEuLogin","id":"personEuLogin"}, + {"label":"personFirstName","id":"personFirstName"}, + {"label":"personLastName","id":"personLastName"}, + {"label":"personFullName","id":"personFullName"}, + {"label":"organisationFullName","id":"organisationFullName"}, + {"label":"organisationShortName","id":"organisationShortName"}, + {"label":"organisationPIC","id":"organisationPIC"}, + {"label":"proposalId","id":"proposalId"}, + {"label":"proposalAcronym","id":"proposalAcronym"}, + {"label":"proposalType","id":"proposalType"}, + {"label":"expertFirstName","id":"expertFirstName"}, + {"label":"expertLastName","id":"expertLastName"}, + {"label":"expertFullName","id":"expertFullName"}, + {"label":"FIOFirstName","id":"FIOFirstName"}, + {"label":"FIOLastName","id":"FIOLastName"}, + {"label":"FIOFullName","id":"FIOFullName"}, + {"label":"POFirstName","id":"POFirstName"}, + {"label":"POLastName","id":"POLastName"}, + {"label":"POFullName","id":"POFullName"}, + {"label":"TechDDFirstName","id":"TechDDFirstName"}, + {"label":"TechDDLastName","id":"TechDDLastName"}, + {"label":"TechDDFullName","id":"TechDDFullName"}, + {"label":"reportURL","id":"reportURL"}, + {"label":"unsubscribeURL","id":"unsubscribeURL"} + ] + } + ] +} \ No newline at end of file diff --git a/app/assets/json/system/user-messages.json b/app/assets/json/system/user-messages.json new file mode 100644 index 0000000..733e4e0 --- /dev/null +++ b/app/assets/json/system/user-messages.json @@ -0,0 +1,31 @@ +{ + "version": "1.0", + "locale": "en-uk", + "source": "https://domain/endpoint", + "updated": "2023-11-14 11:00:00", + "expires": "2023-11-14 11:00:00", + "content": [ + { + "id": "shutdownSoon", + "label": "Shutdown in minutes", + "severity": "warning", + "duration": 30, + "message": [ + "We're improving your MyEIC platform.", + "Therefore, we need to shut-down the platform in a few minutes.", + "Please promptly finish-up what you're doing and log-out." + ] + }, + { + "id": "shutdownNow", + "label": "Shutdown now", + "severity": "danger", + "duration": 0, + "message": [ + "The platform will now be shut-down for maintenance !", + "You'll be logged-out in a few seconds.", + "Feel free to be back on MyEIC in an hour." + ] + } + ] +} \ No newline at end of file diff --git a/app/assets/json/tests/New-feature-todo.txt b/app/assets/json/tests/New-feature-todo.txt new file mode 100644 index 0000000..a773f37 --- /dev/null +++ b/app/assets/json/tests/New-feature-todo.txt @@ -0,0 +1,41 @@ +/* + +Typical TODO-list for new app feature: + +=> New route: + => Delegating route in baseRoutes.json (without method) + => Add real route(s) in the xxxController.json (section:routes) + +=> New controller : + => Create xxxController.json (minimum: routes, views to load, model to load) + => Create xxxController.js + => (!) make sure to have a correct "app.registerClass"(same as filename !) + => (!) make sure the class name is unique across the universe + => Create the methods used in the route(s) definition + => Add this.loadWindow in the method(s) + => second param is object of anything to pass to view, such ass model(s) (1) + +=> New model : + => Create xxxModel.js + => (!) make sure to have a correct "app.registerClass" (same as filename !) + => (!) make sure the class name is unique across the universe + +=> New view : + => Create xxxView.html + => Create xxxView.js + => (!) make sure to have a correct "app.registerClass" (same as filename !) + => (!) make sure the class name is unique across the universe + => Needs at least a method "DOMContentLoaded(options)" + => probably want to use "ui.eicfy(this.el)" + => setup all your dom & components references + => probably want to get stuff from the controller via options.xxx + => typical: "this.model = this.options.model" (see (1)) + or: like "for(let model in options.models) this[model] = options.models[model]" + +=> Make a menu entry : + => Add an entry in "/app/assets/json/global/app-menu-map.json" + => (!) Make sure to select the proper roles (or "*" for open-bar) + + + +*/ \ No newline at end of file diff --git a/app/assets/json/tests/available-pics.txt b/app/assets/json/tests/available-pics.txt new file mode 100644 index 0000000..a69cf01 --- /dev/null +++ b/app/assets/json/tests/available-pics.txt @@ -0,0 +1,106 @@ +889194733 Granted +934188280 Granted +892649679 Granted +917568106 Granted +904060759 Granted +888564233 Granted +888330366 Granted +888554145 Granted +898827900 Granted +888323091 Granted +888325128 Granted +888511562 Granted +892722235 Granted +913000861 Granted +889396978 Granted +890403838 Granted +898781534 Granted +931664437 Granted +904105282 Granted +886470682 Granted +894431763 Granted +910667138 Granted +886482710 Granted +890038730 Granted +892657148 Granted +910897028 Granted +886501625 Granted +904414615 Granted +910449664 Granted +907587485 Granted +889228295 Granted +891358221 Granted +886526845 Granted +936304335 Granted +894423712 Granted +907679247 Granted +925244783 Granted +885790324 Granted +885800315 Granted +931630681 Granted +891563279 Granted +898815387 Granted +911172023 Granted +911227992 Granted +885787123 Granted +891010476 Granted +894993878 Granted +885846390 Granted +895010174 Granted +889226258 Granted +886396671 Granted + + +927984548 Granted +891694714 +891087979 +995981645 +905736531 NIKE + + + +***************************** SHORTPROPS ***************************** + + +User Org SP +n0005lk9 / / +n0005lka 891808301 / +n0005lkb 888657256 190157586 +n0005lkd / 190116115 + +steinic 886396671 created + + +n0005lke / Z8bltqvKewuraPkGN0rS (not in the BE yet --> need onboarding) / 190117162 +n0005lkf (not in the BE yet --> need onboarding) 923569011 190138101 +n0005lk9 --> l'utilisateur existe mais n'a accès à rien +n0005lka --> l'utilisateur existe et est admin de l'organisation 891808301 (qui existe elle aussi) +n0005lkb --> l'utilisateur est admin de l'organisation et de la short mentionnées +n0005lkd --> l'utilisateur est admin de la short mentionnée (qui n'a pas de PIC) ; il n'est membre d'aucune organisation +n0005lke --> l'utilisateur n'existe pas encore dans le BE mais son EULogin est lié à une short existante (qui n'a pas de PIC) +n0005lkf --> l'utilisateur n'existe pas encore dans le BE mais son EULogin est lié à une short existante, qui elle-même est liée à une organisation (qui n'existe pas encore dans le BE) +n0005lkl +n0005lki +n0005lkj + +T3stE2E@eic.EU + + +Gavin.eic1@gmail.com: n000110z / Easme12345678901 => Z8bltqvKewuraPkGN0rS +samantha.patelle@gmail.com Easme12345 + +n0005jin / uraPkGN0rSZ8bltqvKew : BP_SPOC_FastTrack + + +https://myeic.dev.eismea.eu/applicant/999519720 +999507207 +999513706 +999516519 +999519720 +999588784 +999678121 +999770950 +999780262 +999796946 +999833612 +999906459 diff --git a/app/assets/json/tests/ced.json b/app/assets/json/tests/ced.json new file mode 100644 index 0000000..a7c6e02 --- /dev/null +++ b/app/assets/json/tests/ced.json @@ -0,0 +1,17 @@ +{ + "success" : true, + "payload": [ + { + "family_name": "Stein", + "given_name": "Nicolas", + "email": "nicolas.stein@disney.com", + "https://ecas.ec.europa.eu/claims/uid":"steinni" + }, + { + "family_name": "Lapraline", + "given_name": "Toto", + "email": "toto@gmail.com", + "https://ecas.ec.europa.eu/claims/uid":"piperto" + } + ] +} diff --git a/app/assets/json/tests/existing_roles.json b/app/assets/json/tests/existing_roles.json new file mode 100644 index 0000000..ff1b187 --- /dev/null +++ b/app/assets/json/tests/existing_roles.json @@ -0,0 +1,32 @@ +[ + { + "role": "BP_PO", + "permissions": { + "tokens": [ "list", "setSettings", "getSettings" ], + "users": [ "list", "search", "create", "revoke" ], + "company": [ "search", "grant", "revoke" ], + "templates": ["list", "search", "create", "clone", "edit", "reject", "approve" ] + } + }, + { "role": "BP_HoU", + "permissions": { + "tokens": [ "list" ], + "users": [ ], + "company": [ ] + } + }, + { "role": "BP_SPOC_FastTrack", + "permissions": { + "tokens": [ "list" ], + "users": [ "list", "search", "create", "revoke" ], + "company": [ "search", "grant" ] + } + }, + { "role": "BP_SPOC_Plugin", + "permissions": { + "tokens": [ "list", "getPrograms", "addProgram", "removeProgram" ], + "users": [ "list", "search", "create", "revoke" ], + "company": [ "search", "grant" ] + } + } +] diff --git a/app/assets/json/tests/icons.html b/app/assets/json/tests/icons.html new file mode 100644 index 0000000..0720300 --- /dev/null +++ b/app/assets/json/tests/icons.html @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/json/tests/massMailer-infos.txt b/app/assets/json/tests/massMailer-infos.txt new file mode 100644 index 0000000..9348a21 --- /dev/null +++ b/app/assets/json/tests/massMailer-infos.txt @@ -0,0 +1,11 @@ +CNS infos: + +Home page in confluence: +https://citnet.tech.ec.europa.eu/CITnet/confluence/display/CNS/CNS+Home +API swagger: +https://webgate.acceptance.ec.europa.eu/cns/restapi/?ticket=ST-3492070-ib8qIagzgjT0HjAnhZogjDJSwITAq4YOCQaPzSEzqkjXKYaMeSCdzzdjIxd6OCLEzgJYDCWfcAwTXd4czOpzwnrU-zGrcc7GCOy8q7wCXbuuQ9K-QDr1sFx5wNzYWsj7jNzSnl6VPOBo2YiHpKMXIlWXUDD7sVt23FD6R4fZfIxnlYH4pcAATXPFU5UaOFC1UzHyzvm#/ + + + + + diff --git a/app/assets/json/tests/model_bug.txt b/app/assets/json/tests/model_bug.txt new file mode 100644 index 0000000..f752428 --- /dev/null +++ b/app/assets/json/tests/model_bug.txt @@ -0,0 +1,80 @@ + *********************************************** + * Raiders of the lost-arcmodel (archaïc model)* + *********************************************** + +===> Le comportement zarb: +On édite une propal, on refocus le dashboard, on clique sur view de la même propal (probablement idem si edit) : +La propal se re-focus, mais les dernières données encodées n'y sont pas. +Biensur, réessayé en veillant bien à attendre le temps de l'auto-save, +vérifié en voyant passer le PUT en console-network mais le blème est bien côté FE. + + + +===> L'enquête: +- Suivit le reloading des données en les dumpant partout, depuis le modèle (reload OK, données fraiches, donc effectivement c'est pas le BE) +jusque dans la vue ou -surprise- elles sont périmées. +- Pourtant séquence temporelle correcte, on a bien le model.getPropa avant le view.fill +- Finalement soupçon sur l'instantiation des modèles => mise (temoraire) d'un UUID random comme propriété du modèle dans son constructeur. + Du coup on peux tracer les changements d'instance. + + +===> Le diagnostique: +L'utilisateur sur le dashboard, fait un "Edit" sur la propal (première ouverture de cette propal): +- Route vers "SubmissionController::proposal" +- Ctrl instancie le model submissionModel (instance SM1) +- Ctrl load les datas dans SM1.data + THEN il fait un this.loadwindow (SumissionShortForm2023View), passe tous les modeles (dont SM1) + son ancêtre "EICcontroller" fait un "createwindow", et un "loadview" : param "data.models" =tous les modeles (dont SM1) +- "DOMContentLoaded(options)" est lancé dans la view "SubmissionShortForm2023View", SM1 arrive par "options.models", devient "this.submission" +- La view-propal fait des "fill()" pour tous les tabs, prend ses datas dans "this.submission" donc dans SM1.data ===> all good + +- Ensuite, le user refocus la fenetre dashboard et fait un "view" sur la même propal. (probablement un "edit" aurais le même comportement) +- Route vers "SubmissionController::proposal" +- Ctrl instancie le model submissionModel (instance SM2) ====> aie ! +- Ctrl load les datas fraiches dans SM2.data + THEN il fait un loadwindow (SumissionShortForm2023View), passe tous les modeles (dont SM2) + son ancetre "EICcontroller" conmait cette fenetre, et donc fait un "this.focus" (pas un create) param "data" = tous les modeles (dont SM2) +- "DOMContentFocused(data)" est lancé dans la view "SubmissionShortForm2023View", qui recoit SM2 via options.models +- MAIS "DOMContentFocused" se fout pas mal de options.models ====> ouille ! + This.submission reste donc l'instance SM1 pas fraiche ====> et bardaf, c'est l'embardée ! + + +- Biensur, Si on continue les allez-retour, il y a chaque fois une nouvelle instance de modèle, + mais les tabs continuent d'utiliser la toute première instance ===> aie-ouille-bardaf ! + + +===> Le fix: + +1. Patché d'abord en réassignant les modèles dans DOMContentFocused de "SubmissionShortForm2023View". (fastoche) + +!!! Oui mais, dans le cas des Tabs ca ne suffit pas, car les tabs ne sont pas réinstanciés nonplus. +De plus, leur "DOMContentFocused" n'est jamais appelé. + +2. Ajouté un appel à "DOMContentFocused" pour tous les chunks.view dans "SubmissionShortForm2023View::DOMContentFocused" pour propager le focus aux tabs + +3. Ensuite ajouté un "DOMContentFocused" dans la maman des tabs "SubmissionShortFormTabView" qui assigne this.model avec options.models.sumbission (options.models étant maintenant dispo) + +Du coup les vues & tabs ont la dernière instance du modèle, créée en réentrant dans le CTRL et donc les données fraiches. +...Reste a espérer qu'il ne traine plus de refs sur la vielle instance de modèle et qu'elle soit donc proprement garbage-collectée. + + +Attention, du coup sémentiquement : "DOMContentFocused" d'un tab veux dire "la fenêtre à laquelle le tab appartient est refocussée", +a ne pas confondre évidemment avec le focus du tab lui-même ( = event 'selected' du composant). + + +Makes me wonder : dommage qu'on réinstancie le modèle (en général, même fenêtre (avec mêm url dont params) = mêmes données, +le rafraichissement éventuel des données pourrais aussi bien se faire sans changer d'instance de modèle. +Mais lorsque EICcontroller teste pour voir si c'est une fenetre connue, il est déjà trop tard : +le ctrl-fiston a déjà instancié et choppé les datas, d'ailleurs c'est même obligatoirement synchrone avant de lancer la fenetre : via le THEN) +D'un autre côté, créer une association modèle-window (pour savoir si on l'a déjà plus tôt) n'est clairement pas un bon pattern... +... A méditer avec un malibu-ananas. + +Si on reste sur le patch ci-dessus, faut bien garder ca en tête paske ce pattern => bug potientiel va se retrouver ailleurs ! + + + +===> Side-effect & Fix on the fix : +Dans certains cas les focus sont appelés sans options (lorsqu'on clicke sur les badges fenêtre). +=> rajouté un test pour ne pas tenter de recopier les modèles si pas d'options. + Pas grave parceque ca correspond au cas ou on refocus la fenêtre sans rerouter, donc avec modèles non-réinstanciés. + Mais j'adore pas tout ca... faudrat qu'on en cause, voir si on peut clarifier/simplifier. diff --git a/app/assets/json/tests/platformDownRedisValue.js b/app/assets/json/tests/platformDownRedisValue.js new file mode 100644 index 0000000..8cf2d91 --- /dev/null +++ b/app/assets/json/tests/platformDownRedisValue.js @@ -0,0 +1,14 @@ +{ + "blockedUUIDs": [ + "n0005lka" + ], + "platformRestrictions": { + "allowedRoles": [ + "EIC_Admin", + "EIC_Dev" + ], + "allowedUUIDs": [ + "n0005i29" + ] + } +} \ No newline at end of file diff --git a/app/assets/json/tests/testlog-2023-23-06.txt b/app/assets/json/tests/testlog-2023-23-06.txt new file mode 100644 index 0000000..7bb792e --- /dev/null +++ b/app/assets/json/tests/testlog-2023-23-06.txt @@ -0,0 +1,18 @@ +# Test log from 2023-06-23 +# +# - means bug +# + means missing feature +# + means change request +# + +- /organisations/PIC/ => sends an array of organisations (ony 1 item though). there should be only 1 object +- /organisations/PIC/members => CORS error +- /organisations/PIC/proposals => CORS error +- logged under user fallimi => received ORG_MEMBER and SP_ADMIN roles but no permissions on /organisations (?!?) + ++ missing /users/search => same as /bypass/users/search (could be global) ++ missing /organisations/PIC/members/UID GET => retrieve details of a member (in order to update...) ++ missing "phone" property in organisation member => align to proposal fields + +* change "function" property in organisation member to "position" => align to proposal fields +* change "administrator" property in organisation member to "admin" => align to member profile diff --git a/app/assets/json/tests/tips-n-tricks.txt b/app/assets/json/tests/tips-n-tricks.txt new file mode 100644 index 0000000..e56d1c3 --- /dev/null +++ b/app/assets/json/tests/tips-n-tricks.txt @@ -0,0 +1,2 @@ +Converting SELECT OPTIONS to meta (json) from console: +Array.prototype.slice.call(document.querySelectorAll('[name="ref2selector"] option')).map(o => `{"id": "${o.value}", "label": "${o.innerHTML}"}`).join(",") \ No newline at end of file diff --git a/app/assets/json/workflows/wf-coaching-admin.json b/app/assets/json/workflows/wf-coaching-admin.json new file mode 100644 index 0000000..6ad51a7 --- /dev/null +++ b/app/assets/json/workflows/wf-coaching-admin.json @@ -0,0 +1,65 @@ +{ + "entities": [ + { + "title": "", + "subtitle": "Priorities", + "severity": "info", + "badge": 42, + "data": { + "id": "priorities" + } + }, + { + "title": "", + "subtitle": "Coach selection", + "severity": "primary", + "badge": 65, + "data": { + "id": "invitations" + } + }, + { + "title": "", + "subtitle": "Plan definition", + "badge": 2, + "severity": "primary", + "data": { + "id": "plans" + } + }, + { + "title": "", + "subtitle": "Timesheet", + "severity": "primary", + "badge": 27, + "data": { + "id": "timesheets" + } + }, + { + "title": "", + "subtitle": "Evaluation", + "severity": "primary", + "badge": 69, + "data": { + "id": "evaluations" + } + }, + { + "title": "", + "subtitle": "Closed", + "severity": "success", + "badge": 259, + "data": { + "id": "closed" + } + } + ], + "relations": [ + { "source": "priorities", "target": "invitations" }, + { "source": "invitations", "target": "plans" }, + { "source": "plans", "target": "timesheets" }, + { "source": "timesheets", "target": "evaluations" }, + { "source": "evaluations", "target": "closed" } + ] +} \ No newline at end of file diff --git a/app/assets/json/workflows/wf-coaching-applicant.json b/app/assets/json/workflows/wf-coaching-applicant.json new file mode 100644 index 0000000..ef017ad --- /dev/null +++ b/app/assets/json/workflows/wf-coaching-applicant.json @@ -0,0 +1,53 @@ +{ + "entities": [ + { + "title": "", + "subtitle": "Priorities", + "severity": "primary", + "data": { + "id": "priorities" + } + }, + { + "title": "", + "subtitle": "Coach selection", + "severity": "primary", + "data": { + "id": "invitations" + } + }, + { + "title": "", + "subtitle": "Coaching plan", + "badge": "!", + "severity": "accent", + "data": { + "id": "plan" + } + }, + { + "title": "", + "subtitle": "Timesheet", + "severity": "secondary", + "data": { + "id": "timesheet" + } + }, + { + "title": "", + "subtitle": "Evaluation", + "severity": "secondary", + "data": { + "id": "evaluation" + } + }, + { + "title": "", + "subtitle": "Closed", + "severity": "secondary", + "data": { + "id": "closed" + } + } + ] +} \ No newline at end of file diff --git a/app/assets/json/workflows/wf-mailings.json b/app/assets/json/workflows/wf-mailings.json new file mode 100644 index 0000000..444a9d6 --- /dev/null +++ b/app/assets/json/workflows/wf-mailings.json @@ -0,0 +1,66 @@ +{ + "entities": [ + { + "title": "", + "subtitle": "Creation", + "severity": "secondary", + "badge": null, + "data": { + "id": "start" + } + }, + { + "title": "", + "subtitle": "Content", + "severity": "secondary", + "badge": null, + "data": { + "id": "template" + } + }, + { + "title": "", + "subtitle": "Recipients", + "severity": "secondary", + "badge": null, + "data": { + "id": "recipients" + } + }, + { + "title": "", + "subtitle": "Data Mapping", + "severity": "secondary", + "badge": null, + "data": { + "id": "mappings" + } + }, + { + "title": "", + "subtitle": "Review", + "severity": "secondary", + "badge": null, + "data": { + "id": "approval" + } + }, + { + "title": "", + "subtitle": "Expedition", + "severity": "secondary", + "badge": null, + "data": { + "id": "schedule" + } + } + ], + "relations": [ + { "source": "start", "target": "template" }, + { "source": "start", "target": "recipients" }, + { "source": "template", "target": "mappings" }, + { "source": "recipients", "target": "mappings" }, + { "source": "mappings", "target": "approval" }, + { "source": "approval", "target": "schedule" } + ] + } \ No newline at end of file diff --git a/app/assets/json/workflows/wf-projects-funding.json b/app/assets/json/workflows/wf-projects-funding.json new file mode 100644 index 0000000..f32e4cd --- /dev/null +++ b/app/assets/json/workflows/wf-projects-funding.json @@ -0,0 +1,123 @@ +{ + "entities": [ + { + "title": "Evaluations", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "eval" + } + }, + { + "title": "Tech DDs", + "subtitle": "", + "severity": "primary", + "data": { + "id": "techdd" + }, + "child": { + "entities": [ + { + "title": "Draft", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "draft" + } + }, + { + "title": "Reopened", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "reopen" + } + }, + { + "title": "Integrity check", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "integrity" + } + }, + { + "title": "EIB Consultation", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "eib" + } + }, + { + "title": "Review", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "review" + } + }, + { + "title": "Approval", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "approval" + } + }, + { + "title": "Finalized", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "finalized" + } + } + + ], + "relations": [ + { "source": "draft", "target": "integrity" } + ] + } + }, + { + "title": "GAP", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "gap" + } + }, + { + "title": "KYC", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "kyc" + } + }, + { + "title": "Progress Meetings", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "meeting" + } + }, + { + "title": "Final", + "subtitle": "", + "severity": "secondary", + "data": { + "id": "final" + } + } + ], + "relations": [ + { "source": "eval", "target": "gap" }, + { "source": "eval", "target": "techdd" }, + { "source": "techdd", "target": "kyc" }, + { "source": "kyc", "target": "meeting" }, + { "source": "meeting", "target": "final" } + ] +} \ No newline at end of file diff --git a/app/assets/json/workflows/wf-templates.json b/app/assets/json/workflows/wf-templates.json new file mode 100644 index 0000000..3c3a554 --- /dev/null +++ b/app/assets/json/workflows/wf-templates.json @@ -0,0 +1,64 @@ +{ + "entities": [ + { + "title": "", + "subtitle": "Create", + "severity": "secondary", + "badge": null, + "data": { + "id": "start" + } + }, + { + "title": "", + "subtitle": "Clone", + "severity": "secondary", + "badge": null, + "data": { + "id": "start" + } + }, + { + "title": "", + "subtitle": "Edit", + "severity": "secondary", + "badge": null, + "data": { + "id": "edit" + } + }, + { + "title": "", + "subtitle": "Submit", + "severity": "secondary", + "badge": null, + "data": { + "id": "submit" + } + }, + { + "title": "", + "subtitle": "Approval", + "severity": "secondary", + "badge": null, + "data": { + "id": "approval" + } + }, + { + "title": "", + "subtitle": "Reject", + "severity": "secondary", + "badge": null, + "data": { + "id": "reject" + } + } + ], + "relations": [ + { "source": "start", "target": "edit" }, + { "source": "edit", "target": "submit" }, + { "source": "submit", "target": "reject" }, + { "source": "submit", "target": "approval" } + ] + } \ No newline at end of file diff --git a/app/assets/sfx/sampler/98.mp3 b/app/assets/sfx/sampler/98.mp3 new file mode 100755 index 0000000..667e29a Binary files /dev/null and b/app/assets/sfx/sampler/98.mp3 differ diff --git a/app/assets/sfx/sampler/balladur.mp3 b/app/assets/sfx/sampler/balladur.mp3 new file mode 100755 index 0000000..095c68e Binary files /dev/null and b/app/assets/sfx/sampler/balladur.mp3 differ diff --git a/app/assets/sfx/sampler/bourpif.mp3 b/app/assets/sfx/sampler/bourpif.mp3 new file mode 100644 index 0000000..b82542f Binary files /dev/null and b/app/assets/sfx/sampler/bourpif.mp3 differ diff --git a/app/assets/sfx/sampler/celebrate.mp3 b/app/assets/sfx/sampler/celebrate.mp3 new file mode 100755 index 0000000..2ad187c Binary files /dev/null and b/app/assets/sfx/sampler/celebrate.mp3 differ diff --git a/app/assets/sfx/sampler/fairplay.mp3 b/app/assets/sfx/sampler/fairplay.mp3 new file mode 100644 index 0000000..e49fa29 Binary files /dev/null and b/app/assets/sfx/sampler/fairplay.mp3 differ diff --git a/app/assets/sfx/sampler/gamin.mp3 b/app/assets/sfx/sampler/gamin.mp3 new file mode 100755 index 0000000..8e65e8f Binary files /dev/null and b/app/assets/sfx/sampler/gamin.mp3 differ diff --git a/app/assets/sfx/sampler/guingamp.mp3 b/app/assets/sfx/sampler/guingamp.mp3 new file mode 100755 index 0000000..534d9b8 Binary files /dev/null and b/app/assets/sfx/sampler/guingamp.mp3 differ diff --git a/app/assets/sfx/sampler/hassancehef.mp3 b/app/assets/sfx/sampler/hassancehef.mp3 new file mode 100644 index 0000000..8bf5747 Binary files /dev/null and b/app/assets/sfx/sampler/hassancehef.mp3 differ diff --git a/app/assets/sfx/sampler/jcvd.mp3 b/app/assets/sfx/sampler/jcvd.mp3 new file mode 100755 index 0000000..131f338 Binary files /dev/null and b/app/assets/sfx/sampler/jcvd.mp3 differ diff --git a/app/assets/sfx/sampler/judgenot.mp3 b/app/assets/sfx/sampler/judgenot.mp3 new file mode 100755 index 0000000..44f4c43 Binary files /dev/null and b/app/assets/sfx/sampler/judgenot.mp3 differ diff --git a/app/assets/sfx/sampler/manu.mp3 b/app/assets/sfx/sampler/manu.mp3 new file mode 100755 index 0000000..7565ed5 Binary files /dev/null and b/app/assets/sfx/sampler/manu.mp3 differ diff --git a/app/assets/sfx/sampler/metaphore.mp3 b/app/assets/sfx/sampler/metaphore.mp3 new file mode 100755 index 0000000..728c610 Binary files /dev/null and b/app/assets/sfx/sampler/metaphore.mp3 differ diff --git a/app/assets/sfx/sampler/neanderthal.mp3 b/app/assets/sfx/sampler/neanderthal.mp3 new file mode 100644 index 0000000..85fdf9a Binary files /dev/null and b/app/assets/sfx/sampler/neanderthal.mp3 differ diff --git a/app/assets/sfx/sampler/paillettes.mp3 b/app/assets/sfx/sampler/paillettes.mp3 new file mode 100755 index 0000000..1d7c1ce Binary files /dev/null and b/app/assets/sfx/sampler/paillettes.mp3 differ diff --git a/app/assets/sfx/sampler/phrases.mp3 b/app/assets/sfx/sampler/phrases.mp3 new file mode 100644 index 0000000..0637b4c Binary files /dev/null and b/app/assets/sfx/sampler/phrases.mp3 differ diff --git a/app/assets/sfx/sampler/projet.mp3 b/app/assets/sfx/sampler/projet.mp3 new file mode 100755 index 0000000..04aab14 Binary files /dev/null and b/app/assets/sfx/sampler/projet.mp3 differ diff --git a/app/assets/sfx/sampler/quenouilles.mp3 b/app/assets/sfx/sampler/quenouilles.mp3 new file mode 100755 index 0000000..2ae6f1a Binary files /dev/null and b/app/assets/sfx/sampler/quenouilles.mp3 differ diff --git a/app/assets/styles/app.css b/app/assets/styles/app.css new file mode 100755 index 0000000..5aef64b --- /dev/null +++ b/app/assets/styles/app.css @@ -0,0 +1,256 @@ +/* Default app color palette */ +:root,:after,:before { + --app-color-primary: var(--eicui-base-color-primary-100); + --app-color-secondary: var(--eicui-base-color-grey-100); + --app-color-success: var(--eicui-base-color-success-100); + --app-color-danger: var(--eicui-base-color-danger-100); + --app-color-warning: var(--eicui-base-color-warning-100); + --app-color-accent: var(--eicui-base-color-accent-100); + --app-color-info: var(--eicui-base-color-info-100); + --app-color-white: var(--eicui-base-color-white); + --app-color-black: var(--eicui-base-color-black); + --app-bg-color: var(--eicui-app-body-bg-color); + + --app-font-size-2xs: var(--eicui-base-icon-size-2xs); + --app-font-size-xs: var(--eicui-base-icon-size-xs); + --app-font-size-s: var(--eicui-base-icon-size-s); + --app-font-size-m: var(--eicui-base-icon-size-m); + --app-font-size-l: var(--eicui-base-icon-size-l); + --app-font-size-xl: var(--eicui-base-icon-size-xl); + --app-font-size-2xl: var(--eicui-base-icon-size-2xl); + --app-font-size-3xl: var(--eicui-base-icon-size-3xl); + --app-font-size-4xl: var(--eicui-base-icon-size-4xl); + + --app-header-height: var(--eicui-app-top-message-height); + + --app-menu-collapsed-width: 50px; + --app-menu-expanded-width: 240px; + + --app-menu-width: var(--app-menu-expanded-width); + +} + +body[eicapp] { + display: grid; + grid-template-rows: auto; + grid-template-columns: min-content auto; + min-height: 100vh; + box-sizing: border-box; +} + +[eicapp] [eicapptoolbar] { + display: flex; + position: fixed; + right: 0; + left: 0; + top: calc(var(--eicui-app-header-height) + var(--eicui-app-top-message-height)); + z-index: 10; + box-shadow: 0 0 20px #0000004d; +} + +[eicapp] footer { + position: fixed; + bottom: 0; +} +[eicapp] [eicmenu].app-menu { + height: calc(100vh - var(--eicui-app-toolbar-height-active)); + position: fixed; + top: var(--eicui-app-toolbar-height-active); + z-index: 2; +} +[eicapp] .app-workspace { + display: grid; + /* + flex-direction: column; + flex-grow: 1; + */ + min-height: 0; + padding: 0 0 0 0; + position: relative; + width: 100%; + margin-top: var(--eicui-app-toolbar-height-active); + box-sizing: border-box; + grid-column: 2; + grid-row: 1; + transition: all .2s; +} + +[eicapp] > [eicmenu] + .app-workspace, +[eicapp] > [eicmenu][collapsed]:hover + .app-workspace { + padding-left: var(--app-menu-expanded-width); +} +[eicapp] > [eicmenu][collapsed]:not(:hover) + .app-workspace{ + padding-left: var(--app-menu-collapsed-width); +} + +[eicapp] .app-workspace .window { + position: fixed; + padding: 3px; + background: var(--app-color-secondary); + box-shadow: 0 0 20px rgba(0, 0, 0, 0.35); + cursor: nwse-resize; + right: auto; + bottom: auto; + overflow: hidden; + z-index: 2; + display: grid; + grid-template-rows: min-content 1fr; + max-height: 90vh; + max-width: 90vw; +} +[eicapp] .app-workspace .window.active { + z-index: 3; + background: var(--app-color-primary); +} +[eicapp] .app-workspace .window > header { display: grid; } +[eicapp] .app-workspace .window > header h1 { + padding: var(--eicui-base-spacing-xs); + color: var(--app-color-white); + margin: 0; + font-size: large; + cursor: move; +} +[eicapp] .app-workspace .window > header .controls { + position: relative; + display: flex; + grid-auto-columns: auto; + white-space: nowrap; + align-items: center; + grid-gap: var(--eicui-base-spacing-xs); + margin-right: var(--eicui-base-spacing-s); +} +[eicapp] .app-workspace .window > header .controls button.expand { display: inline-flex; } +[eicapp] .app-workspace .window > header .controls button.shrink { display: none; } +[eicapp] .app-workspace .window > section { + padding: var(--eicui-base-spacing-xs) var(--eicui-base-spacing-s); + background: var(--app-bg-color); + cursor: default; + margin: 0; + overflow: auto; + transition: all 0.5s; +} +[eicapp] .app-workspace .window[device="tablet"] > section { + padding: 0; +} +[eicapp] .app-workspace .window[device="mobile"] > section { + padding: 0; +} +[eicapp] .app-workspace .window[expanded] { + box-shadow: none; + width: 100%; + max-width:none; + padding: 0 var(--eicui-base-spacing-2xs) var(--eicui-base-spacing-3xl) var(--eicui-base-spacing-2xs); + background-color: var(--app-bg-color); + cursor: default; + margin: 0; + overflow: visible; + position: relative; + height: auto; + box-sizing: border-box; + min-height: calc(100vh - var(--eicui-app-toolbar-height-active)); + overflow-y: auto; +} +[eicapp] .app-workspace .window[expanded] > header h1 { + display:none; +} +[eicapp] .app-workspace .window[expanded] > header .controls { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: var(--eicui-base-spacing-m) var(--eicui-base-spacing-xs) 0 0; +} +[eicapp] .app-workspace .window[expanded] > header .controls button { + background: var(--eicui-base-color-grey-20) !important; + padding: var(--eicui-base-spacing-m) var(--eicui-base-spacing-xs); + color: var(--app-color-secondary); +} +[eicapp] .app-workspace .window[expanded] > header .controls button.expand { + display: none; +} +[eicapp] .app-workspace .window[expanded] > header .controls button.shrink { + display: inline-flex; +} +[eicapp] .app-workspace .window[expanded] > section { + margin: 0; + padding: 0 0 var(--eicui-base-spacing-s) 0; + overflow: visible; + height: auto; +} + +[eicapp] .app-content-thesaurus { + position: fixed; + bottom: 0; + left: 0; + right: 0; + z-index: 4; + overflow: hidden; + padding: var(--eicui-base-spacing-m) var(--eicui-base-spacing-m) var(--eicui-base-spacing-s) var(--eicui-base-spacing-m); + text-align: center; + pointer-events: none; +} +[eicapp] .app-content-thesaurus [eicchip] { + box-shadow: 0px 0px 14px 0px #00000066; + cursor: pointer; +} +[eicapp] .app-content-thesaurus [eicchip] label { cursor: pointer; } + + +[eicapp] [eicdialog][device="tablet"] > [eiccard] { + max-height: 95vh; + max-width: 95vw; +} +[eicapp] [eicdialog][device="mobile"] > [eiccard] { + max-height: 100vh; + max-width: 100vw; + height: 100vh; + width: 100vw; +} + +[eicapp] [device="tablet"] article[eiccard] { + margin: 0; +} +[eicapp] [device="mobile"] article[eiccard] { + margin: 0; +} + +.eic-session { + padding: 0; + display: grid; + grid-template-columns: min-content; + grid-gap: 10px; +} +.eic-session button.status { + display: inline-grid; + justify-content: center; + align-content: center; + overflow: hidden; + font-size: 1.6rem; +} + +[device="tablet"] section .cols-2:not(.noflex), [device="mobile"] section .cols-2:not(.noflex) { + display: flex; + flex-direction: column; + grid-template-columns: none; + align-items: initial; +} +[device="tablet"] .cols-3, [device="mobile"] .cols-3, +[device="tablet"] .cols-4, [device="mobile"] .cols-4, +[device="tablet"] .cols-5, [device="mobile"] .cols-5, +[device="mobile"] .cols-6 { + display: flex; + flex-direction: column; + grid-template-columns: none; +} + +[device="tablet"] .cols-6 { + grid-template-columns: 1fr 1fr 1fr; +} + +[device="tablet"] .cols-8 { + grid-template-columns: 1fr 1fr 1fr 1fr; +} + +[device="mobile"] .cols-8 { + grid-template-columns: 1fr 1fr; +} diff --git a/app/assets/styles/common/massmail.css b/app/assets/styles/common/massmail.css new file mode 100644 index 0000000..06f43f5 --- /dev/null +++ b/app/assets/styles/common/massmail.css @@ -0,0 +1,219 @@ + +/********************************************************************** + +.massmailer [hidden]{ + display:none; +} +.massmailer .massmail-send{ + justify-self: center; +} +.massmailer .panes{ + grid-template-columns: 2fr 3fr; +} + +.massmailer article header h1{ + color: var(--eicui-base-color-primary); +} +.massmailer article header h1.mailing-name{ + text-align: center; +} +.massmailer article header .template-name, +.massmailer article header h1.mailing-name span{ + color: var(--eicui-body-color); +} + +.massmailer .workflow[loading="true"]::before{ + content: "\e981"; + animation: spin 1s infinite linear; + font-family: 'glyphs'; + position: absolute; + font-size: inherit; + width: min-content; + color: var(--app-color-info); + left: var(--eicui-base-spacing-xs); + top: var(--eicui-base-spacing-xs); + background: transparent; + z-index: 2; +} +.massmailer .workflow[loading="true"]::after{ + content: "updating..."; + position: absolute; + font-size: inherit; + width: min-content; + padding: 0 var(--eicui-base-spacing-s); + color: var(--app-color-info); + top: 0; + padding: var(--eicui-base-spacing-xs) var(--eicui-base-spacing-xs) var(--eicui-base-spacing-xs) var(--eicui-base-spacing-xl); + background: transparent; + left: 0; +} +.massmailer .workflow text.title{ + font-size: var(--eicui-base-font-size-xs); +} +.massmailer .workflow text.subtitle{ + font-size: calc(var(--eicui-base-font-size-xs)/1.2); + font-style: italic; +} +.massmailer .workflow .badge{ + opacity: .85; +} +.massmailer .templates-grid{ + height: fit-content; + min-height: 8em; +} +.massmailer span.token[eicchip]{ + font-size: 0.75rem; +} +.massmailer .templates-grid li.row{ + grid-template-columns: 15em 10em 4em 8em; +} + +.massmailer .templates-grid .cell i.ffs{ margin-right: .5em; } +.massmailer .templates-grid .cell i.ffs.icon-folder{ + color: var(--eicui-base-color-warning); +} + +.massmailer .tpl-panes{ + grid-template-columns: 32em 2fr; +} +.massmailer .tpl-text-body{ + max-width: 50vw; +} +.massmailer .tpl-text-body pre{ + text-wrap: wrap; + font-family: var(--eicui-base-font-family); +} +.massmailer .mapping-grid ul{ + list-style: none; +} +.massmailer .mapping-grid ul li .cols-3{ + grid-template-columns: 1fr 1fr 10em; +} + +.massmailer .mapping-grid ul li [eicchip]{ + max-width: fit-content; + height: 2em; +} + +.massmailer button.test-send{ + justify-self: right; +} +.massmailer .approval-panel button.reject, +.massmailer .approval-panel button.approve, +.massmailer .schedule-tab button.schedule { + width: 20rem; +} +.massmailer .schedule-tab footer{ + justify-content: center; +} +.massmailer .approval-panel .buttons { + justify-items: center; +} +.massmailer .schedule-panel [name="scheduleDate"], +.massmailer .schedule-panel .eicui-input-container { + width:10rem; +} + + +.import-dialog .toggle-switch.greyed .toggle-bar, +.import-dialog .toggle-switch.greyed .toggle-thumb{ + background-color: var(--eicui-base-color-grey-25)!important; +} +.import-dialog .hidden{ + display: none; +} +.import-dialog .settings div{ + text-align: center; +} +.import-dialog .report-title{ + color: var(--eicui-base-color-success); + font-style: italic; + grid-row: 1/3; +} +.import-dialog .report-details ul{ + margin: 0 0 0 1em; + list-style: disclosure-closed; +} +.import-dialog .report-details ul span[success]{ + font-weight: bold; +} +.import-dialog .report.error{ + color: var(--eicui-base-color-danger); +} +.import-dialog [eiccard][hidden]{ + display: none; +} +.import-dialog span[spinner][spin]{ + width: fit-content; +} +.import-dialog .switches{ + align-items: center; +} +.import-dialog .toggle-switch.greyed .toggle-bar{ + background-color: var(--eicui-base-color-grey-25)!important; +} +.import-dialog .toggle-switch.greyed .toggle-thumb{ + background-color: var(--eicui-base-color-grey-75)!important; +} +.import-dialog .toggle-switch[disabled]{ + opacity:0.5; +} + + +.mapping-dialog .toggle-switch.greyed .toggle-bar, +.mapping-dialog .toggle-switch.greyed .toggle-thumb{ + background-color: var(--eicui-base-color-grey-25)!important; +} +.mapping-dialog .hidden{ + display: none; +} +.mapping-dialog .settings div{ + text-align: center; +} +.mapping-dialog .report-title{ + color: var(--eicui-base-color-success); + font-style: italic; + grid-row: 1/3; +} +.mapping-dialog .report-details ul{ + margin: 0 0 0 1em; + list-style: disclosure-closed; +} +.mapping-dialog .report-details ul span[success]{ + font-weight: bold; +} +.mapping-dialog .report.error{ + color: var(--eicui-base-color-danger); +} +.mapping-dialog [eiccard][hidden]{ + display: none; +} +.mapping-dialog .sample-grid{ + font-size: var(--eicui-base-font-size-s); +} +.mapping-dialog .sample-grid li.row{ + grid-template-columns: auto 3em; +} + + + +.test-dialog .toggle-switch.greyed .toggle-bar, +.test-dialog .toggle-switch.greyed .toggle-thumb{ + background-color: var(--eicui-base-color-grey-25)!important; +} +.test-dialog .hidden{ + display: none; +} +.test-dialog input.token-value{ + padding: initial; +} +.test-dialog .tokens-form{ + padding: 0 .5em .5em .5em; +} +.test-dialog .tokens-form li{ + margin-bottom: 0.2em; +} + + + +*/ \ No newline at end of file diff --git a/app/assets/styles/common/templitor.css b/app/assets/styles/common/templitor.css new file mode 100644 index 0000000..2effe45 --- /dev/null +++ b/app/assets/styles/common/templitor.css @@ -0,0 +1,386 @@ +.templitor > header, +.templitorManage > header { + background: url('/app/assets/images/cards/templitorHeader.png') center/cover no-repeat; + border-bottom: 4px solid white !important; +} + +.templates-tab, .cols-2 { + display: flex; +} + +.templitor .templates { + width: 60vw; +} + +.create-new-tpl { + float: right; + top: -2em; +} + +.tplViewer { + flex: 1; + position: relative; + width: 20vw; + max-width: 20vw; + max-width: 30%; + max-height: 61vh; + background-color: white; + border: 1px solid #ccc; + padding: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + z-index: 1000; + display: none; +} + +.tplViewer .tpl-html { + max-width: 22vw; +} + +.tplViewer .img { + max-width: 100%; + height: auto; +} + +.tpl-html { + border: 1px solid #ccc; + padding: 10px; + border-radius: 5px; + position: inherit; + overflow: auto; +} + +.tpl-html img { + max-width: 100%; + height: auto; +} + +.tpl-html table { + table-layout: auto; +} + +.tpl-html p, +.tpl-html span.token, +.tpl-html footer span, +.tpl-html table { + font-size: 0.8em; +} + +.templatesList[templatesList] { + max-height: calc(95vh - 40vh); + overflow-y: auto; + display: grid; + grid-template-columns: repeat(6, 1fr); +} + +.templatesList .grid-header, +.templatesList .grid-row { + display: grid; + grid-template-columns: repeat(6, 1fr); + padding: 10px; + border-bottom: 1px solid #ddd; +} + +.templatesList .grid-header { + background-color: #f5f5f5; + font-weight: bold; +} +.tplMeta, +.tplTools{ + border: unset!important; + box-shadow: none!important; +} +.tpl-editor, +.tpl-editor-container{ + background-color: #a0a0a0; +} +.template-item { + background: #f9f9f9; + border: 2px solid var(--eicui-app-body-bg-color) !important; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + font-size: 0.75em; + position: relative; + margin: 0.4em !important; +} + +.template-item h1, .template-item h2, .template-item h3 { + font-size: 1.5em; + margin: 0.5em; +} + +.template-item p { + font-size: 1.2em; + margin: 0.5em; + line-height: 0; +} + +.template-item:hover { + transform: scale(1.02); + background-color: #FFFAE9 !important; +} + +.templatesList .template-item.selected { + background-color: #FFFAE9 !important; + font-weight: 600; + font-style: italic; +} + +.tplEditor { + margin-top: 20px; + border: 1px solid #a0a0a0; + padding: 10px; +} + +.tplEditor textarea { + display: block !important; + width: 100%; + height: 100px; + font-size: 14px; +} + +.tplEditor h6 { + margin: 0!important; + padding:0; +} + +.save-html, .tool-button { + display: inline-block; + margin-top: 10px; + padding: 10px; + border: 1px solid #ccc; + cursor: grab; +} + +.templateEditor { + min-width: 30em; +} + +.tplViewer section > header, +.tplPreview section > header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.tplViewer section > header h1, +.tplPreview section > header h1 { + margin: 0; +} + +.tplViewer section > header button, +.tplPreview section > header button { + margin-left: 10px; + padding: 5px !important; +} + +.tpl-header-editor, .tpl-main-editor, .tpl-footer-editor, .tpl-alternateText-editor { + border: 1px solid #a0a0a0; + padding: 10px; + position: relative; + margin-bottom: 10px; + min-height: 5em; +} + +.tpl-header-editor::before, .tpl-main-editor::before, .tpl-footer-editor::before { + content: attr(data-label); + position: absolute; + top: -10px; + left: 10px; + background: white; + padding: 0 5px; + font-weight: bold; +} + +.tpl-html > footer { + position: inherit; +} + +.paragraph-placeholder { + border: 1px dashed #ccc; + padding: 5px; + margin: 5px 0; +} + +.line-break { + display: block; + margin: 10px 0; + border-top: 1px solid #ccc; +} + +#colorWell { + position: absolute; + display: none; + background: white; + padding: 5px; + border: 1px solid #ccc; + z-index: 1000; +} + +.radioB { + display: flex; + align-items: center; + gap: 10px; +} +.tpl-em{ + font-size: small; +} + +.tplName { + flex-grow: 0.7; + min-width: 50%; + margin-bottom: 0; +} + +.tplSubject input, +.tplName input{ + width: 60ch; +} + +input[type="radio"] { + margin-right: 5px; +} + +.tpl-alternateText-editor { + user-select: none; +} + +.tpl-toolButtons { + position: sticky; + top: 0; + background-color: white; + z-index: 1000; +} + +.tpl-sendMailTest { + margin-left: auto !important; +} + +.resizable { + display: inline-block; + position: relative; + border: 1px solid transparent; +} + +.resizable img { + max-width: 100%; + height: auto; +} + +.resize-handle { + width: 10px; + height: 10px; + background-color: #fff; + position: absolute; + bottom: 0; + right: 0; + cursor: se-resize; +} + +.resize-handle::after { + content: "↔"; + font-size: 16px; +} + +@media (max-width: 768px) { + .templatesList[templatesList] { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 480px) { + .templatesList[templatesList] { + grid-template-columns: 1fr; + } +} +/* Styles for lists */ +.tpl-bullet-list, +.tpl-dash-list, +.tpl-numbered-list { + margin-left: 20px!important; +} +/* Styles for bullet lists */ +.tpl-bullet-list { + list-style-type: disc; +} +/* Styles for dashed lists */ +.tpl-dash-list { + list-style-type: none; +} + +.tpl-dash-list li::before { + content: "-"; /* Add a dash before each list item */ + margin-right: 10px; +} + +/* Styles for numbered lists */ +.tpl-numbered-list { + list-style-type: decimal; /* Default numbered list */ +} + +/* Optional: Customize the appearance of list items */ +.tpl-bullet-list li, +.tpl-dash-list li, +.tpl-numbered-list li { + padding: 5px 0; +} + +/*Add Table */ +.tpl-table { + width: 100%; + border-collapse: collapse; + resize: both; + overflow: hidden; +} + +.tpl-table-bordered { + border: 1px solid #ccc; +} + +.tpl-table th, .tpl-table td { + border: 1px solid #ccc; + padding: 10px; + text-align: left; +} + +.tpl-table-bordered th, .tpl-table-bordered td { + border: 1px solid #ccc; +} + +.tpl-table th { + background-color: #f2f2f2; +} + +.tpl-table-bordered { + border: 1px solid #ccc; +} + +.tpl-table th { + background-color: #f4f4f4; +} + +.tpl-table td, .tpl-table th { + resize: both; +} + +/*HTMLPreview */ +.he-img-select-container { + display: none; + position: fixed; + z-index: 1000; + background-color: white; + border: 1px solid #ccc; + padding: 10px; +} + +.tplViewer.not-editable::after { + content: 'Not Editable'; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) rotate(-45deg); + font-size: 5rem; + color: rgba(200, 0, 0, 0.1); /* Transparent red */ + z-index: 10; + pointer-events: none; + white-space: nowrap; +} diff --git a/app/assets/styles/projects/bypass.css b/app/assets/styles/projects/bypass.css new file mode 100755 index 0000000..819a50f --- /dev/null +++ b/app/assets/styles/projects/bypass.css @@ -0,0 +1,99 @@ +[device="tablet"] [eicdatagrid] .cell { padding: var(--eicui-base-spacing-xs) 0; } +[device="mobile"] [eicdatagrid] .cell { padding: var(--eicui-base-spacing-xs) 0; } + +/* +.fasttracks > header { background: url('/app/assets/images/cards/fasttracks-card.jpg'); } +*/ +.fasttracks .granted-tokens, +.fasttracks .global-granted-tokens { + margin-top: var(--eicui-base-spacing-m); +} +.fasttracks .granted-tokens .row { grid-template-columns: 120px 2fr 1fr 1fr 1fr 120px 2fr 150px; } +[device="tablet"] .fasttracks .granted-tokens .row { grid-template-columns: 120px 0fr 0fr 1fr 1fr 1fr 0fr 50px; } +[device="mobile"] .fasttracks .granted-tokens .row { grid-template-columns: 120px 0fr 0fr 0fr 1fr 0fr 0fr 40px; } +.fasttracks .granted-tokens .row .cell:nth-child(2) { text-align: center; } +.fasttracks .granted-tokens .row .cell:nth-child(4) { text-align: center; } +.fasttracks .granted-tokens .row .cell:nth-child(6) { text-align: center; } + +.fasttracks .global-granted-tokens .row { grid-template-columns: 120px 2fr 1fr 1fr 1fr 1fr 2fr 1fr 150px; } +.fasttracks .global-granted-tokens .row, .fasttracks .granted-tokens .row { min-height: 48px; } +[device="tablet"] .fasttracks .global-granted-tokens .row { grid-template-columns: 120px 0fr 0fr 1fr 1fr 1fr 0fr 0fr 90px; } +[device="mobile"] .fasttracks .global-granted-tokens .row { grid-template-columns: 120px 0fr 0fr 0fr 1fr 0fr 0fr 0fr 90px; } +.fasttracks .global-granted-tokens .row .cell:nth-child(2) { text-align: center; } +.fasttracks .global-granted-tokens .row .cell:nth-child(5) { text-align: center; } +.fasttracks .global-granted-tokens .row .cell:nth-child(6) { text-align: center; } +.fasttracks .global-granted-tokens .row .cell:nth-child(7) { text-align: center; } +.fasttracks .global-granted-tokens .row .cell:nth-child(9) { text-align: center; } + +.fasttracks .history-tokens .row { grid-template-columns: 200px 120px 2fr 120px 1fr; } +[device="mobile"] .fasttracks .history-tokens .row { grid-template-columns: 1fr 1fr 0fr 1fr 0fr; } +.fasttracks .history-tokens .row .cell:nth-child(2) { text-align: center; } +.fasttracks .history-tokens .row .cell:nth-child(3) { text-align: center; } +.fasttracks .history-tokens .row .cell:nth-child(5) { text-align: center; } + +.fasttracks .users-list .row { grid-template-columns: 1fr 2fr 3fr 2fr 2fr 2fr 90px; } + +.fasttracks .programmes-list .row { grid-template-columns: 1fr 120px; } + +.tabs-extended section { + padding: 0 !important; + display: flex; + align-items: center; +} +.fasttracks .metrics { + display: flex; + flex-direction: row; + justify-content: center; + text-align: center; +} +.fasttracks .metrics > div { + display: inline-flex; + justify-content: center; + flex-direction: column; + border: 1px solid var(--eicui-base-color-grey-15); + margin: 0 var(--eicui-base-spacing-s) 0 var(--eicui-base-spacing-s); + flex: 1; +} +[device="tablet"] .fasttracks .metrics > div { + border: none; + display: grid; + align-items: baseline; + grid-template-rows: min-content 1fr; +} +[device="mobile"] .fasttracks .metrics > div { display: none; } +.fasttracks .metrics > div > span { + font-size: x-large; + font-weight: bold; + padding: var(--eicui-base-spacing-2xs) 0 0 0; +} +.fasttracks .metrics > div label { + font-size: smaller; + text-transform: uppercase; + font-weight: bold; +} +[eicdialog] .fasttracks { + min-width: 40vw; +} +[eicdialog] .fasttracks section { + padding: 0; + overflow: visible; +} +.fasttracks .kic-domains-list .row, +.fasttracks .plugin-domains-list .row, +[eicdialog] .fasttracks.settings [eicdatagrid] .row { + grid-template-columns: auto 100px 100px; +} +.fasttracks .kic-domains-list .dataset .row .cell:nth-child(3), +.fasttracks .plugin-domains-list .dataset .row .cell:nth-child(3), +[eicdialog] .fasttracks.settings [eicdatagrid] .dataset .row .cell:nth-child(3) { + text-align: right; +} +.fasttracks .kic-domains-list .dataset .row .cell:nth-child(4), +.fasttracks .plugin-domains-list .dataset .row .cell:nth-child(4), +[eicdialog] .fasttracks.settings [eicdatagrid] .dataset .row .cell:nth-child(4) { + text-align: right; +} +.cell.actions span { + color: var(--eicui-base-color-grey-50); + font-size: var(--eicui-base-font-size-s); +} \ No newline at end of file diff --git a/app/assets/styles/projects/submissions.css b/app/assets/styles/projects/submissions.css new file mode 100644 index 0000000..18b9cb8 --- /dev/null +++ b/app/assets/styles/projects/submissions.css @@ -0,0 +1,91 @@ +[device="tablet"] [eicdatagrid] .cell { padding: var(--eicui-base-spacing-xs) 0; } +[device="mobile"] [eicdatagrid] .cell { padding: var(--eicui-base-spacing-xs) 0; } + +.tabs-extended section { + padding: 0 !important; + display: flex; + align-items: center; +} +.shortsubmission .tabs-extended li i[class^="icon-"]{ + padding-right: 10pt; +} +.shortsubmission .tabs-extended li{ + box-shadow: none; + background-color: #A2CBA2; +} +.shortsubmission .tabs-extended li div{ + z-index:10 +} +.shortsubmission .tabs-extended li.tab-selected { + background-color: #71D071; + border-bottom: none; +} +.shortsubmission .tabs-extended li .tab-arrow{ + transform: rotate(-45deg); + border: solid white; + border-width: medium; + border-width: 0 3px 3px 0; + display: inline-block; + padding: 14pt; + position: absolute; + right: -9pt; + border-radius: 3px; + z-index: 9; + background-color: inherit; +} + +.shortsubmission .metrics { + display: flex; + flex-direction: row; + justify-content: center; + text-align: center; +} +.shortsubmission .metrics > div { + display: inline-flex; + justify-content: center; + flex-direction: column; + border: 1px solid var(--eicui-base-color-grey-15); + margin: 0 var(--eicui-base-spacing-s) 0 var(--eicui-base-spacing-s); + flex: 1; + max-width: 14vw; +} +[device="tablet"] .shortsubmission .metrics > div { + border: none; + display: grid; + align-items: baseline; + grid-template-rows: min-content 1fr; +} +[device="mobile"] .shortsubmission .metrics > div { display: none; } +.shortsubmission .metrics > div > span { + font-size: x-large; + font-weight: bold; + padding: var(--eicui-base-spacing-2xs) 0 0 0; +} +.shortsubmission .metrics > div label { + font-size: smaller; + text-transform: uppercase; + font-weight: bold; +} +[eicdialog] .shortsubmission { + min-width: 40vw; +} +[eicdialog] .shortsubmission section { + padding: 0; + overflow: visible; +} +.documents .videoStage{ + background: url('/app/assets/images/videobg.png'); + background-position: center; + background-repeat: no-repeat; + text-align: center; + min-height: 525px; +} + +.documents video.EmbedVideo { + margin: 15px auto 25px auto; +} + +.submission.short-form .EmbedSubmissionDocument { + width: 100%; + height: 70vh; +} \ No newline at end of file diff --git a/app/config/baseRoutes.json b/app/config/baseRoutes.json new file mode 100755 index 0000000..7765313 --- /dev/null +++ b/app/config/baseRoutes.json @@ -0,0 +1,162 @@ +[ + { + "url": "!defaultroute", + "role": "*", + "controller" : "/common/errorController", + "method": "_404" + }, + { + "url": "/401", + "role": "*", + "controller" : "/common/errorController", + "method": "_401" + }, + { + "url": "/", + "role": [ "PROJECT_PO", "PROJECT_FIO", "PROJECT_TechDDExpert" ], + "exturl": "/icmp" + }, + { + "url": "/", + "role": "Org_Member", + "exturl": "/applicant" + }, + { + "url": "/", + "role": ["SOE_Admin", "SOE_National" ], + "exturl": "/soe" + }, + { + "url": "/", + "role": "*", + "exturl": "/onboarding" + }, + { + "url": "/onboarding", + "role": "*", + "controller": "/common/onboardingController" + }, + { + "url": "/", + "role": [ "EIC_Admin", "BP_PO", "BP_HoU" ], + "exturl": "/bypass" + }, + { + "url": "/", + "role": [ "BP_SPOC_Plugin" ], + "exturl": "/bypass/plugins" + }, + { + "url": "/", + "role": [ "BP_SPOC_FastTrack" ], + "exturl": "/bypass/fast-tracks" + }, + { + "url": "/common/myprofile", + "role": "*", + "controller" : "common/myProfileController", + "method": "index" + }, + { + "url": "/about", + "role": "*", + "controller" : "common/aboutController" + }, + { + "url": "/bypass", + "role": "*", + "controller" : "/projects/bypass/BypassController" + }, + { + "url": "/system", + "role": "*", + "controller" : "/system/systemController" + }, + { + "url": "/applicant", + "role": "*", + "controller": "/applicants/ApplicantController" + }, + { + "url": "/organisations/:pic/proposals", + "role": "Org_Member", + "controller": "/projects/submissions/SubmissionsController" + }, + { + "url": "/coachings/admin", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller": "/coachings/CoachingAdminController", + "method": "dashboard" + }, + { + "url": "/coachings/coach", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller": "/coachings/CoachingCoachController", + "method": "dashboard" + }, + { + "url": "/coachings/coaches/:id", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller": "/coachings/CoachingAdminController", + "method": "profile" + }, + { + "url": "/coachings/coaching/:id", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller": "/coachings/CoachingApplicantController", + "method": "view" + }, + { + "url": "/lab/components", + "role": "EIC_Dev", + "controller" : "/system/systemController", + "method": "components" + }, + { + "url": "/soe", + "role": [ "EIC_Dev", "EIC_Admin", "SOE_National", "SOE_Admin" ], + "controller" : "/projects/soe/SoeController", + "method": "dashboard" + }, + { + "url": "/soe/companies/:pic/projects/:number/fundings", + "role": [ "EIC_Dev", "EIC_Admin", "SOE_National", "SOE_Admin" ], + "controller" : "/projects/soe/SoeController", + "method": "feedbacks" + }, + { + "url": "/mailings", + "role": [ "MAIL_Editor", "MAIL_Reviewer", "MAIL_Sender", "EIC_Dev", "EIC_Admin" ], + "controller" : "/comms/mailings/MailingsController" + }, + { + "url": "/icmp", + "role": [ "PROJECT_PO", "PROJECT_FIO", "PROJECT_TechDDExpert" ], + "controller" : "/projects/icmp/ICMPController", + "method": "Dashboard" + }, + { + "url": "/icmp/projects/:number", + "role": [ "PROJECT_PO", "PROJECT_FIO", "PROJECT_TechDDExpert" ], + "controller" : "/projects/icmp/ICMPController", + "method": "project" + }, + { + "url": "/icmp/projects/:number/:node/:nodeId", + "role": [ "PROJECT_PO", "PROJECT_TechDDExpert", "PROJECT_FIO" ], + "controller" : "/projects/icmp/ICMPController", + "method": "project" + }, + { + "url": "/templates", + "role": ["TEMPLATE_Editor", "TEMPLATE_Reviewer", "EIC_Dev", "EIC_Admin"], + "controller" : "comms/templates/TemplatesController", + "method": "search" + }, + { + "url": "/templates/:id", + "role": ["TEMPLATE_Editor", "TEMPLATE_Reviewer", "EIC_Dev", "EIC_Admin"], + "controller" : "comms/templates/TemplatesController", + "method": "tplAction" + } +] \ No newline at end of file diff --git a/app/config/config.README b/app/config/config.README new file mode 100644 index 0000000..24b64f3 --- /dev/null +++ b/app/config/config.README @@ -0,0 +1,83 @@ + +"assets": Config of the assets manager + + "basePath": Where all assets are (normally /app/assets/) expected to have sub-folders "html", "images", "json", "sfx', "styles" + + +"router": Config of the router (not the routes) + + "getRolesFrom": How to get the roles, can be an array of string or string representing a function + (normally app.User.getRoles : will thus use getRoles method of the user class) + + "controllersPath": Where all controllers are (normally /app/controllers/) + "modelsPath": Where all models are (normally /app/models/) + "viewsPath": Where all views are (normally /app/views/) + + "libsBaseClasses": Array of application libraries to preload + "path": path below /app/libs, + "classes": Array of classes (= scripts names) to load, + "dependencies" : Object where + KEY is the class name that depends on something + VALUE is an Array of dependencies classes (= scripts names) (to load before the KEY class can be loaded) + + "masterController": class name of the master controller that shall instanciated before any other controller (don't forget to preload it in the libs or elsewhere), + "defaultMasterTemplate": The default view name used by the mastercontroller (the view that fills the page's body) + + +"logger": Config of the logging system + "enabled": Well... + "levels": Array with possible values "err","warn": messages of levels present here are posted to postUrl + "latestErrsMax": Number of log entries to keep in app.latestErrors (use in support page) + "postUrl": Where to post the json of a logger entry + + +"userLib": Config of the user library (core or custom) + "className": If present, will be used to overwrite the vanilla-core User class by convention : "myUser", in libs, + + Options below depend on the custom user class, here's for EIC : + + "authEndpoint": API url to check if authenticated and get the auth redirect URL if not, + "logoutEndpoint": API url to logout, + "apiDiscoveryEndpoint": API url for services discovery + "resourcePermissionsEndpoint": API url for permissions discovery + "apiStage": Stage name or '*', used to filter API services discovered + "apiStageExceptions": Object where + KEY is business entity name (like in permissions) + VALUE is an object where + KEY is the action name on the business entity (like in permissions) + VALUE is an object where + "method" : http method to use + "uri": the uri to call + + "authForwardDomain": if true sets the header "x-requested-path" to the url path, when authenticating (used for original url preservation across EUlogin) + + +"messageBus": Config of the message bus library + "enabled": well... + "pathToWorker": path to the websocket worker script ("/core/libs/MessageBusWorker.js" unless custom), + "protocol": (should really be "wss://" as "ws://" is insecure and would come with all sorts of browser limitations) + "port": ("" to use same as for web which is recommanded to avoid browser & firewall limitations) + "path": path part of the websocket URL where you'll be http-upgraded ("/api/msgbus") + "connectTimeout": well... (in seconds) + "autoReconnect": wait that many seconds before attempting a FIRST reconnect on disconnection. Carefull not to overload the server ! (5 is cool) + "autoReconnectTimeFactor": on every new attempt, multiply the previous delay by this factor (float), so retrials are more and more time-spaced (1.3 is cool) + "autoReconnectTimeMax": max reconnect delay not to go over when autoReconnectTimeFactor is >1 (30 is cool) + "autoReconnectJitterPercent": percentage of randomness applied on reconnection times. + Important so that after a server-down, not everyone retries precisely at the same time + (10 is cool) + +"squeeze": Config of the squeezer (read by the squeezer during deploy, and by sparc) + + "indexDefaults" : What to put in the index page whan no scripts are "setIndexPage" or no styles are "setIndexPage" + "scripts" : Array of script paths (from url root) that will end-up as script tags ([ "/core/Sparc-core-1.0.js" ]) + "styles" : Array of css paths (from url root) that will end-up as link tags (["/app/thirdparty/eicui/eicui-2.0.css"]) + + "packages" : Array of packages objects (also called "dragées") where + "target": the name of the concatenated script to create, that willend-up in /squeezed + "sources": Array of scripts (url paths) to concatenate + "compressed": will produce a ".js.gz" if true. Do not use in AWS as cloudfront does compression on the fly, + and doesn't know how to properly send a gzip (missing content-encoding header) + "minify": minify if true (using uglify-js) + "mangle": mangle if true (using uglify-js), + "setIndexPage": If true, adds a script tag in the index.html page pointing to this target + diff --git a/app/config/config.json b/app/config/config.json new file mode 100644 index 0000000..0d5af90 --- /dev/null +++ b/app/config/config.json @@ -0,0 +1,113 @@ +{ + "assets": { + "basePath": "/app/assets/" + }, + "router": { + "getRolesFrom": "app.User.getRoles", + "controllersPath": "/app/controllers/", + "modelsPath": "/app/models/", + "viewsPath": "/app/views/", + "libsBaseClasses":[ + { + "path": "/EIC", + "classes": [ "EICController", "EICDomContent", "EICDialogContent", "EICMetaData", "EICModel", "EICPluralModel", "EICBusModel" ], + "dependencies" : { "EICPluralModel": [ "EICModel" ] } + }, + { "onlyIfClasses": [ "MessageBus" ], + "path": "/Bus/rendezVous", + "classes": [ "MBRendezVous" ], + "dependencies" : { } + } + ], + "masterController": "EICAppController", + "defaultMasterTemplate": "templates/EICAppTemplate" + }, + "logger": { + "enabled": true, + "levels": ["err","warn"], + "latestErrsMax": 20, + "postUrl": "xxxhttps://api.dev.eismea.eu/logger" + }, + "userLib": { + "className": "myUser", + "authEndpoint": "https://api.dev.eismea.eu/stable/authorizer/checkAuthenticated", + "logoutEndpoint": "https://api.dev.eismea.eu/stable/authorizer/logout", + "apiDiscoveryEndpoint": "https://api.dev.eismea.eu/stable/apis/services", + "resourcePermissionsEndpoint": "https://api.dev.eismea.eu/stable/permissions", + "apiStage": "stable", + "apiStageExceptions": { + }, + "authForwardDomain": true, + "keepAliveSeconds": 0 + }, + "matomo4sparc": { + "enabled": true, + "trackUrl": "https://analytics.test.eismea.eu/matomo.php", + "idsite":7 + }, + "messageBus":{ + "enabled": true, + "debug": true, + "tokenUrl": "https://api.dev.eismea.eu/stable/msgBusToken", + "pathToWorker": "/core/libs/MessageBusWorker.js", + "protocol": "wss://", + "host": "bus.dev.eismea.eu", + "port": "", + "XdevotpToken": "qhsdfkjhqsgdfkqhs", + "Xhost": "eismea.internike.com", + "Xport": "4443", + "path": "/msgbus", + "connectTimeout": 5, + "autoReconnect": 5, + "autoReconnectTimeFactor": 1.3, + "autoReconnectTimeMax": 30, + "autoReconnectJitterPercent": 10, + "frontBusPrefix": "", + "userNotifChan": "system:notifs:{uid}", + "rendezVousChan": "rendezVous:{uid}", + "ptpChanPrefix": "peer2peer:" + }, + "squeeze": { + "indexDefaults" : { + "scripts" : [ "/core/Sparc-core-1.0.js" ], + "styles" : ["/app/thirdparty/eicui/eicui-2.0.css"] + }, + "packages" : [ + { + "target": "core.js", + "sources": [ "/core/Sparc-core-1.0.js", + "/core/libs/Assets.js", + "/core/libs/Events.js", + "/core/libs/Logger.js", + "/core/libs/MessageBus.js", + "/core/libs/Router.js", + "/core/baseClasses/Controller.js", + "/core/baseClasses/MasterController.js", + "/core/baseClasses/Model.js", + "/core/baseClasses/View.js", + "/core/baseClasses/User.js", + "/app/libs/myUser.js" + ], + "compressed": false, + "minify": true, + "mangle": false, + "setIndexPage": true + }, + { + "target": "eiclibs.js", + "sources": [ + "/app/libs/EIC/EICController.js", + "/app/libs/EIC/EICDialogContent.js", + "/app/libs/EIC/EICDomContent.js", + "/app/libs/EIC/EICMetaData.js", + "/app/libs/EIC/EICModel.js", + "/app/libs/EIC/EICPluralModel.js" + ], + "compressed": false, + "minify": false, + "mangle": false, + "setIndexPage": true + } + ] + } +} diff --git a/app/config/config.myeic.accp.json b/app/config/config.myeic.accp.json new file mode 100644 index 0000000..2dc2962 --- /dev/null +++ b/app/config/config.myeic.accp.json @@ -0,0 +1,110 @@ +{ + "assets": { + "basePath": "/app/assets/" + }, + "router": { + "getRolesFrom": "app.User.getRoles", + "controllersPath": "/app/controllers/", + "modelsPath": "/app/models/", + "viewsPath": "/app/views/", + "libsBaseClasses":[ + { + "path": "/EIC", + "classes": [ "EICController", "EICDomContent", "EICDialogContent", "EICMetaData", "EICModel", "EICPluralModel", "EICBusModel" ], + "dependencies" : { "EICPluralModel": [ "EICModel" ] } + }, + { "onlyIfClasses": [ "MessageBus" ], + "path": "/Bus/rendezVous", + "classes": [ "MBRendezVous" ], + "dependencies" : { } + } + ], + "masterController": "EICAppController", + "defaultMasterTemplate": "templates/EICAppTemplate" + }, + "logger": { + "enabled": true, + "levels": ["err","warn"], + "latestErrsMax": 20, + "postUrl": "xxxhttps://api.accp.eismea.eu/logger" + }, + "userLib": { + "className": "myUser", + "authEndpoint": "https://api.accp.eismea.eu/stable/authorizer/checkAuthenticated", + "logoutEndpoint": "https://api.accp.eismea.eu/stable/authorizer/logout", + "apiDiscoveryEndpoint": "https://api.accp.eismea.eu/stable/apis/services", + "resourcePermissionsEndpoint": "https://api.accp.eismea.eu/stable/permissions", + "apiStage": "stable", + "apiStageExceptions": { + }, + "authForwardDomain": false, + "keepAliveSeconds": 0 + }, + "matomo4sparc": { + "enabled": true, + "trackUrl": "https://analytics.accp.eismea.eu/matomo.php", + "idsite":5 + }, + "messageBus":{ + "enabled": true, + "debug": false, + "tokenUrl": "https://api.accp.eismea.eu/stable/msgBusToken", + "pathToWorker": "/core/libs/MessageBusWorker.js", + "protocol": "wss://", + "host": "bus.accp.eismea.eu", + "port": "", + "path": "/msgbus", + "connectTimeout": 5, + "autoReconnect": 5, + "autoReconnectTimeFactor": 1.3, + "autoReconnectTimeMax": 30, + "autoReconnectJitterPercent": 10, + "frontBusPrefix": "", + "userNotifChan": "system:notifs:{uid}", + "rendezVousChan": "rendezVous:{uid}", + "ptpChanPrefix": "peer2peer:" + }, + "squeeze": { + "indexDefaults" : { + "scripts" : [ "/core/Sparc-core-1.0.js" ], + "styles" : ["/app/thirdparty/eicui/eicui-2.0.css"] + }, + "packages" : [ + { + "target": "core.js", + "sources": [ "/core/Sparc-core-1.0.js", + "/core/libs/Assets.js", + "/core/libs/Events.js", + "/core/libs/Logger.js", + "/core/libs/MessageBus.js", + "/core/libs/Router.js", + "/core/baseClasses/Controller.js", + "/core/baseClasses/MasterController.js", + "/core/baseClasses/Model.js", + "/core/baseClasses/View.js", + "/core/baseClasses/User.js", + "/app/libs/myUser.js" + ], + "compressed": false, + "minify": true, + "mangle": false, + "setIndexPage": true + }, + { + "target": "eiclibs.js", + "sources": [ + "/app/libs/EIC/EICController.js", + "/app/libs/EIC/EICDialogContent.js", + "/app/libs/EIC/EICDomContent.js", + "/app/libs/EIC/EICMetaData.js", + "/app/libs/EIC/EICModel.js", + "/app/libs/EIC/EICPluralModel.js" + ], + "compressed": false, + "minify": false, + "mangle": false, + "setIndexPage": true + } + ] + } +} diff --git a/app/config/config.myeic.prod.json b/app/config/config.myeic.prod.json new file mode 100644 index 0000000..e897c9e --- /dev/null +++ b/app/config/config.myeic.prod.json @@ -0,0 +1,110 @@ +{ + "assets": { + "basePath": "/app/assets/" + }, + "router": { + "getRolesFrom": "app.User.getRoles", + "controllersPath": "/app/controllers/", + "modelsPath": "/app/models/", + "viewsPath": "/app/views/", + "libsBaseClasses":[ + { + "path": "/EIC", + "classes": [ "EICController", "EICDomContent", "EICDialogContent", "EICMetaData", "EICModel", "EICPluralModel", "EICBusModel" ], + "dependencies" : { "EICPluralModel": [ "EICModel" ] } + }, + { "onlyIfClasses": [ "MessageBus" ], + "path": "/Bus/rendezVous", + "classes": [ "MBRendezVous" ], + "dependencies" : { } + } + ], + "masterController": "EICAppController", + "defaultMasterTemplate": "templates/EICAppTemplate" + }, + "logger": { + "enabled": true, + "levels": ["err","warn"], + "latestErrsMax": 20, + "postUrl": "xxxhttps://api.eismea.eu/logger" + }, + "userLib": { + "className": "myUser", + "authEndpoint": "https://api.eismea.eu/stable/authorizer/checkAuthenticated", + "logoutEndpoint": "https://api.eismea.eu/stable/authorizer/logout", + "apiDiscoveryEndpoint": "https://api.eismea.eu/stable/apis/services", + "resourcePermissionsEndpoint": "https://api.eismea.eu/stable/permissions", + "apiStage": "stable", + "apiStageExceptions": { + }, + "authForwardDomain": false, + "keepAliveSeconds": 0 + }, + "matomo4sparc": { + "enabled": true, + "trackUrl": "https://analytics.eismea.eu/matomo.php", + "idsite":10 + }, + "messageBus":{ + "enabled": true, + "debug": false, + "tokenUrl": "https://api.eismea.eu/stable/msgBusToken", + "pathToWorker": "/core/libs/MessageBusWorker.js", + "protocol": "wss://", + "host": "bus.eismea.eu", + "port": "", + "path": "/msgbus", + "connectTimeout": 5, + "autoReconnect": 5, + "autoReconnectTimeFactor": 1.3, + "autoReconnectTimeMax": 30, + "autoReconnectJitterPercent": 10, + "frontBusPrefix": "", + "userNotifChan": "system:notifs:{uid}", + "rendezVousChan": "rendezVous:{uid}", + "ptpChanPrefix": "peer2peer:" + }, + "squeeze": { + "indexDefaults" : { + "scripts" : [ "/core/Sparc-core-1.0.js" ], + "styles" : ["/app/thirdparty/eicui/eicui-2.0.css"] + }, + "packages" : [ + { + "target": "core.js", + "sources": [ "/core/Sparc-core-1.0.js", + "/core/libs/Assets.js", + "/core/libs/Events.js", + "/core/libs/Logger.js", + "/core/libs/MessageBus.js", + "/core/libs/Router.js", + "/core/baseClasses/Controller.js", + "/core/baseClasses/MasterController.js", + "/core/baseClasses/Model.js", + "/core/baseClasses/View.js", + "/core/baseClasses/User.js", + "/app/libs/myUser.js" + ], + "compressed": false, + "minify": true, + "mangle": false, + "setIndexPage": true + }, + { + "target": "eiclibs.js", + "sources": [ + "/app/libs/EIC/EICController.js", + "/app/libs/EIC/EICDialogContent.js", + "/app/libs/EIC/EICDomContent.js", + "/app/libs/EIC/EICMetaData.js", + "/app/libs/EIC/EICModel.js", + "/app/libs/EIC/EICPluralModel.js" + ], + "compressed": false, + "minify": false, + "mangle": false, + "setIndexPage": true + } + ] + } +} diff --git a/app/config/config.myeic.test.json b/app/config/config.myeic.test.json new file mode 100644 index 0000000..1206aef --- /dev/null +++ b/app/config/config.myeic.test.json @@ -0,0 +1,110 @@ +{ + "assets": { + "basePath": "/app/assets/" + }, + "router": { + "getRolesFrom": "app.User.getRoles", + "controllersPath": "/app/controllers/", + "modelsPath": "/app/models/", + "viewsPath": "/app/views/", + "libsBaseClasses":[ + { + "path": "/EIC", + "classes": [ "EICController", "EICDomContent", "EICDialogContent", "EICMetaData", "EICModel", "EICPluralModel", "EICBusModel" ], + "dependencies" : { "EICPluralModel": [ "EICModel" ] } + }, + { "onlyIfClasses": [ "MessageBus" ], + "path": "/Bus/rendezVous", + "classes": [ "MBRendezVous" ], + "dependencies" : { } + } + ], + "masterController": "EICAppController", + "defaultMasterTemplate": "templates/EICAppTemplate" + }, + "logger": { + "enabled": true, + "levels": ["err","warn"], + "latestErrsMax": 20, + "postUrl": "xxxhttps://api.test.eismea.eu/logger" + }, + "userLib": { + "className": "myUser", + "authEndpoint": "https://api.test.eismea.eu/stable/authorizer/checkAuthenticated", + "logoutEndpoint": "https://api.test.eismea.eu/stable/authorizer/logout", + "apiDiscoveryEndpoint": "https://api.test.eismea.eu/stable/apis/services", + "resourcePermissionsEndpoint": "https://api.test.eismea.eu/stable/permissions", + "apiStage": "stable", + "apiStageExceptions": { + }, + "authForwardDomain": false, + "keepAliveSeconds": 0 + }, + "matomo4sparc": { + "enabled": true, + "trackUrl": "https://analytics.test.eismea.eu/matomo.php", + "idsite":9 + }, + "messageBus":{ + "enabled": true, + "debug": true, + "tokenUrl": "https://api.test.eismea.eu/stable/msgBusToken", + "pathToWorker": "/core/libs/MessageBusWorker.js", + "protocol": "wss://", + "host": "bus.test.eismea.eu", + "port": "", + "path": "/msgbus", + "connectTimeout": 5, + "autoReconnect": 5, + "autoReconnectTimeFactor": 1.3, + "autoReconnectTimeMax": 30, + "autoReconnectJitterPercent": 10, + "frontBusPrefix": "", + "userNotifChan": "system:notifs:{uid}", + "rendezVousChan": "rendezVous:{uid}", + "ptpChanPrefix": "peer2peer:" + }, + "squeeze": { + "indexDefaults" : { + "scripts" : [ "/core/Sparc-core-1.0.js" ], + "styles" : ["/app/thirdparty/eicui/eicui-2.0.css"] + }, + "packages" : [ + { + "target": "core.js", + "sources": [ "/core/Sparc-core-1.0.js", + "/core/libs/Assets.js", + "/core/libs/Events.js", + "/core/libs/Logger.js", + "/core/libs/MessageBus.js", + "/core/libs/Router.js", + "/core/baseClasses/Controller.js", + "/core/baseClasses/MasterController.js", + "/core/baseClasses/Model.js", + "/core/baseClasses/View.js", + "/core/baseClasses/User.js", + "/app/libs/myUser.js" + ], + "compressed": false, + "minify": true, + "mangle": false, + "setIndexPage": true + }, + { + "target": "eiclibs.js", + "sources": [ + "/app/libs/EIC/EICController.js", + "/app/libs/EIC/EICDialogContent.js", + "/app/libs/EIC/EICDomContent.js", + "/app/libs/EIC/EICMetaData.js", + "/app/libs/EIC/EICModel.js", + "/app/libs/EIC/EICPluralModel.js" + ], + "compressed": false, + "minify": false, + "mangle": false, + "setIndexPage": true + } + ] + } +} diff --git a/app/controllers/EICAppController.js b/app/controllers/EICAppController.js new file mode 100755 index 0000000..97b5abc --- /dev/null +++ b/app/controllers/EICAppController.js @@ -0,0 +1,40 @@ +class EICAppController extends MasterController { + + ControllerReady() { + // setting up session interactions + if(app.User.isAuthenticated) { + this.profile = this.content.initSession(); + } + } + + onBusConnected() { + //if('MBRendezVous' in app.LoadedClasses) app.MessageBus.rendezVous = new MBRendezVous(this) + + app.MessageBus.addBusListener( + 'growl', + ['system:notifs', + app.config.messageBus.userNotifChan.replace(/\{uid\}/g, app.User.identity.uuid) + ], + (chan, payload, sender) => { + ui.growl.append(payload.growlMessage, payload.growlSeverity, 1000*payload.growlTime) + } + ) + + app.MessageBus.addBusListener( + 'kick', + ['system:notifs', + app.config.messageBus.userNotifChan.replace(/\{uid\}/g, app.User.identity.uuid) + ], + (chan, payload, sender) => { + if(app.User.hasRole('EIC_Admin') || app.User.hasRole('EIC_Dev')) return + app.User.logout() + } + ) + + app.User.loadPreferences(); + + //if('ChatModule' in app.LoadedClasses) this.chat = new ChatModule(this.content); + } +} + +app.registerClass('EICAppController', EICAppController); \ No newline at end of file diff --git a/app/controllers/EICAppController.json b/app/controllers/EICAppController.json new file mode 100755 index 0000000..5fb24c0 --- /dev/null +++ b/app/controllers/EICAppController.json @@ -0,0 +1,16 @@ +{ + "models": [ ], + "views": [ "templates/EICAppTemplate", "templates/dialogs/ConfirmDialog" ], + "controllerDependencies": [ + "/thirdparty/eicui/eicui-2.1", + "/thirdparty/Matomo/Matomo4Sparc", + "/controllers/common/errorController" + ], + "assets": { + "styles": [ {"path": "/app/thirdparty/eicui", "name":"/eicui-2.0.css" }, {"name":"app.css" } ], + "json": [ + {"name":"global/app-menu-map.json"}, + {"path": "/app/controllers/common/", "name": "errorController.json", "comment": "Trick to preload errorController stuff, to still have error messages if S3 is down."} + ] + } +} \ No newline at end of file diff --git a/app/controllers/applicants/ApplicantController.js b/app/controllers/applicants/ApplicantController.js new file mode 100644 index 0000000..28979d6 --- /dev/null +++ b/app/controllers/applicants/ApplicantController.js @@ -0,0 +1,79 @@ +/** + * Applicant management + * + * @version 1.0 + * @author Michael Fallise + */ +class ApplicantController extends EICController { + + constructor() { + super(); + } + + dispatch() { + app.User.getBusinessPermissions([ '/organisations' ], 'Org_Member') + .then(async payload => { + if(payload['/organisations'].permissions.includes("list")) { + let model = new ApplicantOrganisationsModel(payload['/organisations'].permissions) + + model.list() + .then( async payload => { + if(payload.length > 0) { + let first = payload[0]; + app.Router.route('/applicant/' + first.pic); + } else { + ui.growl.append("You don't belong to any organisation", 'danger') + } + }) + } + }) + } + + dashboard(options) { + ui.lock(); + + let pic = options.params.pic; + + app.User.getBusinessPermissions([ + '/organisations', + '/organisations/' + pic, + '/organisations/' + pic + '/members', + '/organisations/' + pic + '/proposals' + ], 'Org_Member') + .then(async payload => { + + if(payload['/organisations/' + pic].permissions.includes('read')) { + + // MFA: Coachings currently using proposals permissions as they are linked and BE not having coaching info locally on their side + let models = { + myOrganisations: new ApplicantOrganisationsModel(payload['/organisations'].permissions), + applicant: new ApplicantOrganisationModel(payload['/organisations/' + pic].permissions), + members: new ApplicantMembersModel(payload['/organisations/' + pic + '/members'].permissions), + proposals: new ApplicantOrganisationProposalsModel(payload['/organisations/' + pic + '/proposals'].permissions), + coachings: new ApplicantOrganisationCoachingsModel(payload['/organisations/' + pic + '/proposals'].permissions), + } + + ui.unlock(); + + this.loadWindow( + 'applicants/ApplicantDashboardView', + { + title: 'My EIC', + static: true, + expanded: true + }, + { + models: models, + pic: pic, + url: options.currentRoute.url + } + ) + } else { + ui.unlock(); + ui.growl.append('You don\'t have access to this organisation', 'danger' ); + } + }) + } +} + +app.registerClass('ApplicantController', ApplicantController); \ No newline at end of file diff --git a/app/controllers/applicants/ApplicantController.json b/app/controllers/applicants/ApplicantController.json new file mode 100644 index 0000000..c1d282b --- /dev/null +++ b/app/controllers/applicants/ApplicantController.json @@ -0,0 +1,35 @@ +{ + "routes": [ + { + "url": "/", + "role": "Org_Member", + "controller" : "applicants/ApplicantController", + "method": "dispatch" + }, + { + "url": "/:pic", + "role": "Org_Member", + "controller" : "applicants/ApplicantController", + "method": "dashboard" + } + ], + "models": [ + "organisations/ApplicantOrganisationModel", + "organisations/ApplicantMembersModel", + "organisations/ApplicantOrganisationsModel", + "users/onboardingUserModel" + ], + "views": [ + "applicants/ApplicantDashboardView", + "applicants/dialogs/ApplicantMemberDialog", + "applicants/dialogs/ApplicantProposalSearchDialog", + "common/onboarding/dialogs/onboardingApplicantDialog" + ], + "dependencies": { }, + "assets": { + "json": [ + {"id":"organisation-genders", "name": "meta/organisation-genders.json"}, + {"id":"organisation-functions", "name": "meta/organisation-functions.json"} + ] + } +} \ No newline at end of file diff --git a/app/controllers/coachings/CoachingAdminController.js b/app/controllers/coachings/CoachingAdminController.js new file mode 100644 index 0000000..f0e0988 --- /dev/null +++ b/app/controllers/coachings/CoachingAdminController.js @@ -0,0 +1,34 @@ +class CoachingAdminController extends EICController { + + dashboard() { + + let models = { + coachings: new CoachingAdminModel() + } + + this.loadWindow( + 'coachings/admin/CoachingAdminDashboardView', + { + title: 'Coaching monitoring', + static: true, + expanded: true + }, + { + models: models + }); + } + + coaching(options) { + + } + + profile(options) { + this.loadWindow('coachings/common/CoachProfileView', { + title: 'Coach profile', + static: true, + expanded: true + }); + } +} + +app.registerClass('CoachingAdminController', CoachingAdminController); \ No newline at end of file diff --git a/app/controllers/coachings/CoachingAdminController.json b/app/controllers/coachings/CoachingAdminController.json new file mode 100644 index 0000000..26fc7df --- /dev/null +++ b/app/controllers/coachings/CoachingAdminController.json @@ -0,0 +1,20 @@ +{ + "routes": [ ], + "models": [ "coachings/CoachingAdminModel" ], + "views": [ + "coachings/common/CoachProfileView", + "coachings/admin/CoachingAdminDashboardView", + "coachings/admin/dialogs/CoachingCreditsDialog" + ], + "dependencies": { }, + "controllerDependencies": [ + "/thirdparty/eicui/plugins/SVG/SVG", + "/thirdparty/eicui/plugins/NodeMap/NodeMap" + ], + "assets": { + "styles": [ + {"path": "/app/thirdparty/eicui/plugins/SVG", "name":"/SVG.css" }, + {"path": "/app/thirdparty/eicui/plugins/NodeMap", "name":"/NodeMap.css" } + ] + } +} \ No newline at end of file diff --git a/app/controllers/coachings/CoachingApplicantController.js b/app/controllers/coachings/CoachingApplicantController.js new file mode 100644 index 0000000..d032e17 --- /dev/null +++ b/app/controllers/coachings/CoachingApplicantController.js @@ -0,0 +1,12 @@ +class CoachingApplicantController extends EICController { + + view(options) { + this.loadWindow('coachings/applicant/CoachingApplicantView', { + title: 'My coaching ' + options.params.id, + static: true, + expanded: true + }); + } +} + +app.registerClass('CoachingApplicantController', CoachingApplicantController); \ No newline at end of file diff --git a/app/controllers/coachings/CoachingApplicantController.json b/app/controllers/coachings/CoachingApplicantController.json new file mode 100644 index 0000000..b30a891 --- /dev/null +++ b/app/controllers/coachings/CoachingApplicantController.json @@ -0,0 +1,7 @@ +{ + "routes": [ ], + "models": [ ], + "views": [ "coachings/applicant/CoachingApplicantView" ], + "dependencies": { }, + "assets": { } +} \ No newline at end of file diff --git a/app/controllers/coachings/CoachingCoachController.js b/app/controllers/coachings/CoachingCoachController.js new file mode 100644 index 0000000..250b4b7 --- /dev/null +++ b/app/controllers/coachings/CoachingCoachController.js @@ -0,0 +1,34 @@ +class CoachingCoachController extends EICController { + + dashboard() { + let models = { + coachings: new CoachingCoachModel() + } + + this.loadWindow('coachings/coach/CoachingCoachDashboardView', { + title: 'Coach dashboard', + static: true, + expanded: true + }, + { + models: models + }); + } + + coaching(id) { + + } + + profile(options) { + this.loadWindow('coachings/common/CoachProfileView', { + title: 'My profile', + static: true, + expanded: true + }, + { + mode: 'edit' + }); + } +} + +app.registerClass('CoachingCoachController', CoachingCoachController); \ No newline at end of file diff --git a/app/controllers/coachings/CoachingCoachController.json b/app/controllers/coachings/CoachingCoachController.json new file mode 100644 index 0000000..bc1d422 --- /dev/null +++ b/app/controllers/coachings/CoachingCoachController.json @@ -0,0 +1,10 @@ +{ + "routes": [ ], + "models": [ "coachings/CoachingCoachModel" ], + "views": [ + "coachings/coach/CoachingCoachView", + "coachings/coach/CoachingCoachDashboardView" + ], + "dependencies": { }, + "assets": { } +} \ No newline at end of file diff --git a/app/controllers/common/aboutController.js b/app/controllers/common/aboutController.js new file mode 100644 index 0000000..06c829d --- /dev/null +++ b/app/controllers/common/aboutController.js @@ -0,0 +1,56 @@ +class aboutController extends EICController { + + disclaimer(){ + this.loadWindow('common/disclaimerView', { + title: 'Legal notice', + static: true, + expanded: true + }); + } + + support() { + + + this.loadWindow('common/support/SupportView', { + title: 'Technical support', + static: true, + expanded: true + }, + { + models: { tickets: new SupportModel(["list", "create"]) } + }); + } + + helpdesk(){ + this.loadWindow('common/HelpDeskView', { + title: 'Help Desk', + static: true, + expanded: true + }); + } + + guides(){ + this.loadWindow('common/GuidesListView', { + title: 'Welcome Guides', + static: true, + expanded: true + }, + {}); + } + + guide(params){ + let guideMeta = app.Assets.Store.json.videoGuides.guides.find((item)=>item.id==params.params.guideID) + + this.loadWindow('common/GuideView', { + title: guideMeta.title, + static: true, + expanded: true + }, + { + guideMeta: guideMeta, + + }); + } +} + +app.registerClass('aboutController', aboutController); \ No newline at end of file diff --git a/app/controllers/common/aboutController.json b/app/controllers/common/aboutController.json new file mode 100644 index 0000000..c510903 --- /dev/null +++ b/app/controllers/common/aboutController.json @@ -0,0 +1,48 @@ +{ + "routes": [ + { + "url": "/legalnotice", + "role": "*", + "controller" : "common/aboutController", + "method": "disclaimer" + }, + { + "url": "/support", + "role": "*", + "controller" : "common/aboutController", + "method": "support" + }, + { + "url": "/helpdesk", + "role": "*", + "controller" : "common/aboutController", + "method": "helpdesk" + }, + { + "url": "/guides", + "role": "*", + "controller" : "common/aboutController", + "method": "guides" + }, + { + "url": "/guide/:guideID", + "role": "*", + "controller" : "common/aboutController", + "method": "guide" + } + ], + "models": [ "system/SupportModel" ], + "views": [ + "common/disclaimerView", + "common/support/SupportView", + "common/support/dialogs/SupportIssueFormDialog", + "common/HelpDeskView", + "common/GuidesListView", + "common/GuideView" + ], + "controllerDependencies": [ + "/thirdparty/eicui/plugins/Select/BinaryFileContentSelector", + "/helpers/basicDialogs" + ], + "assets": { } +} \ No newline at end of file diff --git a/app/controllers/common/errorController.js b/app/controllers/common/errorController.js new file mode 100755 index 0000000..35e926e --- /dev/null +++ b/app/controllers/common/errorController.js @@ -0,0 +1,31 @@ +/** + * + */ +class errorController extends EICController { + + /** + * + * @param {*} args + */ + _404(args) { ui.growl.append('Sorry, this resource is unavailable', 'danger'); } + + async _401(args) { + let options = { + title: 'Session expired', + message: `Unfortuately, your action could not be completed,
+ because your session has expired !
+ Please retry after a succesfull login. + `, + cancelLabel: 'Login again...', + okLabel: '', + severity: 'danger', + muted: false, + okPromise:() => { }, + } + let result = await this.openDialog(await this.loadContent('templates/dialogs/ConfirmDialog', options, options)); + window.onbeforeunload = null // If user asks to relogin, not need to have him confirm he's leaving the app ! + document.location.href = args.params.triggerUrl + } +} + +app.registerClass('errorController', errorController); \ No newline at end of file diff --git a/app/controllers/common/errorController.json b/app/controllers/common/errorController.json new file mode 100755 index 0000000..a771b52 --- /dev/null +++ b/app/controllers/common/errorController.json @@ -0,0 +1,7 @@ +{ + "routes": [ ], + "models": [ ], + "views": [ ], + "dependencies": { }, + "assets": { } +} \ No newline at end of file diff --git a/app/controllers/common/myProfileController.js b/app/controllers/common/myProfileController.js new file mode 100644 index 0000000..76375f2 --- /dev/null +++ b/app/controllers/common/myProfileController.js @@ -0,0 +1,12 @@ +class myProfileController extends EICController { + + index(routeInfo){ + this.loadWindow('common/profile/myProfileView', { + title: 'My Profile', + static: true, + expanded: true + }); + } +} + +app.registerClass('myProfileController', myProfileController); \ No newline at end of file diff --git a/app/controllers/common/myProfileController.json b/app/controllers/common/myProfileController.json new file mode 100644 index 0000000..81ba4c1 --- /dev/null +++ b/app/controllers/common/myProfileController.json @@ -0,0 +1,10 @@ +{ + "routes": [ ], + "models": [ ], + "views": [ + "common/profile/myProfileView", + "common/profile/dialogs/ProfilePreferencesResetDialog" + ], + "dependencies": { }, + "assets": { } +} \ No newline at end of file diff --git a/app/controllers/common/onboardingController.js b/app/controllers/common/onboardingController.js new file mode 100644 index 0000000..cb72402 --- /dev/null +++ b/app/controllers/common/onboardingController.js @@ -0,0 +1,50 @@ +class onboardingController extends EICController { + + async index() { + + let profile = await this.openDialog( + await this.loadContent( + 'common/onboarding/dialogs/onboardingLandingDialog', { title: 'Welcome to the EIC platform!' }, {}) + ); + + if(profile) { this.onboardProfile(profile); } + } + + async onboardProfile(profile) { + let options = { view: '', label: '' }; + + switch(profile) { + case 'Applicant': + options.view = 'common/onboarding/dialogs/onboardingApplicantDialog'; + options.label = 'Now tell us about your organisation'; + break; + } + + app.User.getBusinessPermissions(['/organisations']) + .then(async payload => { + let rc = await this.openDialog( + await this.loadContent( + options.view, + { title: options.label }, + { models: {'user': new onboardingUserModel(payload['/organisations'].permissions) } } + ) + ); + if(!rc) this.index(); + else { + if(rc.request=='join') { + await this.openDialog( + await this.loadContent( + 'common/onboarding/dialogs/onboardingRequestSuccessDialog', + { title: 'Request successfull' }, + { legalname: rc.legalname } + ) + ); + } + } + }) + + } + +} + +app.registerClass('onboardingController', onboardingController); \ No newline at end of file diff --git a/app/controllers/common/onboardingController.json b/app/controllers/common/onboardingController.json new file mode 100644 index 0000000..af99552 --- /dev/null +++ b/app/controllers/common/onboardingController.json @@ -0,0 +1,15 @@ +{ + "routes": [ ], + "models": [ + "users/onboardingUserModel" + ], + "views": [ + "common/onboarding/dialogs/onboardingLandingDialog", + "common/onboarding/dialogs/onboardingApplicantDialog", + "common/onboarding/dialogs/onboardingRequestSuccessDialog" + ], + "dependencies": { }, + "assets": { + "styles": [] + } +} \ No newline at end of file diff --git a/app/controllers/comms/mailings/MailingsController.js b/app/controllers/comms/mailings/MailingsController.js new file mode 100644 index 0000000..0061b6c --- /dev/null +++ b/app/controllers/comms/mailings/MailingsController.js @@ -0,0 +1,63 @@ +class MailingsController extends EICController { + + constructor() { + super() + + app.meta.add('wf-mailings', app.Assets.Store.json['wf-mailings']) + } + + async dashboard(options) { + + app.User.getBusinessPermissions(['/mailings']) + .then(async payload => { + if(payload['/mailings'].permissions.length > 0) { + let models = { + mailings: new MailingsModel(payload['/mailings'].permissions) + } + + await app.Assets.loadHtml({name:'mailing/tile.html'}) + this.loadWindow( + 'comms/mailings/dashboard/MailingDashboardView', + { + title: 'Mailings', + static: true, + expanded: true + }, + { + models: models + } + ) + } else { + ui.growl.append('Sorry, you do not have access to this resource', 'danger') + } + }) + } + + async mailing(options) { + app.User.getBusinessPermissions(['/mailings', '/templates', '/contactMgr']) + .then(async payload => { + if(payload['/mailings'].permissions.length > 0) { + let models = { + mailings: new MailingsModel(payload['/mailings'].permissions), + templates : new TemplatesModel(payload['/templates'].permissions), + contactMgr: new ContactMgrModel(payload['/contactMgr'].permissions), + } + + this.loadWindow('comms/mailings/sheet/MailingSheetView', { + title: 'Mailing sheet', + static: true, + expanded: true + },{ + id: options.params.id, + models: models + }) + } else { + ui.growl.append('Sorry, you do not have access to this resource', 'danger') + } + }) + } + +} + +app.registerClass('MailingsController', MailingsController) + diff --git a/app/controllers/comms/mailings/MailingsController.json b/app/controllers/comms/mailings/MailingsController.json new file mode 100644 index 0000000..e34f39b --- /dev/null +++ b/app/controllers/comms/mailings/MailingsController.json @@ -0,0 +1,53 @@ +{ + "routes": [ + { + "url": "/:id", + "role": [ "MAIL_Editor", "MAIL_Reviewer", "MAIL_Sender", "EIC_Dev", "EIC_Admin" ], + "controller" : "comms/mailings/MailingsController", + "method": "mailing" + }, + { + "url": "/", + "role": [ "MAIL_Editor", "MAIL_Reviewer", "MAIL_Sender", "EIC_Dev", "EIC_Admin" ], + "controller" : "comms/mailings/MailingsController", + "method": "dashboard" + } + ], + "models": [ "comms/templates/TemplatesModel", + "comms/mailings/MailingsModel", + "comms/mailings/ContactMgrModel" + ], + "views": [ + "/comms/mailings/dashboard/MailingDashboardView", + "comms/mailings/sheet/MailingSheetView", + "comms/mailings/sheet/dialogs/MailingImportDialog", + "comms/mailings/sheet/dialogs/MailingExclusionDialog", + "comms/mailings/sheet/dialogs/MailingFetchDialog", + "comms/mailings/sheet/dialogs/MailingMappingDialog", + "comms/mailings/sheet/dialogs/MailingTestDialog", + "comms/mailings/sheet/dialogs/MailingTemplatePreviewDialog", + "comms/mailings/sheet/dialogs/MailingDuplicatesDialog", + "templates/Ffs/dialogs/FileBrowserDialog" + ], + "controllerDependencies": [ + "https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js", + "/helpers/basicDialogs", + "/helpers/translator", + "/helpers/validators", + "/helpers/activeAttributes", + "/thirdparty/eicui/plugins/FileUpload/FileUpload", + "/thirdparty/eicui/plugins/NodeMap/NodeMap", + "/thirdparty/eicui/plugins/Charts/Charts", + "/libs/Ffs/fakeFileSystem" + ], + "assets": { + "json": [ + {"id":"wf-mailings", "name": "workflows/wf-mailings.json"} + ], + "styles": [ + {"name":"NodeMap.css", "path":"/app/thirdparty/eicui/plugins/NodeMap/" }, + {"name":"FileUpload.css", "path":"/app/thirdparty/eicui/plugins/FileUpload/"}, + {"name":"Charts.css", "path":"/app/thirdparty/eicui/plugins/Charts/" } + ] + } +} \ No newline at end of file diff --git a/app/controllers/comms/templates/TemplatesController.js b/app/controllers/comms/templates/TemplatesController.js new file mode 100644 index 0000000..bca90d9 --- /dev/null +++ b/app/controllers/comms/templates/TemplatesController.js @@ -0,0 +1,55 @@ +class TemplatesController extends EICController { + constructor() { + super() + } + + async search() { + app.User.getBusinessPermissions(['/templates']) + .then(async payload => { + if(payload['/templates'].permissions.length > 0) { + let models = { + templates: new TemplatesModel(payload['/templates'].permissions) + } + this.loadWindow('comms/templates/manager/TemplatesManagerView', { + title: 'Templates', + static: true, + expanded: true + }, + { + models: models + } + ) + } else { + ui.growl.append('Sorry, you do not have access to this resource', 'danger') + } + }) + } + + async tplAction(options) { + app.User.getBusinessPermissions(['/templates']) + .then(async payload => { + if(payload['/templates'].permissions.length > 0) { + const templateId = options.params.id; + let models = { + templates: new TemplatesModel(payload['/templates'].permissions) + } + // Edit template + this.loadWindow( + 'comms/templates/editor/TemplatesEditorView', + { + title: 'Edit Template ' + templateId.substring(0, 6), + static: true, + expanded: true + }, + { + id: templateId, + models: models + }) + } else { + ui.growl.append('Sorry, you do not have access to this resource', 'danger') + } + }) + } + } + +app.registerClass('TemplatesController', TemplatesController); diff --git a/app/controllers/comms/templates/TemplatesController.json b/app/controllers/comms/templates/TemplatesController.json new file mode 100644 index 0000000..4369911 --- /dev/null +++ b/app/controllers/comms/templates/TemplatesController.json @@ -0,0 +1,39 @@ +{ + "routes": [ + { + "url": "/templates", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller" : "comms/templates/TemplatesController", + "method": "search" + }, + { + "url": "/:id", + "role": [ "EIC_Dev", "EIC_Admin" ], + "controller" : "comms/templates/TemplatesController", + "method": "tplAction" + } + ], + "models": [ "comms/templates/TemplatesModel" ], + "views": [ + "comms/templates/manager/TemplatesManagerView", + "comms/templates/editor/TemplatesEditorView", + "comms/templates/dialogs/TemplatesMailTestDialog", + "comms/templates/dialogs/TemplatesUplImgDialog", + "comms/templates/dialogs/TemplatesDecisionDialog", + "templates/Ffs/dialogs/FileBrowserDialog" + ], + "controllerDependencies": [ + "/helpers/basicDialogs", + "/helpers/translator", + "/helpers/validators", + "/helpers/activeAttributes", + "/libs/Ffs/fakeFileSystem", + "/thirdparty/eicui/plugins/HtmlEditor/HtmlEditor", + "/thirdparty/eicui/plugins/FileUpload/FileUpload" + ], + "assets": { + "styles": [ + {"name":"FileUpload.css", "path":"/app/thirdparty/eicui/plugins/FileUpload/"} + ] + } +} \ No newline at end of file diff --git a/app/controllers/projects/bypass/BypassController.js b/app/controllers/projects/bypass/BypassController.js new file mode 100755 index 0000000..ec31627 --- /dev/null +++ b/app/controllers/projects/bypass/BypassController.js @@ -0,0 +1,97 @@ +/** + * FastTrack management + * + * @version 1.0 + * @author Michael Fallise + */ +class BypassController extends EICController { + + guidelinesURL = "https://eic.ec.europa.eu/eic-funding-opportunities/eic-accelerator/fast-track-and-plug-schemes-eic-accelerator_en"; + + constructor() { + super(); + + app.meta.add('accelerator-tracks', app.Assets.Store.json['accelerator-tracks']); + app.meta.add('organisation-functions', app.Assets.Store.json['organisation-functions']); + app.meta.add('organisation-genders', app.Assets.Store.json['organisation-genders']); + } + + /** + * Entrypoint for FastTrack Managers + */ + dashboardAdmin() { + + app.User.getBusinessPermissions(['/organisations/tokens', '/organisations/tokens/users', '/organisations']) + .then(payload => { + let profile = Object.keys(payload).reduce((acc, perm)=>{ Object.assign(acc,payload[perm].profile); return(acc) }, {}) + + let models = { + tokens: new BypassTokensModel(payload['/organisations/tokens'].permissions), + company: new BypassCompanyModel([...payload['/organisations'].permissions, ...payload['/organisations/tokens'].permissions]), + }; + + if(payload['/organisations/tokens/users'].permissions && (payload['/organisations/tokens/users'].permissions.length>0)) { + models.users = new BypassUsersModel(payload['/organisations/tokens/users'].permissions) + } + + this.loadWindow( + 'projects/bypass/BypassAdminDashboard', + { title: 'Bypass', static: true, expanded: true }, + { profile: profile, models: models } + ); + }); + } + + /** + * Entrypoint for FastTrack KIC Managers + */ + dashboardKIC() { + app.User.getBusinessPermissions(['/organisations/tokens', '/organisations/tokens/users', '/organisations']) + .then(payload => { + let profile = Object.keys(payload).reduce((acc, perm)=>{ Object.assign(acc,payload[perm].profile); return(acc) }, {}) + + let models = { + tokens: new BypassTokensModel(payload['/organisations/tokens'].permissions), + company: new BypassCompanyModel([...payload['/organisations'].permissions, ...payload['/organisations/tokens'].permissions]) + }; + + if(payload['/organisations/tokens/users'].permissions && (payload['/organisations/tokens/users'].permissions.length>0)) { + models.users = new BypassUsersModel(payload['/organisations/tokens/users'].permissions) + } + + this.loadWindow( + 'projects/bypass/BypassKICDashboard', + { title: 'Fast-Tracks', static: true, expanded: true }, + { profile: profile, models: models } + ); + }); + } + + /** + * Entrypoint for FastTrack Plugin Managers + */ + dashboardPlugin() { + app.User.getBusinessPermissions(['/organisations/tokens', '/organisations/tokens/users', '/organisations']) + .then(payload => { + let profile = Object.keys(payload).reduce((acc, perm)=>{ Object.assign(acc,payload[perm].profile); return(acc) }, {}) + + let models = { + tokens: new BypassTokensModel(payload['/organisations/tokens'].permissions), + company: new BypassCompanyModel([...payload['/organisations'].permissions, ...payload['/organisations/tokens'].permissions]) + }; + + if(payload['/organisations/tokens/users'].permissions) { + models.users = new BypassUsersModel(payload['/organisations/tokens/users'].permissions) + } + + this.loadWindow( + 'projects/bypass/BypassPluginDashboard', + { title: 'Plugins', static: true, expanded: true }, + { profile: profile, models: models } ); + }); + } + + guidelines() { window.open(this.guidelinesURL, "_blank"); } +} + +app.registerClass('BypassController', BypassController); \ No newline at end of file diff --git a/app/controllers/projects/bypass/BypassController.json b/app/controllers/projects/bypass/BypassController.json new file mode 100755 index 0000000..a0e7287 --- /dev/null +++ b/app/controllers/projects/bypass/BypassController.json @@ -0,0 +1,74 @@ +{ + "routes": [ + { + "url": "/", + "role": ["BP_SPOC_Plugin"], + "exturl":"/bypass/plugins" + }, + { + "url": "/", + "role": ["BP_SPOC_FastTrack"], + "exturl":"/bypass/fast-tracks" + }, + { + "url": "/", + "role": ["BP_PO", "BP_HoU"], + "controller" : "/projects/bypass/BypassController", + "method": "dashboardAdmin" + }, + { + "url": "/fast-tracks", + "role": ["BP_SPOC_FastTrack"], + "controller" : "/projects/bypass/BypassController", + "method": "dashboardKIC" + }, + { + "url": "/plugins", + "role": ["BP_SPOC_Plugin"], + "controller" : "/projects/bypass/BypassController", + "method": "dashboardPlugin" + }, + { + "url": "/path-finder", + "role": ["BP_SPOC_FastTrack"], + "controller" : "/projects/bypass/BypassController", + "method": "dashboardKIC" + }, + { + "url": "/guidelines", + "role": ["BP_PO", "BP_HoU", "BP_SPOC_FastTrack", "BP_SPOC_Plugin"], + "controller" : "/projects/bypass/BypassController", + "method": "guidelines" + } + ], + "models": [ + "evaluations/BypassTokensModel", + "organisations/BypassCompanyModel", + "users/BypassUsersModel" + ], + "views": [ + "projects/bypass/BypassAdminDashboard", + "projects/bypass/BypassKICDashboard", + "projects/bypass/BypassPluginDashboard", + {"view":"projects/bypass/BypassPluginManagementContent", "dependencies": ["projects/bypass/BypassBaseManagementContent"]}, + {"view":"projects/bypass/BypassAdminManagementContent", "dependencies": ["projects/bypass/BypassBaseManagementContent"]}, + {"view":"projects/bypass/BypassKICManagementContent", "dependencies": ["projects/bypass/BypassBaseManagementContent"]}, + "projects/bypass/dialogs/BypassProgramAddDialog", + "projects/bypass/dialogs/BypassTokenGrantDialog", + "projects/bypass/dialogs/BypassTokenGrantProposalDialog", + "projects/bypass/dialogs/BypassTokenRevokeDialog", + "projects/bypass/dialogs/BypassTrackSetupDialog", + "projects/bypass/dialogs/BypassUserProfileDialog" + ], + "controllerDependencies": [ "/helpers/basicDialogs", "/helpers/translator" ], + "assets": { + "styles": [ + { "name": "projects/bypass.css" } + ], + "json": [ + { "id": "accelerator-tracks", "name": "meta/accelerator-tracks.json" }, + { "id":"organisation-genders", "name": "meta/organisation-genders.json"}, + { "id":"organisation-functions", "name": "meta/organisation-functions.json"} + ] + } +} \ No newline at end of file diff --git a/app/controllers/projects/icmp/ICMPController.js b/app/controllers/projects/icmp/ICMPController.js new file mode 100644 index 0000000..bb34ed3 --- /dev/null +++ b/app/controllers/projects/icmp/ICMPController.js @@ -0,0 +1,88 @@ +class ICMPController extends EICController { + + constructor(params) { + super(params) + app.meta.add('icmp-techdd-status', app.Assets.Store.json['icmp-techdd-status']); + app.meta.add('icmp-fundings', app.Assets.Store.json['icmp-fundings']); + app.meta.add('icmp-countries', app.Assets.Store.json['icmp-countries']); + app.meta.add('icmp-instruments', app.Assets.Store.json['icmp-instruments']); + } + + /** + * + * @returns + */ + Dashboard() { + console.log('here') + ui.lock(); + + app.User.getBusinessPermissions([ '/icmp/projects' ]) + .then(async payload => { + + ui.unlock(); + + if(payload['/icmp/projects'].permissions.length > 0) { + let models = { + projects: new ICMPProjectsModel(payload['/icmp/projects'].permissions) + }; + + if(app.User.hasRole('PROJECT_PO') || app.User.hasRole('PROJECT_FIO')) { + this.loadWindow( + 'projects/icmp/ProjectFundingPODashboardView', + { title: 'ICMP', static: true, expanded: true }, + { models: models } ); + return; + } + + if(app.User.hasRole('PROJECT_TechDDExpert')) { + this.loadWindow( + 'projects/icmp/ProjectFundingExpertDashboardView', + { title: 'ICMP', static: true, expanded: true }, + { models: models } ); + return; + } + } else { + ui.growl.append('You don\'t have access to this resource', 'danger' ); + } + }); + } + + /** + * + * @param {*} options + */ + project(options) { + + let number = options.params.number + let node = options.params.node + let nodeId = options.params.nodeId + + ui.lock(); + + app.User.getBusinessPermissions([`/icmp/projects/${number}`]) + .then(async payload => { + + if(payload[`/icmp/projects/${number}`].permissions.length > 0) { + ui.unlock(); + + let models = { + project: new ICMPProjectModel(payload[`/icmp/projects/${number}`].permissions) + }; + + this.loadWindow( + 'projects/icmp/ProjectFundingProjectView', + { title: 'Project sheet', static: true, expanded: true }, + { + models: models, + projectNumber: number, + node: node, + nodeId: nodeId, + }); + } else { + ui.growl.append('You don\'t have access to this resource', 'danger' ); + } + }); + } +} + +app.registerClass('ICMPController', ICMPController); \ No newline at end of file diff --git a/app/controllers/projects/icmp/ICMPController.json b/app/controllers/projects/icmp/ICMPController.json new file mode 100644 index 0000000..a811851 --- /dev/null +++ b/app/controllers/projects/icmp/ICMPController.json @@ -0,0 +1,39 @@ +{ + "routes": [], + "models": [ + "projects/icmp/ProjectFundingModel", + "projects/icmp/ICMPProjectsModel", + "projects/icmp/ICMPProjectModel", + "projects/icmp/ICMPProjectNodeModel" + ], + "views": [ + "projects/icmp/ProjectFundingPODashboardView", + "projects/icmp/ProjectFundingExpertDashboardView", + "projects/icmp/ProjectFundingProjectView", + "projects/icmp/project/ProjectFundingInfoView", + "projects/icmp/project/ProjectFundingTechDDView", + "projects/icmp/project/ProjectFundingTeamView", + "projects/icmp/project/ProjectFundingHistoryView", + "projects/icmp/project/ProjectFundingDocumentsView", + "projects/icmp/project/dialogs/ICMPNodeActionConfirmDialog", + {"view":"projects/icmp/project/forms/ICMPFormTechddV1FullView", "dependencies": ["projects/icmp/project/forms/ICMPFormTechddV1View"]}, + {"view":"projects/icmp/project/forms/ICMPFormTechddV1EnhancedView", "dependencies": ["projects/icmp/project/forms/ICMPFormTechddV1View"]} + + ], + "controllerDependencies": [ + "/thirdparty/eicui/plugins/SVG/SVG", + "/thirdparty/eicui/plugins/NodeMap/NodeMap" + ], + "assets": { + "styles": [ + {"path": "/app/thirdparty/eicui/plugins/SVG", "name":"/SVG.css" }, + {"path": "/app/thirdparty/eicui/plugins/NodeMap", "name":"/NodeMap.css" } + ], + "json": [ + { "id": "icmp-techdd-status", "name": "meta/icmp-techdd-statuses.json" }, + { "id": "icmp-fundings", "name": "meta/project-funding-types.json" }, + { "id": "icmp-countries", "name": "meta/coaching-countries.json" }, + { "id": "icmp-instruments", "name": "meta/project-funding-instruments.json" } + ] + } +} \ No newline at end of file diff --git a/app/controllers/projects/soe/SoeController.js b/app/controllers/projects/soe/SoeController.js new file mode 100644 index 0000000..a94c85a --- /dev/null +++ b/app/controllers/projects/soe/SoeController.js @@ -0,0 +1,74 @@ + +class SoeController extends EICController { + + constructor() { + super(); + + app.meta.add('soe-fundings', app.Assets.Store.json['soe-fundings']); + app.meta.add('soe-countries', app.Assets.Store.json['coaching-countries']); + } + + /** + * Entrypoint for FastTrack Managers + */ + dashboard() { + + app.User.getBusinessPermissions(['/soe']) + .then(payload => { + + if(payload['/soe'].permissions.length > 0) { + let models = { + soe: new SoeModel(payload['/soe'].permissions) + } + + let scope = payload['/soe'].profile.country ? app.meta.getItem('soe-countries', payload['/soe'].profile.country).label: 'Monitoring'; + + this.loadWindow( + 'projects/soe/SoeDashboardView', + { title: 'SoE ' + scope, static: true, expanded: true }, + { + models: models, + scope : scope + } + ); + } else { + ui.growl.append('Sorry, you do not have access to this resource!', 'danger') + } + + }); + + + } + + feedbacks(options) { + + let pic = options.params.pic + let number = options.params.number + + app.User.getBusinessPermissions([`/soe/organisations/${pic}/projects/${number}/fundings`]) + .then(payload => { + let scope = payload[`/soe/organisations/${pic}/projects/${number}/fundings`] + if(scope.permissions.length > 0) { + + let models = { soe: new SoeModel(scope.permissions) } + + this.loadWindow( + 'projects/soe/SoeFeedbacksView', + { title: `Project ${number} (SoE)`, static: true, expanded: true }, + { + pic: pic, + number: number, + models: models + } + ); + } else { + ui.growl.append('Sorry, you do not have access to this resource', 'danger') + } + }); + + + } + +} + +app.registerClass('SoeController', SoeController); \ No newline at end of file diff --git a/app/controllers/projects/soe/SoeController.json b/app/controllers/projects/soe/SoeController.json new file mode 100644 index 0000000..0c30b03 --- /dev/null +++ b/app/controllers/projects/soe/SoeController.json @@ -0,0 +1,17 @@ +{ + "routes": [ ], + "models": [ "projects/SoeModel" ], + "views": [ + "projects/soe/SoeDashboardView", + "projects/soe/SoeFeedbacksView", + "projects/soe/dialogs/SoeFeedbackFormDialog", + "projects/soe/dialogs/SoeFeedbackHistoryDialog" + ], + "dependencies": { }, + "assets": { + "json": [ + { "id":"coaching-countries", "name": "meta/coaching-countries.json" }, + { "id":"soe-fundings", "name": "meta/soe-fundings.json" } + ] + } +} \ No newline at end of file diff --git a/app/controllers/projects/submissions/SubmissionsController.js b/app/controllers/projects/submissions/SubmissionsController.js new file mode 100644 index 0000000..65c23b4 --- /dev/null +++ b/app/controllers/projects/submissions/SubmissionsController.js @@ -0,0 +1,76 @@ +/** + * Submission management + * + * @version 1.0 + */ +class SubmissionsController extends EICController { + + + /** + * + * @param {*} options + * + */ + proposal(options) { + let pic = options.params.pic; + let number = options.params.pid; + let mode = options.params.mode || 'read'; + + app.User.getBusinessPermissions([ + `/organisations/${pic}/proposals/${number}`, + `/organisations/${pic}/proposals/${number}/members` + ], 'Org_Member') + .then( async payload => { + + if(mode == 'edit') { + if(!payload[`/organisations/${pic}/proposals/${number}`].permissions.includes('update')) { + mode = 'read'; + } + } + + if(payload[`/organisations/${pic}/proposals/${number}`].permissions.includes('read')) { + + let models = { + 'submission' : new SubmissionModel( payload[`/organisations/${pic}/proposals/${number}`].permissions ), + 'team' : new SubmissionTeamModel( [ 'create', 'update', 'delete' ] ), + 'members' : new SubmissionMembersModel( payload[`/organisations/${pic}/proposals/${number}/members`].permissions ) + }; + + app.meta.add('organisation-functions', app.Assets.Store.json['organisation-functions']); + app.meta.add('organisation-genders', app.Assets.Store.json['organisation-genders']); + app.meta.add('eic-keywords', app.Assets.Store.json['eic-keywords']); + + models.submission.getProposal(pic,number).then( + async () => { + let formVersions = { + 'legacy' : '2022', + '1.0' : '2023', + '1.1' : '2023' + }; + + let formVersion = formVersions[models.submission.data.version || 'legacy']; + + await Loader.loadViews(app.Router.ControllerConfigs.SubmissionsController.lazyViews[formVersion]); + this.loadWindow( + `projects/submissions/${formVersion}/SubmissionShortForm${formVersion}View`, + { title: 'Proposal ' + number, static: true, expanded: true }, + { + profile: { + mode: mode, + pic: pic, + number: number + }, + models: models + } + ); + }) + + } else { + ui.growl.append('You are not allowed to access this proposal', 'danger'); + } + + }) + } +} + +app.registerClass('SubmissionsController', SubmissionsController); diff --git a/app/controllers/projects/submissions/SubmissionsController.json b/app/controllers/projects/submissions/SubmissionsController.json new file mode 100644 index 0000000..3b86bd9 --- /dev/null +++ b/app/controllers/projects/submissions/SubmissionsController.json @@ -0,0 +1,60 @@ +{ + "routes": [ + { + "url": "/:pid", + "role": "Org_Member", + "controller" : "/projects/submissions/SubmissionsController", + "method": "proposal" + } + ], + "models": [ + "/submissions/SubmissionModel", + "/organisations/ApplicantMembersModel" + ], + "views": [ + "/projects/submissions/dialogs/SubmissionFormAccessDialog", + "/projects/submissions/dialogs/SubmissionFormComplaintDialog" + + ], + "controllerDependencies": [ "/thirdparty/AwsGoodies/AwsFileDownload", "/thirdparty/AwsGoodies/AwsFileUpload", "https://cdn.jsdelivr.net/npm/hls.js@latest" ], + "assets": { + "styles": [ { "name": "projects/submissions.css" } ], + "json": [ + {"id":"organisation-genders", "name": "meta/organisation-genders.json"}, + {"id":"eic-keywords", "name": "meta/eic-keywords.json"}, + {"id":"organisation-functions", "name": "meta/organisation-functions.json"} + ] + }, + "lazyViews": { + "2022": [ + "/projects/submissions/2022/SubmissionShortForm2022View", + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022WhatView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022WhyView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022WhoView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022HowView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022AmountView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022WhomView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022ImpactView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022DocumentsView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2022/tabs/SubmissionShortForm2022StatusView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]} + ], + "2023": [ + "/projects/submissions/2023/SubmissionShortForm2023View", + "/projects/submissions/dialogs/SubmissionFormTeamMemberDialog", + "/projects/submissions/dialogs/SubmissionFormUploadDialog", + "/projects/submissions/dialogs/SubmissionFormConcurrencyDialog", + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023CompanyView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023CompetitionView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023FundingView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023GeneralView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023ProblemView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023SolutionView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023TeamView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023ImpactView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023DocumentsView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023DisclaimerView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023StatusView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]}, + {"view":"projects/submissions/2023/tabs/SubmissionShortForm2023ConsentView", "dependencies": [ "projects/submissions/SubmissionShortFormTabView" ]} + ] + } +} \ No newline at end of file diff --git a/app/controllers/system/systemController.js b/app/controllers/system/systemController.js new file mode 100755 index 0000000..009c288 --- /dev/null +++ b/app/controllers/system/systemController.js @@ -0,0 +1,107 @@ +class systemController extends EICController { + + /** + * Platform access control + * + * @param {*} params + */ + control() { + app.meta.add('user-roles', app.Assets.Store.json['user-roles']); + app.meta.add('user-messages', app.Assets.Store.json['user-messages']); + let models = { + platform: new PlatformModel() + } + + this.loadWindow( + 'system/admin/platform-control/AdminAccessControlView', + { title: 'Platform Control', static: true, expanded: true }, + { models: models } + ); + } + + explore() { + + + app.User.getBusinessPermissions([ '/storage/entities' ], 'EIC_Admin') + .then(payload => { + + console.log(payload) + + let models = { + ml: new MarklogicModel(payload['/storage/entities'].permissions) + } + + this.loadWindow( + 'system/admin/explorer/DataExplorerView', + { title: 'Data explorer', static: true, expanded: true }, + { models: models } + ); + }) + } + + /** + * System Health check content + * + * @param {*} params + */ + healthcheck() { + + this.loadWindow('system/tools/statusView', { + title: 'Health Check', + static: true, + expanded: true + } + ); + } + + /** + * + */ + async styleguide() { + + await Loader.loadViews(["system/tools/styleguideView"]); + + this.loadWindow('system/tools/styleguideView', { + title: 'Style guide', + static: true, + expanded: true + }); + } + + /** + * + */ + async eicui() { + + await Loader.loadViews(["system/tools/EICUIView"]); + + this.loadWindow( + 'system/tools/EICUIView', + { title: 'EICUI', static: true, expanded: true} + ); + } + + sampler(params) { + this.loadWindow( + 'system/lab/SamplerView', + { title: 'SAMPLER3000', static: true, expanded: true } + ); + } + + chalkboard(params) { + this.loadWindow( + 'system/lab/ChalkboardView', + { title: 'Chalkboard', static: true, expanded: true } + ); + } + + components(params) { + this.loadWindow('system/lab/ComponentLabView', { + title: 'Component Lab', + static: true, + expanded: true + }); + } +} + +app.registerClass('systemController', systemController); \ No newline at end of file diff --git a/app/controllers/system/systemController.json b/app/controllers/system/systemController.json new file mode 100755 index 0000000..e1d7d00 --- /dev/null +++ b/app/controllers/system/systemController.json @@ -0,0 +1,82 @@ +{ + "routes": [ + { + "url": "/control", + "role": "*", + "controller" : "/system/systemController", + "method": "control" + }, + { + "url": "/healthcheck", + "role": "*", + "controller" : "/system/systemController", + "method": "healthcheck" + }, + { + "url": "/styleguide", + "role": "*", + "controller" : "/system/systemController", + "method": "styleguide" + }, + { + "url": "/eicui", + "role": "*", + "controller" : "/system/systemController", + "method": "eicui" + }, + { + "url": "/sampler", + "role": "*", + "controller" : "/system/systemController", + "method": "sampler" + }, + { + "url": "/chalkboard", + "role": "*", + "controller" : "/system/systemController", + "method": "chalkboard" + }, + { + "url": "/explorer", + "role": "*", + "controller" : "/system/systemController", + "method": "explore" + } + ], + "models": [ + "system/PlatformModel", + "system/MarklogicModel" + ], + "views": [ + "system/admin/platform-control/AdminAccessControlView", + "system/lab/SamplerView", + "system/lab/ChalkboardView", + "system/lab/ComponentLabView", + "system/tools/statusView", + "system/admin/explorer/DataExplorerView", + "system/admin/platform-control/dialogs/PlatformUserMessageDialog", + "system/admin/platform-control/dialogs/PlatformDownDialog", + "system/admin/platform-control/dialogs/PlatformConfigViewDialog", + "system/tools/dialogs/codeTemplateDialog" + ], + "controllerDependencies": [ + "/thirdparty/eicui/plugins/FileUpload/FileUpload", + "/thirdparty/eicui/plugins/Charts/Charts", + "/thirdparty/beautify/beautify.min", + "/thirdparty/beautify/beautify.html.min", + "/thirdparty/beautify/beautify.css.min", + "/thirdparty/highlight/highlight.min", + "/helpers/basicDialogs" + ], + "assets": { + "styles": [ + { "name":"FileUpload.css", "path":"/app/thirdparty/eicui/plugins/FileUpload/" }, + { "name":"Charts.css", "path":"/app/thirdparty/eicui/plugins/Charts/" }, + { "name":"monokai.min.css", "path":"/app/thirdparty/highlight/styles/" } + ], + "json": [ + { "id": "user-roles", "name": "global/user-roles.json" }, + { "id": "user-messages", "name": "system/user-messages.json" } + ] + } +} \ No newline at end of file diff --git a/app/helpers/activeAttributes.js b/app/helpers/activeAttributes.js new file mode 100644 index 0000000..95f9d10 --- /dev/null +++ b/app/helpers/activeAttributes.js @@ -0,0 +1,135 @@ +if(!app.helpers) app.helpers = {} +/** + * Mixing add-in methods to your view instance. + * All of this should not be a helper, but inherited this from EICDomContent, but not my framework anymore. + * @category MyEic + */ +app.helpers.activeAttributes = { + + /** + * setupTriggers adds all click (data-trigger) and change (data-change) handlers. + * handlers should have the signatue : onXyz(component, event), will spit a warning if the handler doesn't exist. + * setupTriggers is re-entrant: it can be called again after refreshing part of the view + * @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) ) + */ + setupTriggers(components){ // Should inherit this from EICDomContent, but not my framework anymore. + for(let component of components.filter(component => component.el.hasAttribute('data-trigger'))) { + if(typeof this[component.el.dataset.trigger] !== 'function') { + console.warn(`data-trigger without corresponding method : ${component.el.dataset.trigger}`) + continue + } + component.click = this[component.el.dataset.trigger].bind(this, component) + } + for(let component of components.filter(component => component.el.hasAttribute('data-change'))) { + if(typeof this[component.el.dataset.change] !== 'function') { + console.warn(`data-change without corresponding method : ${component.el.dataset.trigger}`) + continue + } + component.el.addEventListener("change",this[component.el.dataset.change].bind(this, component)) + if(component.el.type=='text') component.el.addEventListener("keyup",this[component.el.dataset.change].bind(this, component)) + } + }, + + /** + * setupRefs will populate : + * => this.components: an attribute 'data-ref="toto"' will create the reference this.components.toto to the EICUI component + * => this.outputs: an attribute 'data-output="titi"' will create the reference this.outputs.toto to the dom node (used by this.output() ) + * => this.asyncComponents: an attribute 'data-async="tintin"' will create the reference this.asyncComponents.tintin (used by setAsyncLoading() ) + * => this.asyncElements: an attribute 'data-async="haddock"' will create the reference this.asyncElements.haddock (used by setAsyncLoading() ) + * setupRefs is re-entrant: it can be called again after refreshing part of the view + * @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) ) + */ + setupRefs(components){ + if(!this.components) this.components = {} + for(let component of components.filter(component => component.el.hasAttribute('data-ref'))) { + this.components[component.el.dataset.ref] = component + } + if(!this.asyncComponents) this.asyncComponents = {} + for(let component of components.filter(component => component.el.hasAttribute('data-async'))) { + this.asyncComponents[component.el.dataset.async] = component + } + + if(!this.asyncElements) this.asyncElements = {} + for(let el of this.el.querySelectorAll('[data-async]')) { + if('eicuiId' in el.dataset) continue + this.asyncElements[el.dataset.async] = el + } + + if(!this.outputs) this.outputs = {} + for(let el of this.el.querySelectorAll('[data-output]')) { + this.outputs[el.dataset.output] = el + } + }, + + /** + * output (singular) : this.output('mydiv', '

Some markup

') places markup in a data-output node + * @param {*} name + * @param {*} markup + */ + output(name, markup){ + if(name in this.outputs) this.outputs[name].innerHTML = markup + else console.warn(`Output ${name} not found !`) + }, + + /** + * setAsyncLoading Turns on all or some of the loaders + * @param {boolean} value : true to show loading, false to hide + * @param {string[]} names : (optional) array of names to show/hide, (names given via the data-async attributes) + * If no names given, will show/hide all asyncs of the view + * Small counter so it can handle several async requests which are overlapping and using on the same loader. + * Ex1 overlapping completion: loader=true & REQ1-start, loader=true & REQ2-start, REQ1-end & loader=false, REQ2-end & loader=false ] + * Ex2 inverted completion: loader=true & REQ1-start, loader=true & REQ2-start, REQ2-end & loader=false, REQ1-end & loader=false ] + */ + setAsyncLoading(value, names=null){ + if(!this.asyncComponents) this.asyncComponents = {} + if(!this.asyncComponentsCnt) this.asyncComponentsCnt = {} + if(!names) names = [ ...Object.keys(this.asyncComponents), ...Object.keys(this.asyncElements)] + for(let name of names){ + if(name in this.asyncComponentsCnt){ this.asyncComponentsCnt[name] = value ? this.asyncComponentsCnt[name]+1 : this.asyncComponentsCnt[name]-1 } + else { this.asyncComponentsCnt[name] = value ? 1 : 0 } + + if(name in this.asyncComponents) this.asyncComponents[name].loading = (this.asyncComponentsCnt[name]>0) + if(name in this.asyncElements) { + const el = this.asyncElements[name].querySelector('.icon-spinner.spin') + if(el) el.remove() + if((this.asyncComponentsCnt[name]>0)){ + this.asyncElements[name].prepend(Object.assign(document.createElement('div'), + { className: 'icon-spinner spin', style: 'width:1em;height:1em;margin:1em;position: absolute;z-index: 9999;' })) + } + } + } + }, + + /** + * Manage spin loader + * @param {*} element + * @param {*} loadingText + * @returns + */ + showLoading(element, loadingText = '') { + if (!element) return + element.classList.add('loading') + if (element.tagName === 'BUTTON' || element.type === 'button') { + element.disabled = true + element.setAttribute('data-original-content', element.innerHTML); + element.innerHTML = loadingText; + } else if (element.hasAttribute('contenteditable')) { + element.setAttribute('data-original-content', element.innerHTML); + element.innerHTML = `${loadingText}` + element.setAttribute('contenteditable', 'false') + } + }, + + hideLoading(element, defaultIcon = null) { + if (!element) return; + element.classList.remove('loading') + if (element.tagName === 'BUTTON' || element.type === 'button') { + element.disabled = false; + element.innerHTML = element.getAttribute('data-original-content') || defaultIcon || '' + } else if (element.hasAttribute('contenteditable')) { + element.innerHTML = element.getAttribute('data-original-content') || '' + element.setAttribute('contenteditable', 'true') + } + }, + +} diff --git a/app/helpers/basicDialogs.js b/app/helpers/basicDialogs.js new file mode 100644 index 0000000..9a3b62b --- /dev/null +++ b/app/helpers/basicDialogs.js @@ -0,0 +1,27 @@ +if(!app.helpers) app.helpers = {} +/** + * @class mixing addind methods to your view + * @category MyEic + * @subcategory Helpers + * @todo intergate to MeicView ? + * @todo extract template path to config ? + */ +app.helpers.basicDialogs = { + /** + * + * @param {*} options + * @param {*} options.message + * @param {*} [options.severity] + * @param {*} [options.muted] + * @param {*} [options.okLabel] + * @param {*} [options.cancelLabel] + * @returns {*} + */ + async confirmDialog(options) { + options.severity = options.severity ? options.severity : 'danger' + options.muted = options.muted ? 'muted' : '' + let result = await this.openDialog(await this.loadContent('templates/dialogs/ConfirmDialog', options, options)); + return(result) + }, + // other basic dialogs here... +} diff --git a/app/helpers/translator.js b/app/helpers/translator.js new file mode 100644 index 0000000..14a84a0 --- /dev/null +++ b/app/helpers/translator.js @@ -0,0 +1,77 @@ +if(!app.helpers) app.helpers = {} +/** + * Helper for data transformation. + * @class Translator + * @category MyEic + * @subcategory Helpers + */ +app.helpers.translator = { + toCSV(collection, options /* keys=null, withHeader=true, quoteChar = '"', delimiter = ';', downloadName=null */) { + + let defaultOptions = { + headers: [], + delimiter: ',', + quoteCharacter: '"', + filename: 'data' + } + + options = {...defaultOptions, ...options} + /**/ + const _download = function(data, filename) { + + const blob = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), data], { type: 'text/csv; charset=utf-8' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.setAttribute('href', url); + a.setAttribute('download', filename + '.csv'); + a.click(); + } + + if(!options.keys) { // take min. common set of keys in collection (take 1st then successively intersect to itself) + let ids = Object.keys(collection); + options.keys = Object.keys(collection[ids[0]]); + for(let id of ids) { + options.keys = options.keys.filter(x => (collection[id].hasOwnProperty(x))) + } + } + + let csv=''; + let row=[]; + + if(options.headers && options.headers.length > 0){ + for(let key of options.headers) { + row.push(options.quoteCharacter + key + options.quoteCharacter); + } + csv += row.join(options.delimiter)+'\n'; + } else if(Array.isArray(options.headers)) { + for(let title of options.headers){ + row.push(options.quoteCharacter + title + options.quoteCharacter); + } + csv += row.join(options.delimiter)+'\n'; + } + for(let id in collection){ + row = []; + for(let key of options.keys){ + let item = '' + if(typeof(key)=='string'){ // normal column + item = collection[id] + for(let k of key.split('.')) { // Allow for sub-objects with dotted keys notation + if(!item) break + item = item[k] + } + } else if(typeof(key)=='function') { // computed column + item = key(collection[id]) + } else console.warn('CSV: Bad column: ',key) + row.push(options.quoteCharacter + item + options.quoteCharacter); + } + csv += row.join(options.delimiter)+'\n'; + } + + if(options.filename) _download(csv, options.filename); + + return(csv); + }, + fromCSV() { + + } +} diff --git a/app/helpers/validators.js b/app/helpers/validators.js new file mode 100644 index 0000000..75b45c3 --- /dev/null +++ b/app/helpers/validators.js @@ -0,0 +1,24 @@ +if(!app.helpers) app.helpers = {} +/** + * Helper to centralize regexps for usual data validations. + * @category MyEic + * @subcategory Helpers + */ +app.helpers.validators = { + validators : class { + /*********************** All Regexp (for eventual direct use **********************/ + static mailRFC5322Regex = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/ + static mustacheTokenRegex = new RegExp(/\{\{([\w\-\.\^\#\/]+)\}\}/,'gm') + + + + /*********************** All validators **********************/ + static isValidEmail(text){ + return(text.match(this.mailRFC5322Regex)) + } + + static isValidMustacheToken(text){ + return(text.match(this.mustacheTokenRegex)) + } + } +} \ No newline at end of file diff --git a/app/libs/Bus/Chat/ChatModule.js b/app/libs/Bus/Chat/ChatModule.js new file mode 100755 index 0000000..fbbf23f --- /dev/null +++ b/app/libs/Bus/Chat/ChatModule.js @@ -0,0 +1,264 @@ +/** + * @category MyEic + * @subcategory Libraries + */ +class ChatModule{ + + /** + * + * @param {*} appContent + */ + constructor(appContent) { + this.appContent = appContent; + this.unreadChats = {}; + this.chatTargets = {}; + this.onlineUsers = []; + this.recipientId = null; + this.currentHistory = []; + + this.initView(); + + //TODO: inherit API entry_points + // this.APmeta.xxxx + this.APIEntries = { + 'chatTargets' :'/api/chatTargets', + '':'', + + }; + + //TODO: Do this on opening the chat-panel ? => when is it updated ? + this.getConversations() + .then( this.updateChanList.bind(this) ) + .then( this.RequestOnlineUsers.bind(this)); + this.addMsgBusEvents(); + this.RequestUnreadMsgs(); + } + + addMsgBusEvents(){ + app.events.addEvent('MessageBus.Connected', this.RequestUnreadMsgs.bind(this)); + app.events.addEvent('MessageBus.Closed', this.updateUnreadBadge.bind(this)); + app.events.addEvent('MessageBus.NOTIFS', this.updateUnreadBadge.bind(this)); + app.events.addEvent('MessageBus.ISONLINE', this.updateOnlineBadges.bind(this)); + app.events.addEvent('MessageBus.CHANHIST', this.replaceHisto.bind(this)); + app.events.addEvent('MessageBus.CHATMSG', this.recvBus.bind(this)); + } + + RequestUnreadMsgs(){ + return( + app.MessageBus.requestWssGwAction('NOTIFS', null).then( + (payload) => { + this.unreadChats = payload.unreadChats; + //TODO: share the other stuff with friends... (app.something ??) + this.updateUnreadBadge(); + }, + (err)=>{ console.warn('MSGBUS error:',err) }) + ); + } + + RequestOnlineUsers(){ + let usrlist = Object.keys(this.chatTargets.users); + // Request them now + app.MessageBus.requestWssGwAction('ISONLINE', usrlist); + // Watch them + app.MessageBus.requestWssGwAction('WATCHUSERS', usrlist); + } + + getConversations(){ + //TODO use app central fetcher ??? => use fake model like in myUser + return(fetch(this.APIEntries.chatTargets) + .then((response) => response.json())); + } + + recvBus(e){ + let histoDetail = {}; + histoDetail[e.detail.msg.histId] = { + 'msg' : e.detail.msg.msg, + 'sender' : e.detail.msg.sender + }; + this.replaceHisto({ 'detail': histoDetail }); + } + + replaceHisto(e){ + let hids = Object.keys(e.detail); + for(let hid of hids){ // Insert without creating dups + if(!(hid in this.currentHistory)) this.currentHistory[hid] = e.detail[hid]; + } + let html = ''; let day = ''; + let user, acro, dat, timestp; + for(let hid of Object.keys(this.currentHistory).sort()){ + user = this.chatTargets.users[this.currentHistory[hid].sender]; + acro = user.given_name[0].toUpperCase()+'. '+user.family_name; + dat = new Date(1*hid.substring(0,hid.indexOf('-'))); + timestp = dat.toLocaleString('fr').replace('/'+new Date().getFullYear(),''); // hide current year + if((day != '') && (day != dat.getDate())) { + html += `
${(dat.getDate()==(new Date()).getDate())?'(today)':''}
`; + } + html += `
+ ${acro} (${timestp})
+ ${this.currentHistory[hid].msg.replace(/\n/g, '
')} +

`; + day = dat.getDate(); + } + this.chatView.el.querySelector('.history').innerHTML = html; + this.chatView.el.querySelector('.history').scrollTop = this.chatView.el.querySelector('.history').scrollHeight; + } + + updateChanList(chatTargets){ + this.chatTargets = chatTargets; + for(var uid in chatTargets.users){ + if(uid != app.currentUser.userInfo.sub){ + this.addUserChannel(uid, chatTargets.users[uid]); + } + } + for(var chid in chatTargets.lobbies){ + this.addLobbyChannel(chid, chatTargets.lobbies[chid]); + } + } + + addUserChannel(uid, user) { + let acro = user.given_name[0].toUpperCase()+'. '+user.family_name; + this.chanlist.addRow('P:'+uid, [ '', acro ]); + } + + addLobbyChannel(chid, lobby) { + this.chanlist.addRow('C:'+chid, [ '', lobby.name]); + } + + initView() { + this.chatView = { + el: null, + channels: [], + active: false, + currentChannel: null + }; + this.chatView.el = new DropDown(ui.create(` +
+ + +
  • +
    +
    +
    Lobby name...
    +
    + + +
    +
  • +
    +
    + `)).el; + ui.eicfy(this.chatView.el); + this.appContent.find('header .eic-session').prepend(this.chatView.el); + this.chanlist = new DataGrid(this.appContent.find('.chanlist'), { + headers: [ + {label: '', sortable:true }, + {label: 'name', filter: 'text', sortable:true}, + ], + height: '350px', + }); + this.chanlist.onRowClick= this.selectChan.bind(this); + this.chatView.el.querySelector('.send').addEventListener('click', this.onSendMessage.bind(this)); + this.chatView.el.querySelector('.message').addEventListener("keyup", this.onKeyUp.bind(this)); + this.updateUnreadBadge(); + this.chatView.tab = new Tab(); + } + + onKeyUp(event) { + if(this.aftertypeTo) clearTimeout(this.aftertypeTo); + if(event.which == 13 && !event.shiftKey) { + this.onSendMessage(event); + return + } + this.aftertypeTo = setTimeout(() => { + this.chatView.el.querySelector('.message').value = this.emotiAscii2Utf(this.chatView.el.querySelector('.message').value); + }, 900); + } + + emotiAscii2Utf(txt) { + let conv = { + ':-)':'🙂',':)':'🙂',';-)':'😉',';)':'😉',':-D':'😄','x-D':'😂',':-P':'😛', + ':P':'😛',':-|':'😑',':|':'😑',':-(':'🙁',':(':'🙁',":'-)":'😂',":')":'😂', + ":'-(":'😢',":'(":'😢','>:(':'😠','>:[':'😡',':-*':'😘',':*':'😘','O:-)':'😇', + 'O:)':'😇',':-J':'😏' + } + for(let emoasci of Object.keys(conv)) { + if(emoasci == txt.substring(txt.length-emoasci.length)){ + return(txt.substring(0,txt.length-emoasci.length)+conv[emoasci]); + } + } + return(txt); + } + + selectChan(e){ + let rawid = e.currentTarget.dataset.id; + if((rawid[0]!='P') && (rawid[0]!='C')) return; + this.recipientId = rawid; + for(let el of this.chatView.el.querySelectorAll(`.chanlist li.row`)){ + el.style.backgroundColor = ''; + el.style.color = ''; + } + e.currentTarget.style.backgroundColor = 'var(--eicui-app-toolbar-bg-color)'; + e.currentTarget.style.color = 'var(--eicui-base-color-white)'; + this.currentHistory = {}; + let realRecipientId = rawid.substring(2); + let lobbyname; + if(this.recipientId[0]=='P') { + lobbyname = this.chatTargets.users[realRecipientId].given_name+' '+this.chatTargets.users[realRecipientId].family_name + } else if(this.recipientId[0]=='C') { + lobbyname = this.chatTargets.lobbies[realRecipientId].name; + } + this.chatView.el.querySelector('.lobbyname').innerHTML = lobbyname; + app.MessageBus.requestWssGwAction('STARTCHAT', this.recipientId); + app.MessageBus.requestWssGwAction('CHANHIST', this.recipientId); + } + + onSendMessage(e){ + let txt = this.chatView.el.querySelector('.message').value; + app.MessageBus.requestWssGwAction('SENDCHAT', { + 'recipient' : this.recipientId, + 'msg': txt + }) + this.chatView.el.querySelector('.message').value = ''; + } + + updateUnreadBadge(){ + //updateUnreadBadge is decoupled from the msgbus via nbUnreadMsgs so you can redraw the UI anytime, not depending on a msgbus request + let totUnRead = 0; + for(let chan in this.unreadChats) totUnRead += this.unreadChats[chan]; + + if(!app.MessageBus.connected) { + this.chatView.el.querySelector('button.chat-menu').innerHTML = ``; + } else if(totUnRead>0) { + this.chatView.el.querySelector('button.chat-menu').innerHTML = `${totUnRead}`; + } else { + this.chatView.el.querySelector('button.chat-menu').innerHTML = ''; + } + } + + updateOnlineBadges(event){ + this.onlineUsers = event.detail; + let el; + for(el of this.chatView.el.querySelectorAll(`.eic-chat .userled`)){ + el.removeAttribute('success'); + el.setAttribute('danger',''); + } + for(let uid of this.onlineUsers){ + el = this.chatView.el.querySelector(`[data-id="P:${uid}"] .userled`); + if(el) { + el.removeAttribute('danger'); + el.setAttribute('success',''); + } + } + } + +} + +app.registerClass('ChatModule', ChatModule); + + +//TODOs +// Lobbies +// Return to send, shift-return to CRLF +// Limit displayed / requested history +// Store my read / unread msg => real unread notifs +// Smileys diff --git a/app/libs/Bus/Chat/NotoColorEmoji.ttf b/app/libs/Bus/Chat/NotoColorEmoji.ttf new file mode 100755 index 0000000..ef7b725 Binary files /dev/null and b/app/libs/Bus/Chat/NotoColorEmoji.ttf differ diff --git a/app/libs/Bus/Chat/chat.css b/app/libs/Bus/Chat/chat.css new file mode 100755 index 0000000..e29c263 --- /dev/null +++ b/app/libs/Bus/Chat/chat.css @@ -0,0 +1,168 @@ +@font-face { + font-family: 'NotoColorEmoji'; + src: url('NotoColorEmoji.ttf') format('truetype'); +} + +.eic-chat { + min-width: 50vw; + padding: var(--eicui-base-spacing-m) !important; +} +.eic-chat section .conversations > div > div { + display: grid; + grid-gap: 10px; + grid-template-rows: auto min-content min-content; +} +.eic-chat .status { + float: right; + color: var(--eicui-base-color-white); + display: grid; + width: 24px; + height: 24px; + background: var(--eicui-base-color-danger-100); + border-radius: 24px; + font-size: 1rem; + align-content: center; + justify-content: center; +} +.eic-chat .status.active { + background: var(--eicui-base-color-success-100); +} + + +.eic-chat .chanlist { + width: 250px; + font-size: .8em; + border: 1px solid #ccc; + border-radius: 5px; + min-height:350px; + padding: 5px; + grid-area: chanlist; +} +.eic-chat .history{ + grid-area: history; + border: 1px solid #ccc; + border-radius: 5px; + min-height: 300px; + width:100%; + text-transform: none; + max-height: 500px; + overflow: scroll; +} +.eic-chat .lobbyname { + grid-area: lobbyname; + background-color: var(--eicui-app-toolbar-bg-color); + color: var(--eicui-base-color-white); + padding: 5px; + text-transform: none; +} +.eic-chat .history .histo-entry{ + font-family: sans-serif, 'NotoColorEmoji' !important; + background-color: #E8E8FF; + border-radius: 5px; + margin: 2px 5px; + padding: 2px 5px; + display: inline-block; + max-width: 500px; + float: left; + clear: both; +} +.eic-chat .history .day-separator{ + clear: both; + height: 0; + border: 0px none transparent; + border-top: 2px dotted #777; + text-align: center; + line-height: 17px; + font-size: smaller; +} +.eic-chat .history .histo-entry.me{ + float: right; + background-color: #D9F2D7; +} +.eic-chat .history .histo-entry .sender{ + display: inline-block; + font-size: .85em; + font-weight: bold; + background-color: var(--eicui-app-toolbar-bg-color); + color: #FFF; + padding: 0 2px 2px 2px; + border-radius: 5px; + font-family: monospace; +} +.eic-chat .message{ + grid-area: message; + width:550px; + font-family: sans-serif, 'NotoColorEmoji' !important; +} +.eic-chat .send{ + grid-area: send; +} + + +.eic-chat { + display:grid; + grid-template-areas: + 'chanlist lobbyname lobbyname' + 'chanlist history history' + 'chanlist message send'; +} +.eic-chat .chanlist li.row{ + grid-template-columns: 15px 2fr; +} + +.eic-chat .chanlist span.userled{ + position: absolute; + left: 5px; + height: calc(var(--eicui-base-spacing-s)*.8); + min-width: calc(var(--eicui-base-spacing-s)*.8); + border: 1px outset #aaa; +} +.eic-chat .chanlist span.lobbyled{ + position: absolute; + left: 5px; + height: calc(var(--eicui-base-spacing-s)*.8); + min-width: calc(var(--eicui-base-spacing-s)*.8); + border: 2px outset #00A; +} + +.eic-chat .output { + overflow-y: auto; + height: 350px; + background-color: var(--eicui-base-color-white); + width: 100%; + border: 1px solid var(--eicui-base-color-grey); + padding: 10px; + font-size: 0.8rem; +} +.eic-chat .output .emitter { + color: var(--eicui-base-color-primary); + padding-right: 4px; +} + +.eic-chat .cols-2.form { + height: 60px; + align-items: flex-end; +} +.eic-chat .cols-2.form textarea { + resize: none; +} +.eic-chat .lobby { + display: grid; + grid-gap: var(--eicui-base-spacing-m); +} +#subchalst{ + margin: 0 0 0 0; + padding: 0 0 0 5px; +} +#subchalst li{ + font-size:12px; +} +.eic-chat .subscriptions, +.eic-chat .onlineusers{ + min-width: 300px; +} + +.eic-chat .subscriptions label, +.eic-chat .onlineusers label{ + font-weight:bold; +} \ No newline at end of file diff --git a/app/libs/Bus/rendezVous/MBRendezVous.js b/app/libs/Bus/rendezVous/MBRendezVous.js new file mode 100644 index 0000000..947aa62 --- /dev/null +++ b/app/libs/Bus/rendezVous/MBRendezVous.js @@ -0,0 +1,90 @@ +'use strict' +/** + * @category MyEic + * @subcategory Libraries + */ +class MBRendezVous { + + /** + * + * @param {*} appctrl + */ + constructor(appctrl){ + if(!app.MessageBus) return + this.activeMeetChans = {} + this.myUserNotifChan = app.config.messageBus.userNotifChan.replace(/\{uid\}/g, app.User.identity.uuid) + app.MessageBus.addBusListener( + 'rendezVous', + [ this.myUserNotifChan ], + this.onRendezVousRequest.bind(this) + ) + } + + /** + * + * @param {*} chan + * @param {*} payload + * @param {*} sender + */ + async onRendezVousRequest(chan, payload, sender){ + if(! await this.userConfirmation(sender, payload.userMessage)) return + let rdvzchan = payload.chanPrefix + crypto.randomUUID() + //this.activeMeetChans[] = chan + } + + /** + * + * @param {*} sender + * @param {*} userMessage + */ + async userConfirmation(sender, userMessage){ + let options = { + title: 'Connexion request', + message: `

    The user ${sender} invites you to ${userMessage}.

    + `, + cancelLabel: 'Refuse', + okLabel: 'Accept', + severity: 'danger', + okPromise: () => new Promise((ok,ko)=>ok()) + } + await this.mainCtrl.loadContent('templates/dialogs/ConfirmDialog', options, options) + /* + let result = await this.mainView.confirmDialog({ + title: 'Connexion request', + message: `

    The user ${sender} invites you to ${userMessage}.

    + `, + cancelLabel: 'Refuse', + okLabel: 'Accept', + severity: 'danger', + okPromise: () => new Promise((ok,ko)=>ok()) + }) + + if(result) { + console.log('you said YES') + } + */ + } + + /** + * + * @param {*} hisUid + * @param {*} userMessage + * @param {*} timeout + * @returns {Promise} + */ + getRendezVousChan(hisUid, userMessage, timeout){ + if(!app.MessageBus) return( + + new Promise((resolve, reject) => reject('Cannot rendez-vous without messageBus !')) + ) + + return( + new Promise((resolve, reject) => { + + }) + ) + } + +} + +app.registerClass('MBRendezVous', MBRendezVous); \ No newline at end of file diff --git a/app/libs/EIC/EICBusModel.js b/app/libs/EIC/EICBusModel.js new file mode 100644 index 0000000..c0f439a --- /dev/null +++ b/app/libs/EIC/EICBusModel.js @@ -0,0 +1,51 @@ +/** + * @category MyEic + * @subcategory Libraries + * @extends EICModel + */ +class EICBusModel extends EICModel{ + + + /** + * Makes a request to WSSGateway + */ + busWssGwRequest(action, payload = {}){ + if(!app.MessageBus) return(new Promise((ok, ko) => ko)) + if(!app.MessageBus.connected){ // bus not connected => Queue until connected, with 20 sec timeout + return( + app.MessageBus.whenConnectedP(20000).then(()=>{ + return(app.MessageBus.requestWssGwAction(action, payload)) + }, + ()=>{ + console.log('Timeout waiting for connection !') + }) + ) + } + return(app.MessageBus.requestWssGwAction(action, payload)) + } + + /** + * Makes an action request on the bus + */ + busActionRequest(chan, action, payload = {}){ + if(!app.MessageBus) return(new Promise((ok, ko) => ko)) + if(!app.MessageBus.connected){ // bus not connected => Queue until connected, with 20 sec timeout + return( + app.MessageBus.whenConnectedP(20000).then(()=>{ + return(app.MessageBus.requestBusAction(chan, action, payload)) + }, + ()=>{ + console.log('Timeout waiting for connection !') + }) + ) + } + return(app.MessageBus.requestBusAction(chan, action, payload)) + } + + busEvent(chan, event, payload) { + if( (!app.MessageBus) || (!app.MessageBus.connected) ) return(new Promise((ok, ko) => ko)) + app.MessageBus.sendEvent(chan, event, payload) + } +} + +app.registerClass('EICBusModel', EICBusModel) diff --git a/app/libs/EIC/EICController.js b/app/libs/EIC/EICController.js new file mode 100755 index 0000000..c99104a --- /dev/null +++ b/app/libs/EIC/EICController.js @@ -0,0 +1,347 @@ +/** + * @category MyEic + * @subcategory Libraries + * @extends Controller + */ +class EICController extends Controller { + + constructor() { + super(); + this.view2url = {}; + } + + getViewByClass(className) { + let content = Controller._contents.find(o => o.view._className == className) + return content ? content.view: null; + } + + getViewByURL(url) { + let content = Controller._contents.find(o => o.view._url == url) + return content ? content.view: null; + } + + loadContent(name, options, data) { + options = options || {}; + options.onContentLoaded = this.createContent; + return super.loadView(name, options, data); + } + + createContent(options, data, html) { + + let container = ui.create('
    '); + container.innerHTML = Controller.processTemplate(options.name, html, data); + + let view = new app.LoadedClasses[options.className](options); + view._className = options.name.replace('.html', ''); + view._controller = this; + view.el = container; + view.DOMContentLoaded(data); + + container.setAttribute('sparc-id', view._sparcId); + + return view; + } + + loadWindow(name, options, data) { + let url = app.Router.currentRoute.realUrl; + options = options || {}; + // if static, redirect to existing instance + if(options.static) { + /* + MFA: + Using stored real url instead of classname allows different instance of window based on parameter: + eg: + having route "/window/{id}", calling "/window/345" won't replace "/window/123" + + Makes me wonder: shouldn't all windows be static anyway then ? + */ + //let existing = this.getViewByClass(name); + let existing = this.getViewByURL(url); + + if(existing) { + this.focus(existing._sparcId, data); + return; + } + } + options.onContentLoaded = this.createWindow; + super.loadView(name, options, data).then( + view => { + this.view2url[view._sparcId] = url; + view._url = url + } + ); + } + + createWindow(options, data, html) { + + if(!(options.className in app.LoadedClasses)){ + console.error(`Missing view ${options.className} !\nLoad explicitely it from your controller, or as set it as a dependency...`); + return null; + } + + let view = new app.LoadedClasses[options.className](); + view._className = options.name.replace('.html', ''); + view._controller = this; + + Controller._contents.push({ + view: view, + type: 'window', + expanded: options.expanded || false, + visible: true, + active: false + }); + + let content = ui.create(`
    +
    +

    ${options.title || ''}

    +
    + + + +
    +
    +
    +
    `); + if(options.expanded) content.setAttribute('expanded',''); + + let container = content.querySelector('section'); + container.innerHTML = Controller.processTemplate(options.name, html, data); + + view.el = content; + + // setting up window controls + let expand = content.querySelector('header button.expand'); + expand.addEventListener('click', view.expand.bind(view)); + + let shrink = content.querySelector('header button.shrink'); + shrink.addEventListener('click', view.shrink.bind(view)); + + let close = content.querySelector('header button.close'); + close.addEventListener('click', this.onclose.bind(this)); + + content.addEventListener('click', this.onFocusRequest.bind(this)); + content.addEventListener('expanded', this.onFocusRequest.bind(this)); + content.addEventListener('shrinked', this.onFocusRequest.bind(this)); + + content.setAttribute('sparc-id', view._sparcId); + + let parent = Controller._template.view.find('.app-workspace'); + parent.appendChild(content); + + this.addThesaurus(view._sparcId, options.title || 'a window') + + view.DOMContentLoaded(data); + view.initWindowEvents(); + this.focus(view._sparcId); + + return view; + } + + openDialog(view) { + + let promise = new Promise(function(resolve) { + if(typeof view === 'string') { + let message = view; + view = new EICDialogContent(); + view.el = message; + } + + let dialog = EICController.createDialog(view); + + function commit(result) { + EICController.closeDialog(view._sparcId); + resolve(result); + } + + function abort(result) { + EICController.closeDialog(view._sparcId); + resolve(result); + } + + view.commit = commit; + view.abort = abort; + view.buttons.forEach(function(button) { + dialog.querySelector('[eicdialog] > [eiccard] > footer').append(button.el); + }); + + view.DOMContentFocused(); + }); + + return promise; + } + + /** + * Used by a view that needs to change the current URL + * Typically happens when the view allows you to switch to another instance of the business-object + * handled by this controiller. Doinbg a history.replaceState in the view is not enough, because + * the controller needs to keep track of his current URL (in view2url) for changing + * the Browser URL bar when -later- changing window focus. + * @param {string} newUrl + */ + changeUrl(view, newUrl) { + history.replaceState(null, null, newUrl) + this.view2url[view._sparcId] = newUrl + view._url = newUrl + } + + static createDialog(dialog, options) { + + options = options || {}; + + let container = ui.create(`
    +
    + ${ dialog.options.title ? `

    ${dialog.options.title}

    ${dialog.options.subtitle ? `

    ${dialog.options.subtitle}

    `: '' }
    `: ''} +
    +
    +
    +
    `); + + ui.eicfy(container); + + container.querySelector('[eiccard] section').append(dialog.el); + dialog.parentContainer = container; + + document.body.append(container) + + return container; + } + + static closeDialog(id) { document.body.querySelector(`[sparc-id="${id}"]`).remove(); } + + addThesaurus(id, title) { + let container = Controller._template.view.find('.app-content-thesaurus'); + container.querySelectorAll('[eicchip]').forEach(el => el.setAttribute('secondary', '')) + + let chip = new Chip(null, {label: title, destroyable: true}); + chip.el.setAttribute('data-id', id); + chip.addEventListener('click', this.onSelectThesaurus.bind(this)); + chip.addEventListener('destroy', this.onRemoveThesaurus.bind(this)); + + container.append(chip.el); + } + + removeThesaurus(id) { + let container = Controller._template.view.find('.app-content-thesaurus'); + + let chip = container.querySelector(`[data-id="${id}"]`) + if(chip) chip.remove(); + + let remaining = container.querySelectorAll('[eicchip]'); + + if(remaining.length > 0) { + remaining.item(remaining.length - 1).dispatchEvent(new MouseEvent('click')); + } + } + + close(id) { + this.removeThesaurus(id); + this.unloadView(Controller.getContentById(id)); + if(this.view2url.hasOwnProperty(id)) delete(this.view2url[id]); + } + + focus(id, data) { + this.selectThesaurus(id); + let curUrl = new URL(document.location.href).pathname + if(this.view2url.hasOwnProperty(id)) { + history.replaceState(null, null, this.view2url[id]); + curUrl = this.view2url[id] + } + + if(app.matomo) app.matomo.logAction('Focus window / '+curUrl) + + let next = Controller.getContentById(id); + + if(Controller._currentContent) { + if(next.expanded) { + this.blur(Controller._currentContent); + Controller._contents.filter(item => item.type == 'window').forEach(item => this.desactivate(item)); + Controller._contents.filter(item => !item.expanded).forEach(item => this.blur(item)); + } else { + Controller._contents.filter(item => !item.expanded && item.type == 'window').forEach(item => this.attach(item)); + this.attach(Controller._currentContent); + + let altexpand = Controller._contents.filter(item => item.expanded && item.visible && item.type == 'window'); + + if(altexpand.length == 0) { + let latest = Controller._contents.reverse().find(item => item.expanded); + if(latest) { this.attach(latest); } + } + } + } + Controller._currentContent = next; + this.activate(Controller._currentContent, data); + Controller._currentContent.view.DOMContentResized(); + } + + desactivate(content) { + content.view.el.classList.remove('active'); + content.active = false; + if(content.expanded) this.blur(content); + } + + activate(content, data) { + Controller._contents.forEach(o => o.active = false); + Controller._contents.forEach(o => o.view.el.classList.remove('active')); + content.view.el.classList.add('active'); + content.active = true; + + if(!content.visible) this.attach(content); + + content.view.DOMContentFocused(data); + } + + attach(content) { + ui.show(content.view.el,!content.expanded ? 'grid': 'block'); + content.visible = true; + } + + blur(content) { + ui.hide(content.view.el); + content.visible = false; + content.active = false; + content.view.DOMContentBlured(); + } + + onclose(event) { + event.preventDefault(); + event.stopPropagation(); + + this.close(event.currentTarget.dataset.id) + } + + onSelectThesaurus(event) { + event.stopPropagation(); + event.preventDefault(); + + this.focus(event.currentTarget.dataset.id); + } + + selectThesaurus(id) { + let container = Controller._template.view.find('.app-content-thesaurus'); + container.querySelectorAll('[eicchip]').forEach(el => el.setAttribute('secondary', '')) + container.querySelector(`[eicchip][data-id="${id}"]`).removeAttribute('secondary'); + } + onRemoveThesaurus(event) { + event.stopPropagation(); + event.preventDefault(); + + this.close(event.currentTarget.dataset.id); + } + + onFocusRequest(event) { + + let view = event.currentTarget; + while(!view.hasAttribute('sparc-id') && !view.classList.contains('window')) view = view.parentElement; + let content = Controller.getContentById(view.getAttribute('sparc-id')); + if(!content.active || content.expanded != content.view.expanded || (Controller._currentContent.view._sparcId != content.view._sparcId)) { + content.expanded = content.view.expanded; + this.focus(view.getAttribute('sparc-id')); + } + } + + static resize() { + Controller._contents.forEach(item => item.view.DOMContentResized()) + } +} + +app.registerClass('EICController', EICController); \ No newline at end of file diff --git a/app/libs/EIC/EICDialogContent.js b/app/libs/EIC/EICDialogContent.js new file mode 100755 index 0000000..ed6c781 --- /dev/null +++ b/app/libs/EIC/EICDialogContent.js @@ -0,0 +1,76 @@ +/** + * @category MyEic + * @subcategory Libraries + * @extends View + */ +class EICDialogContent extends View { + + icon = null; + + actions = [ + { + label: 'Cancel', + onclick: this.cancel.bind(this), + severity: 'secondary' + }, + { + label: 'OK', + onclick: this.accept.bind(this), + severity: 'primary' + } + ] + + constructor(options) { + super(options); + this.options = options || {}; + window.addEventListener('resize', this.DOMContentResized.bind(this)); + } + + DOMContentLoaded(options) { + + } + + get buttons() { + let list = []; + for(let descriptor of this.actions) { + if(!descriptor.button) { + let button = new Button(ui.create(`