-
+ |
ids.includes(suggestion.id || ''));
- console.log(`suggestions ${suggestions}`);
- const add: Suggestion[] = [];
- const remove: Suggestion[] = [];
- for (const suggestion of suggestions) {
- if (suggestion.action === 'add') {
- add.push(suggestion);
- } else if (suggestion.action === 'remove') {
- remove.push(suggestion);
- }
- }
+ const add: Suggestion[] = suggestions.filter((s) => s.action === 'add');
+ const remove: Suggestion[] = suggestions.filter((s) => s.action === 'remove');
await store.changeRoutes(add, remove);
return Promise.reject({redirect: {name: 'cas', params: {ca: store.ca}}});
}
@@ -71,8 +77,10 @@ export default async function handleCaData(toState: State, store: Store) {
// only fetch details on cas route
if (toState.name.startsWith('cas')) {
// load ca details and roa's
- await store.loadCa();
- await store.loadRepoStatus();
- await store.loadParents();
+ await Promise.all([
+ store.loadCa(),
+ store.loadParents(),
+ store.loadRepoStatus(),
+ ]);
}
}
diff --git a/src/core/handlers/handleLoginRouting.ts b/src/core/handlers/handleLoginRouting.ts
index 7a5ad6f..23cf274 100644
--- a/src/core/handlers/handleLoginRouting.ts
+++ b/src/core/handlers/handleLoginRouting.ts
@@ -9,13 +9,6 @@ export default async function handleLoginRouting(toState: State, store: Store) {
delete toState.params.password;
}
- // clear notification
- if (toState.params.notification === 'clear') {
- store.setNotification(null);
- delete toState.params.notification;
- return Promise.reject({ redirect: toState});
- }
-
// logout (set token to null) and redirect to login
if (toState.name === 'logout') {
store.setToken(null);
diff --git a/src/core/router.ts b/src/core/router.ts
index ba5fa35..09405a7 100644
--- a/src/core/router.ts
+++ b/src/core/router.ts
@@ -10,6 +10,7 @@ const routes = [
{ name: 'cas', path: `${prefix}/cas/:ca`, children: [
{ name: 'add_new', path: '/add' },
{ name: 'add', path: '/add/:id' },
+ { name: 'edit', path: '/edit/:id' },
{ name: 'delete', path: '/delete/:id' },
{ name: 'change', path: '/change'},
{ name: 'parents', path: '/parents', children: [
diff --git a/src/core/store.ts b/src/core/store.ts
index c4f587a..b552a49 100644
--- a/src/core/store.ts
+++ b/src/core/store.ts
@@ -220,17 +220,25 @@ export default class Store implements Data {
await this.handleError(async () => {
if (this.ca !== null) {
- const [caDetails, roas, suggestions] = await Promise.all([
+ const [caDetails, roas] = await Promise.all([
this.api.getCaDetails(this.ca),
this.api.getCaRoas(this.ca),
- this.api.getCaSuggestions(this.ca),
- this.api.getCaParents(this.ca),
- this.api.getCaRepoStatus(this.ca),
]);
this.caDetails[this.ca] = caDetails;
this.roas[this.ca] = roas;
- this.suggestions[this.ca] = suggestions;
+ }
+ });
+ }
+
+ async loadSuggestions(force?: boolean) {
+ if (!this.ca || (this.ca && this.suggestions[this.ca] && force !== true)) {
+ return;
+ }
+
+ await this.handleError(async () => {
+ if (this.ca !== null) {
+ this.suggestions[this.ca] = await this.api.getCaSuggestions(this.ca);
}
});
}
@@ -270,6 +278,7 @@ export default class Store implements Data {
removed: remove,
});
await this.loadCa(true);
+ await this.loadSuggestions(true);
this.setNotification({
type: NotificationType.success,
message: this.translations?.common.success,
@@ -278,6 +287,36 @@ export default class Store implements Data {
});
}
+ async editRoute(id: string, comment: string): Promise {
+ if (this.ca === null || !this.roas[this.ca]) {
+ return false;
+ }
+
+ const route = this.roas[this.ca].find((r) => r.id === id);
+
+ if (!route) {
+ return false;
+ }
+
+ const updatedRoute: Route = {
+ ...route,
+ comment,
+ };
+
+ return await this.handleError(async () => {
+ await this.api.updateRoutes(this.ca as string, {
+ added: [updatedRoute],
+ removed: [],
+ });
+ await this.loadCa(true);
+ this.setNotification({
+ type: NotificationType.success,
+ message: this.translations?.caDetails.confirmation.commentUpdatedSuccess,
+ });
+ return true;
+ });
+ }
+
async addRoute(params: RouteParams): Promise {
if (this.ca === null) {
return false;
diff --git a/src/core/translations.ts b/src/core/translations.ts
index 3adce3c..56a71b4 100644
--- a/src/core/translations.ts
+++ b/src/core/translations.ts
@@ -101,6 +101,7 @@ export interface Translations {
retired: string,
retiredSuccess: string,
addedSuccess: string,
+ commentUpdatedSuccess: string,
},
addROAForm: {
required: string,
@@ -108,6 +109,7 @@ export interface Translations {
prefix_format: string,
},
onboardingWarning: string,
+ initializeRepository: string,
initialize: string,
noResourcesYet: string,
clickToRefresh: string,
diff --git a/src/core/utils.ts b/src/core/utils.ts
index 7b8504c..a3fa572 100644
--- a/src/core/utils.ts
+++ b/src/core/utils.ts
@@ -45,7 +45,18 @@ export function prefixMaxLength(prefix: string | undefined): string {
}
export function formatDate(seconds: number, locale: string) {
- return new Date(seconds * 1000).toLocaleString(locale, { dateStyle: 'long', timeStyle: 'medium' });
+ return new Date(seconds * 1000).toLocaleString(locale, {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ second: 'numeric',
+ hour12: false,
+ timeZone: 'UTC',
+ timeZoneName: 'short',
+ });
}
export function isAbsolute(url: string): boolean {
diff --git a/src/css/button.css b/src/css/button.css
index 42249ff..8968982 100644
--- a/src/css/button.css
+++ b/src/css/button.css
@@ -19,6 +19,11 @@
border: 1px solid var(--grey-dark);
}
+.button.light {
+ color: var(--dark);
+ background: white;
+}
+
.button:hover {
opacity: 0.8;
}
diff --git a/src/css/form.css b/src/css/form.css
index 805e011..edb36ab 100644
--- a/src/css/form.css
+++ b/src/css/form.css
@@ -57,3 +57,12 @@ input::placeholder {
#upload {
display: none;
}
+
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+}
+
+input[type=number] {
+ -moz-appearance: textfield;
+}
diff --git a/src/img/edit.svg b/src/img/edit.svg
new file mode 100644
index 0000000..18aec4c
--- /dev/null
+++ b/src/img/edit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/locales/de.ts b/src/locales/de.ts
index ca04672..cfa4376 100644
--- a/src/locales/de.ts
+++ b/src/locales/de.ts
@@ -89,7 +89,9 @@ export const translations: Translations = {
'added': 'ROA hinzugefügt',
'retired': 'ROA entfernt',
'retiredSuccess': 'Das ROA wurde entfernt',
- 'addedSuccess': 'Das ROA wurde hinzugefügt'
+ 'addedSuccess': 'Das ROA wurde hinzugefügt',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Dies ist ein Pflichtfeld',
@@ -97,6 +99,8 @@ export const translations: Translations = {
'prefix_format': 'Bitte geben Sie ein gültiges IPv4 oder IPv6 Präfix ein'
},
'onboardingWarning': 'Um Ihr Zertifikat und Ihre ROAs zu veröffentlichen müssen Sie Ihre Zertifizierungsstelle mit einer öffentlichen RPKI Datenbank (Repository) verbinden. Sobald die Konfiguration der Eltern-Zertifizierungsstelle abgeschlossen ist, wird die Relying Party Software mit dem Herunterladen Ihres Zertifikates sowie Ihrer ROAs, welche in dieser Datenbank veröffentlicht wurden, beginnen.',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Bitte initialisieren Sie die RPKI Datenbank (Repository) und/oder die Eltern-Zertifizierungsstelle zuerst.',
'noResourcesYet': 'Sie haben noch keine Ressourcen erhalten',
'clickToRefresh': 'Klicken Sie hier um neu zu laden',
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 9480c19..e6c4160 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -88,7 +88,8 @@ export const translations: Translations = {
'added': 'ROA added',
'retired': 'ROA removed',
'retiredSuccess': 'The ROA has been removed',
- 'addedSuccess': 'The ROA has been added'
+ 'addedSuccess': 'The ROA has been added',
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'This field is required',
@@ -96,6 +97,7 @@ export const translations: Translations = {
'prefix_format': 'Please enter a valid IPv4 or IPv6 prefix'
},
'onboardingWarning': 'You will need to connect your CA to a public RPKI repository where it can publish your certificate and ROAs. As soon as the parent configuration is completed, relying party software will immediately start fetching your certificate and the ROAs you create from this repository.',
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Please initialize the RPKI repository and/or the parent first.',
'noResourcesYet': 'You have not received any resources yet',
'clickToRefresh': 'Click here to refresh',
diff --git a/src/locales/es.ts b/src/locales/es.ts
index 2d5e5ef..82b3be8 100644
--- a/src/locales/es.ts
+++ b/src/locales/es.ts
@@ -89,7 +89,9 @@ export const translations: Translations = {
'added': 'ROA agregado',
'retired': 'ROA eliminado',
'retiredSuccess': 'El ROA se ha eliminado',
- 'addedSuccess': 'El ROA se ha agregado'
+ 'addedSuccess': 'El ROA se ha agregado',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Este campo es obligatorio',
@@ -97,6 +99,8 @@ export const translations: Translations = {
'prefix_format': 'Ingrese un prefijo IPv4 o IPv6 válido'
},
'onboardingWarning': 'Deberá conectar su CA a un repositorio RPKI público donde pueda publicar su certificado y sus ROA. Tan pronto como se complete la configuración del padre, el software de validación comenzará a recuperar su certificado y los ROA que cree a partir de este repositorio.',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Primero inicialice el repositorio RPKI y/o el padre.',
'noResourcesYet': 'Todavía no ha recibido ningún recurso',
'clickToRefresh': 'Haga clic aquí para actualizar',
diff --git a/src/locales/fr.ts b/src/locales/fr.ts
index 1e06b17..fde5bc3 100644
--- a/src/locales/fr.ts
+++ b/src/locales/fr.ts
@@ -90,7 +90,9 @@ export const translations: Translations = {
'added': 'ROA ajouté',
'retired': 'ROA enlevé',
'retiredSuccess': 'Le ROA a été enlevé',
- 'addedSuccess': 'Le ROA a été ajouté'
+ 'addedSuccess': 'Le ROA a été ajouté',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Ce champ est requis',
@@ -98,6 +100,8 @@ export const translations: Translations = {
'prefix_format': 'SVP entrez un préfixe IPv4 ou IPv6 valide'
},
'onboardingWarning': 'Veuillez connecter votre AC à un dépôt RPKI publique pour publier votre certificat et vos ROAs. Dès que la configuration côté parent est complète, le \'relying party\' (logiciel validateur) commencera immédiatement à récupérer votre certificat et les ROAs que vous avez créés depuis ce dépôt.',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'SVP initialisez le dépôt RPKI et/ou le parent en premier lieu.',
'noResourcesYet': 'Vous n\'avez pas encore reçu de ressources',
'clickToRefresh': 'Cliquer ici pour rafraîchir',
diff --git a/src/locales/gr.ts b/src/locales/gr.ts
index e60b90a..7315583 100644
--- a/src/locales/gr.ts
+++ b/src/locales/gr.ts
@@ -89,7 +89,9 @@ export const translations: Translations = {
'added': 'Το ROA προστέθηκε',
'retired': 'Το ROA αφαιρέθηκε',
'retiredSuccess': 'Το ROA έχει αφαιρεθεί',
- 'addedSuccess': 'Το ROA έχει προστεθεί'
+ 'addedSuccess': 'Το ROA έχει προστεθεί',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Το πεδίο είναι υποχρεωτικό',
@@ -97,6 +99,8 @@ export const translations: Translations = {
'prefix_format': 'Παρακαλώ εισάγετε ένα έγκυρο IPv4 ή IPv6 πρόθεμα'
},
'onboardingWarning': 'Θα χρειαστεί να συνδέσετε την Αρχή Πιστοποίησής (CA) σας σε ένα δημόσιο αποθετήριο (repository) RPKI που θα μπορεί να δημοσιεύσει το πιστοποιητικό και τα ROA σας. Με το που ολοκληρωθεί η ρύθμιση του CA-πατέρα, λογισμικά επικύρωσης (relying party) θα αρχίσουν να ανακτούν το πιστοποιητικό και τα ROA σας από αυτό το αποθετήριο (repository).',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Παρακαλώ αρχικοποιήστε ένα αποθετήριο (repository) RPKI και/ή τον CA-γονέα πρώτα.',
'noResourcesYet': 'Δεν έχετε λάβει κανέναν πόρο ακόμα',
'clickToRefresh': 'Κάντε κλίκ εδώ για ανανέωση',
diff --git a/src/locales/nl.ts b/src/locales/nl.ts
index aa1cae3..72e5062 100644
--- a/src/locales/nl.ts
+++ b/src/locales/nl.ts
@@ -89,7 +89,9 @@ export const translations: Translations = {
'added': 'ROA toegevoegd',
'retired': 'ROA verwijderd',
'retiredSuccess': 'De ROA is verwijderd',
- 'addedSuccess': 'The ROA is toegevoegd'
+ 'addedSuccess': 'The ROA is toegevoegd',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Dit veld is verplicht',
@@ -97,6 +99,8 @@ export const translations: Translations = {
'prefix_format': 'Vul alstublieft een geldige IPv4 of IPv6 prefix in'
},
'onboardingWarning': 'Om uw certificaat en ROAs te publiceren moet uw CA verbonden worden met een publieke RPKI databank (repository). Zodra de configuratie met de bovenliggende CA is voltooid, zal software gebruikt door de vertrouwende partijen (RPKI validators) direct beginnen met het downloaden en verifiëren van uw certificaat en ROAs die gepubliceerd zijn in deze databank.',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Initialiseer alstublieft eerst uw RPKI databank (repository) en/of de bovenliggende CA.',
'noResourcesYet': 'U heeft nog geen resources ontvangen',
'clickToRefresh': 'Klik hier om te verversen',
diff --git a/src/locales/pt.ts b/src/locales/pt.ts
index 0481b0b..f35c5c6 100644
--- a/src/locales/pt.ts
+++ b/src/locales/pt.ts
@@ -89,7 +89,9 @@ export const translations: Translations = {
'added': 'ROA adicionada',
'retired': 'ROA removida',
'retiredSuccess': 'A ROA foi removida',
- 'addedSuccess': 'A ROA foi adicionada'
+ 'addedSuccess': 'A ROA foi adicionada',
+ // TODO translate
+ 'commentUpdatedSuccess': 'The ROA comment has been updated',
},
'addROAForm': {
'required': 'Este campo é obrigatório',
@@ -97,6 +99,8 @@ export const translations: Translations = {
'prefix_format': 'Por favor, entre um prefixo IPv4 ou IPv6 válido'
},
'onboardingWarning': 'Você deve conectar sua Autoridade Certificadora (CA) a um repositório RPKI público, onde será possível publicar seu certificado e ROAs. Assim que a configuração com a CA-pai for finalizada, imediatamente os softwares de validação (\'relying parties\') terão acesso aos certificado(s) e ROA(s) criados neste repositório.',
+ // TODO translate
+ 'initializeRepository': 'You still need to configure a repository for your CA before it can request resource certificate(s) from its parent(s)',
'initialize': 'Por favor, initialize o repositório RPKI e/ou Pai primeiro.',
'noResourcesYet': 'Você ainda não recebeu nenhum recurso',
'clickToRefresh': 'Clique aqui para atualizar',
|