diff --git a/myconext-gui/src/components/LinkedAccountSummary.svelte b/myconext-gui/src/components/LinkedAccountSummary.svelte
new file mode 100644
index 00000000..b62d9ffd
--- /dev/null
+++ b/myconext-gui/src/components/LinkedAccountSummary.svelte
@@ -0,0 +1,131 @@
+
+
+
+
+
+
{I18n.t("profile.from", {name: institutionName(linkedAccount)})}
+ {@html I18n.t("profile.receivedOnInfo", {date: dateFromEpoch(linkedAccount.createdAt)})}
+ {@html I18n.t("profile.validUntilDateInfo", {date: dateFromEpoch(expiresAt)})}
+
+
+
+
+
+
+
+
+
+
+ {#if linkedAccount.idpScoping !== "idin" && !isEmpty(linkedAccountGivenName(linkedAccount))}
+
+ {/if}
+
+ {#if !isEmpty(linkedAccountFamilyName(linkedAccount))}
+
+ {/if}
+
+ {#if !isEmpty(linkedAccount.dateOfBirth)}
+
+ {/if}
+
+ {#if isStudent(linkedAccount)}
+
+ {/if}
+
+ {#if (linkedAccount.idpScoping === "idin" || isEmpty(linkedAccountGivenName(linkedAccount))) &&
+ isEmpty(linkedAccount.dateOfBirth) && isEmpty(linkedAccountFamilyName(linkedAccount)) &&
+ !isStudent(linkedAccount)}
+ {I18n.t("profile.noValidInformation", {name: institutionName(linkedAccount)})}
+ {/if}
+
+
+
+
+
diff --git a/myconext-gui/src/components/ValidatedData.svelte b/myconext-gui/src/components/ValidatedData.svelte
index c0796eb7..5eb50312 100644
--- a/myconext-gui/src/components/ValidatedData.svelte
+++ b/myconext-gui/src/components/ValidatedData.svelte
@@ -5,9 +5,11 @@
import {user} from "../stores/user";
import {isEmpty} from "../utils/utils";
import {dateFromEpoch} from "../utils/date";
+ import personalInfo from "../icons/verify/personalInfo.svg";
export let institution = {};
export let replacement = false;
+ export let preferredAccount = false;
\ No newline at end of file
diff --git a/myconext-gui/src/locale/en.js b/myconext-gui/src/locale/en.js
index a5dbc1be..898ff1b6 100644
--- a/myconext-gui/src/locale/en.js
+++ b/myconext-gui/src/locale/en.js
@@ -45,7 +45,9 @@ I18n.translations.en = {
verifiedInformationInfo: "This is an overview of the verified information we have received from trusted sources.",
defaultPreferred: "This icon indicates the information is used on 'your personal info' as default.",
receivedOn: "on {{date}}",
+ receivedOnInfo: "Received on {{date}}",
validUntilDate: "valid until {{date}}",
+ validUntilDateInfo: "Valid until {{date}}",
removeLinkPrefix: "Remove this information",
removeLinkPostfix: " from your eduID",
banner: "Some services require that your personal information is validated by a trusted party.",
@@ -89,6 +91,7 @@ I18n.translations.en = {
nonEditable: "Verified by {{name}}",
verifiedBy: "Verified by {{name}}",
validUntil: "Valid until",
+ from: "From {{name}}",
verifyFirstAndLastName: {
addInstitution: "Add institution",
addInstitutionConfirmation: "When you proceed you will be asked to login at the institution you want to link to your eduID. First, select which institution you want to connect; then, login at that institution.
After a successful login you will come back here.",
@@ -108,6 +111,7 @@ I18n.translations.en = {
eppn: "EPPN",
subjectId: "Subject ID",
manageInformation: "Manage your verified information",
+ noValidInformation: "{{name}} has not provided any valid information"
},
eppnAlreadyLinked: {
header: "Connection not added!",
@@ -264,8 +268,8 @@ I18n.translations.en = {
cancel: "Cancel",
deleted: "The connection with your institution {{name}} has been removed",
back: "/institutions",
- deleteInstitution: "Delete institution",
- deleteInstitutionConfirmation: "Are you sure you want to delete the connection with this institution?
Some services require that you your eduID is connected to an institution. You might be prompted to connect an institution if you access one of those services."
+ deleteInstitution: "Delete this information?",
+ deleteInstitutionConfirmation: "Some applications you want to login to with eduID require validated information. By deleting this information you will not be able to login to those applications.
You might be prompted to validate your information again if you want to access them."
},
credential: {
title: "Edit security key",
diff --git a/myconext-gui/src/locale/nl.js b/myconext-gui/src/locale/nl.js
index f675edf0..5ecabc6b 100644
--- a/myconext-gui/src/locale/nl.js
+++ b/myconext-gui/src/locale/nl.js
@@ -44,8 +44,10 @@ I18n.translations.nl = {
verifiedInformation: "Je geverifïeerde informatie",
verifiedInformationInfo: "Dit is een overzicht van de geverifïeerde informatie die we hebben ontvangen van betrouwbare bronnen.",
defaultPreferred: "Dit icon geeft aan dat deze informatie default wordt gebruikt voor 'je persoonlijke informatie'.",
- receivedOn: "Ontvangen op {{date}}",
- validUntilDate: "Geldig tot {{date}}",
+ receivedOn: "op {{date}}",
+ receivedOnInfo: "Ontvangen op {{date}}",
+ validUntilDate: "Geldig tot {{date}}",
+ validUntilDateInfo: "Geldig tot {{date}}",
removeLinkPrefix: "Verwijder deze informatie",
removeLinkPostfix: " uit je eduID",
banner: "Sommige diensten vereisen dat je persoonlijke gegevens worden gevalideerd door een vertrouwde partij.",
@@ -89,6 +91,7 @@ I18n.translations.nl = {
nonEditable: "Geverifiëerd door {{name}}",
verifiedBy: "Geverifiëerd door {{name}}",
validUntil: "Geldig tot",
+ from: "Van {{name}}",
verifyFirstAndLastName: {
addInstitution: "Instelling toevoegen",
addInstitutionConfirmation: "Als je doorgaat word je gevraagd in te loggen via de onderwijsinstelling die je wilt koppelen. Selecteer eerst welke instelling je wilt koppelen en log daarna in.
Nadat je succesvol bent ingelogd kom je hier weer terug.",
@@ -108,6 +111,7 @@ I18n.translations.nl = {
eppn: "EPPN",
subjectId: "Subject ID",
manageInformation: "Manage je geverifïeerde informatie",
+ noValidInformation: "{{name}} heeft geen valide informatie opgeleverd"
},
eppnAlreadyLinked: {
header: "Koppeling niet gemaakt!",
@@ -263,8 +267,8 @@ I18n.translations.nl = {
cancel: "Annuleren",
deleted: "De koppeling met instelling {{name}} is verwijderd",
back: "/instellingen",
- deleteInstitution: "Verwijder koppeling",
- deleteInstitutionConfirmation: "Weet je zeker dat je de koppeling met deze instelling wilt verwijderen?
Sommige diensten vereisen dat je een koppeling hebt met een onderwijsinstelling. Je wordt mogelijk gevraagd een instelling te koppelen als je één van die diensten gebruikt."
+ deleteInstitution: "Verwijder deze informatie",
+ deleteInstitutionConfirmation: "Voor sommige applicaties waarop je wilt inloggen met eduID zijn gevalideerde gegevens nodig. Als je deze gegevens verwijdert, kan je je niet meer aanmelden bij deze toepassingen.
Mogelijk wordt je gevraagd om je gegevens opnieuw te valideren als je er inlogt."
},
credential: {
title: "Bewerk beveiligingssleutel",
diff --git a/myconext-gui/src/routes/PersonalInfo.svelte b/myconext-gui/src/routes/PersonalInfo.svelte
index 496e6b3b..8e85b66a 100644
--- a/myconext-gui/src/routes/PersonalInfo.svelte
+++ b/myconext-gui/src/routes/PersonalInfo.svelte
@@ -26,10 +26,12 @@
import ValidatedData from "../components/ValidatedData.svelte";
import VerifyChoice from "../verify/VerifyChoice.svelte";
import {dateFromEpoch} from "../utils/date";
+ import LinkedAccountSummary from "../components/LinkedAccountSummary.svelte";
let eduIDLinked = false;
let sortedAccounts = [];
+ let sortedExternalAccounts = [];
let preferredAccount = null;
let preferredInstitution = null;
@@ -126,7 +128,7 @@
linkedAccount.expiresAtRole = expiredAt;
linkedAccount.expiredRole = new Date() > linkedAccount.expiresAtRole;
if (isEmpty(linkedAccount.givenName) || isEmpty(linkedAccount.familyName)) {
- linkedAccount.expired = account.expiredRole;
+ linkedAccount.expired = linkedAccount.expiredRole;
linkedAccount.expiresAtNonValidated = linkedAccount.expiresAtRole.getTime();
} else {
linkedAccount.expired = new Date() > new Date(linkedAccount.expiresAt);
@@ -137,6 +139,7 @@
($user.linkedAccounts || []).forEach(account => markExpired(account));
($user.externalLinkedAccounts || []).forEach(account => markExternalLinkedAccountExpired(account));
sortedAccounts = ($user.linkedAccounts || []).sort((a, b) => b.createdAt - a.createdAt);
+ sortedExternalAccounts = ($user.externalLinkedAccounts || []).sort((a, b) => b.createdAt - a.createdAt);
const validLinkedAccounts = sortedAccounts.filter(account => !account.expired);
const validExternalLinkedAccount = !isEmpty($user.externalLinkedAccounts) && !$user.externalLinkedAccounts[0].expired;
const linkedAccount = validLinkedAccounts.find(account => account.preferred) || validLinkedAccounts[0];
@@ -144,15 +147,21 @@
preferredAccount = null;
} else {
preferredAccount = linkedAccount;
+ linkedAccount.preferred = true;
}
if (!isEmpty($user.externalLinkedAccounts)) {
if (isEmpty(preferredAccount) || preferredAccount.createdAt < $user.externalLinkedAccounts[0].createdAt) {
preferredAccount = $user.externalLinkedAccounts[0];
+ $user.externalLinkedAccounts[0].preferred = true;
+ validLinkedAccounts.forEach(acc => acc.preferred = false);
preferredAccount.external = true;
}
}
eduIDLinked = validLinkedAccounts.length > 0 || validExternalLinkedAccount;
+ if (isEmpty($user.linkedAccounts) && isEmpty($user.externalLinkedAccounts)) {
+ showManageVerifiedInformation = false;
+ }
}
const updateChosenName = chosenName => {
@@ -281,6 +290,38 @@
cursor: pointer;
}
}
+
+ .verified-information {
+ max-width: $max-width-not-edit;
+
+ p.info {
+ margin: 25px 0;
+ }
+
+ div.preferred-info {
+ display: flex;
+
+
+ :global(svg) {
+ color: var(--color-primary-green);
+ width: 20px;
+ height: auto;
+ margin: 0 10px auto 0;
+ }
+ }
+
+ div.verified-account {
+ border-top: 1px solid var(--color-primary-grey);
+ margin-top: 25px;
+ padding-top: 25px;
+
+ &:last-child {
+ margin-bottom: 40px;
+ }
+ }
+ }
+
+
.linked-accounts, .add-institution {
max-width: $max-width-not-edit;
}
@@ -416,15 +457,32 @@
{#if showManageVerifiedInformation}
diff --git a/myconext-gui/src/utils/services.js b/myconext-gui/src/utils/services.js
index ca0fee07..0119b8fd 100644
--- a/myconext-gui/src/utils/services.js
+++ b/myconext-gui/src/utils/services.js
@@ -24,3 +24,7 @@ export const linkedAccountGivenName = linkedAccount => {
export const linkedAccountFamilyName = linkedAccount => {
return linkedAccount.external ? linkedAccount.preferredLastName : linkedAccount.familyName;
}
+
+export const isStudent = linkedAccount => {
+ return (linkedAccount.eduPersonAffiliations || []).some(aff => aff.toLowerCase().indexOf("student") > -1);
+}
diff --git a/myconext-gui/src/verify/ValidatedField.svelte b/myconext-gui/src/verify/ValidatedField.svelte
index b9abbafc..77b890ef 100644
--- a/myconext-gui/src/verify/ValidatedField.svelte
+++ b/myconext-gui/src/verify/ValidatedField.svelte
@@ -3,6 +3,8 @@
export let label;
export let value;
+ export let icon;
+ export let overrideShieldIcon;