[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[reclaim-ui] 388/459: significantly simplify identity edit
From: |
gnunet |
Subject: |
[reclaim-ui] 388/459: significantly simplify identity edit |
Date: |
Fri, 11 Jun 2021 23:28:00 +0200 |
This is an automated email from the git hooks/post-receive script.
martin-schanzenbach pushed a commit to branch master
in repository reclaim-ui.
commit 029c279e8f533c3b75a63c4cdb7ac01476d818b3
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Wed Dec 30 13:15:59 2020 +0900
significantly simplify identity edit
---
src/app/edit-identity/edit-identity.component.html | 532 +++++----------------
src/app/edit-identity/edit-identity.component.ts | 240 +++++-----
src/locales/en/messages.json | 9 +-
3 files changed, 231 insertions(+), 550 deletions(-)
diff --git a/src/app/edit-identity/edit-identity.component.html
b/src/app/edit-identity/edit-identity.component.html
index ce72ca3..39cc4f5 100644
--- a/src/app/edit-identity/edit-identity.component.html
+++ b/src/app/edit-identity/edit-identity.component.html
@@ -22,292 +22,155 @@
<!-- Attribute table -->
<div class="card-body" *ngIf="!importInProgress">
<div>
- <h3 class="card-subtitle mb-4">
{{getMessage("edit_identity_html@basicInfo")}} <span (click)="showGeneralInfo =
!showGeneralInfo" class="fa fa-question-circle"></span></h3>
+ <h3 class="mb-2"> {{getMessage("edit_identity_html@addAttributes")}}</h3>
+ <p> {{getMessage("edit_identity_html@addStandardClaim")}} <span
(click)="showGeneralInfo = !showGeneralInfo" class="fa
fa-question-circle"></span></p>
<div class="alert alert-secondary fade show" *ngIf="showGeneralInfo" >
{{getMessage("edit_identity_html@standardScopes")}}
</div>
- <div class="table pb-1">
- <!-- Standard "email" claims first -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingEmailClaims">
- <div class="col-sm">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b>
- </div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div style="flex:1;" *ngIf="claim != claimInEdit">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
- <span *ngIf="isClaimCred(claim) && (claim != claimInEdit)"
>{{ getCredValue(claim) }} <i class="text-primary" style="float:right;"><i
class="fa fa-certificate"></i> {{ getIssuer(claim) }}</i></span>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canUpdateAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button class="btn btn-primary" (click)="editAttribute(claim)"
*ngIf="claim != claimInEdit">
- <span class="fa fa-edit"></span>
- </button>
- <button class="ml-2 btn btn-primary"
(click)="deleteAttribute(claim)">
- <span class="fa fa-trash"></span>
- </button>
- </div>
+ <div class="table pb-1">
+ <!-- Add standard attribute -->
+ <div class="row mb-3"
+ [class.alert-danger]="isInConflict(newStandardAttribute)">
+ <div class="col-sm">
+ <select class="custom-select"
+ [(ngModel)]="newStandardAttribute.name"
+ (change)="newStandardAttribute.name=$event.target.value">
+ <option value="" >{{
getMessage("edit_identity_html@selectAttribute") }}</option>
+ <option *ngFor="let claim of getMissingStandardClaims()"
value={{claim.name}}>
+ {{getDescription(claim)}}
+ </option>
+ </select>
</div>
- <!-- Standard "email" claims missing on the identity -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingEmailClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canAddAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button *ngIf="claim != claimInEdit" class="btn btn-primary"
(click)="editAttribute(claim)">
- <span class="fa fa-plus"></span>
- </button>
+ <div class="col-sm" style="display:flex;">
+ <div style="flex:1;">
+ <input *ngIf="!isClaimCred(newStandardAttribute)"
placeholder="{{ getMessage('Value') }}"
[(ngModel)]="newStandardAttribute.value">
+ <select class="custom-select"
+ *ngIf="newStandardAttribute.credential !== '' &&
isClaimCred(newStandardAttribute)"
(change)="newStandardAttribute.value=$event.target.value">
+ <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
+ <option *ngFor="let claim of
credentialValuesForClaim(newStandardAttribute)" value={{claim.name}}>
+ {{claim.value}} <i>({{claim.name}})</i>
+ </option>
+ </select>
+ </div>
+ <div style="float:right;" *ngIf="credentials.length > 0">
+ <select class="custom-select"
+ [(ngModel)]="newStandardAttribute.credential"
+ (change)="newStandardAttribute.credential=$event.target.value;
newStandardAttribute.flag = ($event.target.value == '') ? '0' : '1'" >
+ <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
+ <option *ngFor="let cred of credentials" value={{cred.id}}>
+ {{getIssuerName(cred)}}
+ </option>
+ </select>
</div>
</div>
+ <div class="col-sm">
+ <button [disabled]="!canAddAttribute(newStandardAttribute)"
class="btn btn-primary" (click)="saveAttribute(newStandardAttribute)">
+ <span class="fa fa-plus"></span>
+ </button>
+ </div>
+ </div>
</div>
+ <p class="mb-2"> {{getMessage("edit_identity_html@addCustomClaim")}}</p>
<div class="table pb-1">
- <!-- Standard "profile" claims first -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingProfileClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b>
- </div>
- </div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div style="flex:1;" *ngIf="claim != claimInEdit">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
- <span *ngIf="isClaimCred(claim) && (claim != claimInEdit)"
>{{ getCredValue(claim) }} <i class="text-primary" style="float:right;"><i
class="fa fa-certificate"></i> {{ getIssuer(claim) }}</i></span>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
+ <!-- Add custom attribute -->
+
+ <div class="row mb-3"
+ [class.alert-danger]="isInConflict(newAttribute)">
<div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canUpdateAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button class="btn btn-primary" (click)="editAttribute(claim)"
*ngIf="claim != claimInEdit">
- <span class="fa fa-edit"></span>
- </button>
- <button class="ml-2 btn btn-primary"
(click)="deleteAttribute(claim)">
- <span class="fa fa-trash"></span>
- </button>
+ <input [class.text-danger]="!attributeNameValid(newAttribute)"
placeholder="{{ getMessage('edit_identity_html@name') }}"
[(ngModel)]="newAttribute.name">
</div>
- </div>
- <!-- Standard "profile" claims missing on the identity -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingProfileClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
+ <div style="flex:1;">
+ <input *ngIf="!isClaimCred(newAttribute)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="newAttribute.value">
<select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
+ *ngIf="newAttribute.credential !== '' &&
isClaimCred(newAttribute)" (change)="newAttribute.value=$event.target.value">
<option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
+ <option *ngFor="let claim of
credentialValuesForClaim(newAttribute)" value={{claim.name}}>
+ {{claim.value}} <i>({{claim.name}})</i>
</option>
</select>
</div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
+ <div style="float:right;" *ngIf="credentials.length > 0">
<select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
+ [(ngModel)]="newAttribute.credential"
+ (change)="newAttribute.credential=$event.target.value;
newAttribute.flag = ($event.target.value == '') ? '0' : '1'" >
<option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
+ <option *ngFor="let cred of credentials" value={{cred.id}}>
{{getIssuerName(cred)}}
</option>
</select>
</div>
</div>
<div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canAddAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button *ngIf="claim != claimInEdit" class="btn btn-primary"
(click)="editAttribute(claim)">
+ <button [disabled]="!canAddAttribute(newAttribute)" class="btn
btn-primary" (click)="saveAttribute(newAttribute)">
<span class="fa fa-plus"></span>
</button>
</div>
</div>
+
</div>
- <div class="table pb-1">
- <!-- Standard "address" claims first -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingAddressClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div style="flex:1;" *ngIf="claim != claimInEdit">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
- <span *ngIf="isClaimCred(claim) && (claim != claimInEdit)"
>{{ getCredValue(claim) }} <i class="text-primary" style="float:right;"><i
class="fa fa-certificate"></i> {{ getIssuer(claim) }}</i></span>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canUpdateAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button class="btn btn-primary" (click)="editAttribute(claim)"
*ngIf="claim != claimInEdit">
- <span class="fa fa-edit"></span>
- </button>
- <button class="ml-2 btn btn-primary"
(click)="deleteAttribute(claim)">
- <span class="fa fa-trash"></span>
- </button>
- </div>
+ <p *ngIf="missingNonStandardClaims.length > 0"
+ class="card-subtitle mb-4">
{{getMessage("edit_identity_html@addRequestedMissingClaim")}}</p>
+ <div *ngIf="missingNonStandardClaims.length > 0"
+ class="table pb-1">
+ <!-- Add standard attribute -->
+ <div class="row mb-3"
+ [class.alert-danger]="isInConflict(newRequestedAttribute)">
+ <div class="col-sm">
+ <select class="custom-select"
+ (change)="newRequestedAttribute.name=$event.target.value">
+ <option value="" >{{
getMessage("edit_identity_html@selectAttribute") }}</option>
+ <option *ngFor="let claim of missingNonStandardClaims"
value={{claim.name}}>
+ {{getDescription(claim)}}
+ </option>
+ </select>
</div>
- <!-- Standard "address" claims missing on the identity -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingAddressClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canAddAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button *ngIf="claim != claimInEdit" class="btn btn-primary"
(click)="editAttribute(claim)">
- <span class="fa fa-plus"></span>
- </button>
+ <div class="col-sm" style="display:flex;">
+ <div style="flex:1;">
+ <input *ngIf="!isClaimCred(newRequestedAttribute)"
placeholder="{{ getMessage('Value') }}"
[(ngModel)]="newRequestedAttribute.value">
+ <select class="custom-select"
+ *ngIf="newRequestedAttribute.credential !== '' &&
isClaimCred(newRequestedAttribute)"
(change)="newRequestedAttribute.value=$event.target.value">
+ <option [value]="getZeroId()" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
+ <option *ngFor="let claim of
credentialValuesForClaim(newRequestedAttribute)" value={{claim.name}}>
+ {{claim.value}} <i>({{claim.name}})</i>
+ </option>
+ </select>
+ </div>
+ <div style="float:right;" *ngIf="credentials.length > 0">
+ <select class="custom-select"
+ [(ngModel)]="newRequestedAttribute.credential"
+
+
(change)="newRequestedAttribute.credential=$event.target.value;
newRequestedAttribute.flag = ($event.target.value == '') ? '0' : '1'" >
+ <option value="">{{
getMessage("edit_identity_html@selfissued") }}</option>
+ <option *ngFor="let cred of credentials" value={{cred.id}}>
+ {{getIssuerName(cred)}}
+ </option>
+ </select>
</div>
</div>
+ <div class="col-sm">
+ <button [disabled]="!canAddAttribute(newRequestedAttribute)"
class="btn btn-primary" (click)="saveAttribute(newRequestedAttribute)">
+ <span class="fa fa-plus"></span>
+ </button>
+ </div>
+ </div>
</div>
+ <hr>
+
+ <!-- All existing attributes -->
+ <h3 class="card-subtitle mb-4">
{{getMessage("edit_identity_html@storedAttributes")}}</h3>
<div class="table pb-1">
- <!-- Standard "phone" claims first -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
+ [class.inEdit]="claim == claimInEdit"
[class.text-primary]="isClaimRequested(claim)"
[class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingPhoneClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
+ *ngFor="let claim of attributes">
+ <div class="col-sm">
+ <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b>
+ </div>
<div class="col-sm" style="display:flex;">
<div style="flex:1;" *ngIf="claim == claimInEdit">
<input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
@@ -336,7 +199,7 @@
</div>
</div>
<div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canUpdateAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
+ <button *ngIf="claim == claimInEdit"
[disabled]="!canUpdateAttribute(claim)" class="btn btn-primary"
(click)="saveAttribute(claim)">
<span class="fa fa-save"></span>
</button>
<button class="btn btn-primary" (click)="editAttribute(claim)"
*ngIf="claim != claimInEdit">
@@ -345,178 +208,7 @@
<button class="ml-2 btn btn-primary"
(click)="deleteAttribute(claim)">
<span class="fa fa-trash"></span>
</button>
- </div>
- </div>
- <!-- Standard "phone" claims missing on the identity -->
- <div class="row mb-3" [class.openid]="inOpenIdFlow()"
- [class.inEdit]="claim == claimInEdit"
- [class.text-primary]="isClaimRequested(claim)"
- [class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingPhoneClaims">
- <div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="claim == claimInEdit">
- <input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <select class="custom-select"
- [(ngModel)]="claim.value"
- *ngIf="claim.credential !== '' && isClaimCred(claim)"
(change)="credentialClaimSelected(claim, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let cred of credentialValuesForClaim(claim)"
value={{cred.name}}>
- {{cred.value}} <i>({{cred.name}})</i>
- </option>
- </select>
- </div>
- <div *ngIf="claim == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="claim.credential"
- (change)="credentialSelected(claim, $event.target.value);">
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" [value]="cred.id">
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="claim == claimInEdit"
[disabled]="!canAddAttribute(claim)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button *ngIf="claim != claimInEdit" class="btn btn-primary"
(click)="editAttribute(claim)">
- <span class="fa fa-plus"></span>
- </button>
- </div>
- </div>
- </div>
-
- <h3 class="card-subtitle mb-4" >{{
getMessage("edit_identity_html@additionalInfo") }} <span (click)="showExtraInfo
= !showExtraInfo" class="fa fa-question-circle"></span></h3>
- <div class="alert alert-secondary fade show" *ngIf="showExtraInfo" >
- {{ getMessage("edit_identity_html@non_standardClaims") }}
- </div>
-
- <!-- Missing "non-standard" claims that are requested -->
- <div class="table pb-1" *ngIf="isAnyRequestedNonStandardClaimMissing()">
- <div class="row mb-3 text-primary"
- [class.inEdit]="missing == claimInEdit"
- [class.openid]="inOpenIdFlow()"
- [class.alert-danger]="newAttribute.name === missing.name"
- *ngFor="let missing of missingNonStandardClaims">
- <div class="col-sm">
- <i *ngIf="isClaimRequested(missing)" class="fa
fa-openid"></i><b> {{missing.name}}</b>
- </div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;">
- <input *ngIf="!isClaimCredentialRequested(missing)"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="missing.value">
- <select class="custom-select"
- *ngIf="isClaimCredentialRequested(missing)"
(change)="credentialClaimSelected(missing, $event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let claim of
credentialValuesForClaim(missing)" value={{claim.name}}>
- {{claim.value}} <i>({{claim.name}})</i>
- </option>
- </select>
- </div>
- <div style="float:right;">
- <i *ngIf="!isClaimCredentialRequested(missing)"
class="text-secondary" style="float:right;"><i class="fa fa-certificate"></i>
{{ getMessage("edit_identity_html@selfissued") }}</i>
- <select class="custom-select"
*ngIf="isClaimCredentialRequested(missing)"
- (change)="credentialSelected(missing, $event.target.value)" >
- <option value="" >{{
getMessage("edit_identity_html@selectSource") }}</option>
- <option *ngFor="let cred of credentials" value={{cred.id}}>
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button [disabled]="!canAddAttribute(missing)" class="btn
btn-primary" (click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- </div>
- </div>
- </div>
- <!-- "non-standard" claims which do exist -->
- <div class="table pb-1">
- <div class="row mb-3"
- [class.inEdit]="attribute == claimInEdit"
- [class.openid]="inOpenIdFlow()"
- [class.text-primary]="isClaimRequested(attribute)"
- [class.alert-danger]="newAttribute.name === attribute.name"
- *ngFor="let attribute of existingNonStandardClaims">
- <div class="col-sm">
- <i *ngIf="isClaimRequested(attribute)" class="fa
fa-openid"></i><b> {{ attribute.name }}</b>
- </div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;" *ngIf="attribute == claimInEdit">
- <input *ngIf="!isClaimCred(attribute)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="attribute.value">
- <select class="custom-select"
- [(ngModel)]="attribute.value"
- *ngIf="isClaimCred(attribute)"
- (change)="credentialClaimSelected(attribute,
$event.target.value)">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let claim of
credentialValuesForClaim(attribute)" value={{claim.name}}>
- {{claim.value}} <i>({{claim.name}})</i>
- </option>
- </select>
- </div>
- <div style="flex:1;" *ngIf="attribute != claimInEdit">
- <span *ngIf="!isClaimCred(attribute) && (attribute !=
claimInEdit)">{{ attribute.value }} <i class="text-secondary"
style="float:right;"><i class="fa fa-certificate"></i> {{
getMessage("edit_identity_html@selfissued") }}</i></span>
- <span *ngIf="isClaimCred(attribute) && (attribute !=
claimInEdit)" >{{ getCredValue(attribute) }} <i class="text-primary"
style="float:right;"><i class="fa fa-certificate"></i> {{ getIssuer(attribute)
}}</i></span>
- </div>
- <div *ngIf="attribute == claimInEdit" style="float:right;">
- <select class="custom-select"
- [(ngModel)]="attribute.credential"
- (change)="credentialSelected(attribute,
$event.target.value)" >
- <option [value]="getZeroId()">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" value={{cred.id}}>
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button *ngIf="attribute == claimInEdit"
[disabled]="!canUpdateAttribute(attribute)" class="btn btn-primary"
(click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
- <button class="ml-1 btn btn-primary"
(click)="editAttribute(attribute)" *ngIf="attribute != claimInEdit">
- <span class="fa fa-edit"></span>
- </button>
- <button class="ml-1 btn btn-primary"
(click)="deleteAttribute(attribute)">
- <span class="fa fa-trash"></span>
- </button>
- </div>
- </div>
- <!-- New Attribute -->
-
- <div class="row mb-3"
- [class.alert-danger]="isInConflict(newAttribute)">
- <div class="col-sm">
- <input [class.text-danger]="!attributeNameValid(newAttribute)"
placeholder="{{ getMessage('edit_identity_html@attribute') }}"
[(ngModel)]="newAttribute.name">
- </div>
- <div class="col-sm" style="display:flex;">
- <div style="flex:1;">
- <input *ngIf="!isClaimCred(newAttribute)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="newAttribute.value">
- <select class="custom-select"
- *ngIf="newAttribute.credential !== '' &&
isClaimCred(newAttribute)" (change)="newAttribute.value=$event.target.value">
- <option value="" >{{
getMessage("edit_identity_html@selectClaim") }}</option>
- <option *ngFor="let claim of
credentialValuesForClaim(newAttribute)" value={{claim.name}}>
- {{claim.value}} <i>({{claim.name}})</i>
- </option>
- </select>
- </div>
- <div style="float:right;">
- <select class="custom-select"
- (change)="newAttribute.credential=$event.target.value;
newAttribute.flag = ($event.target.value == '') ? '0' : '1'" >
- <option value="">{{
getMessage("edit_identity_html@selfissued") }}</option>
- <option *ngFor="let cred of credentials" value={{cred.id}}>
- {{getIssuerName(cred)}}
- </option>
- </select>
- </div>
- </div>
- <div class="col-sm">
- <button [disabled]="!canAddAttribute(newAttribute)" class="btn
btn-primary" (click)="addAttribute()">
- <span class="fa fa-save"></span>
- </button>
</div>
</div>
</div>
@@ -535,8 +227,8 @@
<!-- Edit card buttons -->
<div>
- <button class="btn btn-primary" (click)="saveIdentity()"
[disabled]="!canSaveIdentity()">
- <span class="fa fa-save"></span> {{ getMessage("SaveAndBack") }}
+ <button class="btn btn-primary" (click)="goBack()">
+ <span class="fa fa-save"></span> {{ getMessage("Back") }}
</button>
<button *ngIf="!inOpenIdFlow()" class="btn btn-primary"
[routerLink]="['/edit-authorizations', identity.name]" [style.float]="'right'">
<span class="fa fa-openid"></span>
diff --git a/src/app/edit-identity/edit-identity.component.ts
b/src/app/edit-identity/edit-identity.component.ts
index f461b2b..b48615a 100644
--- a/src/app/edit-identity/edit-identity.component.ts
+++ b/src/app/edit-identity/edit-identity.component.ts
@@ -30,10 +30,9 @@ export class EditIdentityComponent implements OnInit {
credentials: Credential[] = [];
credentialValues: {};
newAttribute: Attribute;
- newCredClaim: Attribute;
- missingCred: Attribute[] = [];
+ newStandardAttribute: Attribute;
+ newRequestedAttribute: Attribute;
requestedClaims: Attribute[] = [];
- optionalClaims: Attribute[] = [];
webfingerEmail: string;
authorizations: Authorization[] = [];
emailNotFoundAlertClosed: boolean = true;
@@ -77,7 +76,8 @@ export class EditIdentityComponent implements OnInit {
this.loadAuthorizationsFromLocalStorage();
this.identity = new Identity('','');
this.newAttribute = new Attribute('', '', this.getZeroId(), '', 'STRING',
'0');
- this.newCredClaim = new Attribute('', '', this.getZeroId(), '', 'STRING',
'1');
+ this.newStandardAttribute = new Attribute('', '', this.getZeroId(), '',
'STRING', '0');
+ this.newRequestedAttribute = new Attribute('', '', this.getZeroId(), '',
'STRING', '0');
this.newCredential = new Credential('', '', '', 'JWT', '', 0, []);
this.loadImportScopesFromLocalStorage()
this.loadImportIdProviderFromLocalStorage();
@@ -136,6 +136,38 @@ export class EditIdentityComponent implements OnInit {
return result;
}
+ private getAttributePriority(attr: Attribute) {
+ if (this.oidcService.isStandardProfileClaim(attr)) {
+ return 5;
+ } else if (this.oidcService.isStandardEmailClaim(attr)) {
+ return 6;
+ } else if (this.oidcService.isStandardAddressClaim(attr)) {
+ return 4;
+ } else if (this.oidcService.isStandardPhoneClaim(attr)) {
+ return 3;
+ } else {
+ return 2;
+ }
+ }
+
+ sortAttributes(attrs: Attribute[]) {
+ return attrs.sort((a,b) => {
+ if (this.getAttributePriority(a) > this.getAttributePriority(b)) {
+ return -1;
+ }
+ if (this.getAttributePriority(a) < this.getAttributePriority(b)) {
+ return 1;
+ }
+ if (a.name > b.name) {
+ return -1;
+ }
+ if (a.name < b.name) {
+ return 1;
+ }
+ return 0;
+ });
+ }
+
private updateAttributes() {
this.reclaimService.getAttributes(this.identity).subscribe(attributes => {
this.existingProfileClaims = this.bootstrapClaimArray
(this.oidcService.getStandardProfileClaims());
@@ -143,7 +175,7 @@ export class EditIdentityComponent implements OnInit {
this.existingPhoneClaims = this.bootstrapClaimArray
(this.oidcService.getStandardPhoneClaims());
this.existingAddressClaims = this.bootstrapClaimArray
(this.oidcService.getStandardAddressClaims());
this.existingNonStandardClaims = [];
- this.attributes = attributes.sort();
+ this.attributes = this.sortAttributes(attributes);
for (let attr of this.attributes) {
if (this.oidcService.isStandardProfileClaim(attr)) {
this.existingProfileClaims =
this.updateClaimArray(this.existingProfileClaims, attr);
@@ -163,6 +195,7 @@ export class EditIdentityComponent implements OnInit {
this.existingAddressClaims =
this.cleanupClaimArray(this.existingAddressClaims);
this.updateMissingAttributes();
this.validateEmailForImport();
+ this.resetAttributes();
},
err => {
//this.errorInfos.push("Error retrieving attributes for ``" +
identity.name + "''");
@@ -170,6 +203,11 @@ export class EditIdentityComponent implements OnInit {
});
}
+ resetAttributes() {
+ this.resetStandardAttribute(this.newStandardAttribute);
+ this.resetAttribute(this.newAttribute);
+ this.resetAttribute(this.newRequestedAttribute);
+ }
inOpenIdFlow() {
return this.oidcService.inOpenIdFlow();
@@ -237,10 +275,10 @@ export class EditIdentityComponent implements OnInit {
isInConflict(attribute: Attribute): boolean {
/*return this.checkConflict(this.missingProfileClaims, attribute) ||
- this.checkConflict(this.missingEmailClaims, attribute) ||
- this.checkConflict(this.missingPhoneClaims, attribute) ||
- this.checkConflict(this.missingAddressClaims, attribute) ||
- this.checkConflict(this.missingNonStandardClaims, attribute) ||*/
+ this.checkConflict(this.missingEmailClaims, attribute) ||
+ this.checkConflict(this.missingPhoneClaims, attribute) ||
+ this.checkConflict(this.missingAddressClaims, attribute) ||
+ this.checkConflict(this.missingNonStandardClaims, attribute) ||*/
return this.checkConflict(this.attributes, attribute);
}
@@ -268,125 +306,62 @@ export class EditIdentityComponent implements OnInit {
return this.canSaveAttributes();
}
- /**
- * TODO fix newAttribute so that we can make
- * it either attested or plain
- */
+ isAttributeOk(attr: Attribute) {
+ return ((attr.name === '') &&
+ (attr.value === '')) &&
+ !this.isInConflict(attr);
+ }
+
canSaveAttributes(): boolean {
if (this.canAddAttribute(this.newAttribute)) {
return true;
}
- return ((this.newAttribute.name === '') &&
- (this.newAttribute.value === '')) &&
- !this.isInConflict(this.newAttribute);
+ return this.isAttributeOk(this.newAttribute) &&
+ this.isAttributeOk(this.newStandardAttribute);
}
- saveIdentity() {
+ goBack() {
localStorage.removeItem("userForCredential");
- this.saveIdentityAttributes();
- }
-
- saveIdentityAttributes() {
- if (this.newAttribute.flag === '0') {
- /**
- * Make sure credential is not still set
- */
- this.newAttribute.credential = '';
- }
- this.storeAttributes()
- .pipe(
- finalize(() => {
- this.newAttribute.name = '';
- this.newAttribute.value = '';
- this.newAttribute.type = 'STRING';
- this.newAttribute.flag = '0';
- this.router.navigate(['/']);
- }))
- .subscribe(res => {
- //FIXME success dialog/banner
- this.updateAttributes();
- this.router.navigate(['/']);
- },
- err => {
- console.log(err);
- //this.errorInfos.push("Failed to update identity ``" +
this.identityInEdit.name + "''");
- });
+ this.router.navigate(['/']);
}
-
- deleteAttribute(attribute) {
- this.reclaimService.deleteAttribute(this.identity, attribute)
- .subscribe(res => {
- //FIXME info dialog
- this.updateAttributes();
- },
- err => {
- //this.errorInfos.push("Failed to delete attribute ``" +
attribute.name + "''");
- console.log(err);
- });
+ resetAttribute(attr: Attribute) {
+ attr.name = '';
+ attr.value = '';
+ attr.type = 'STRING';
+ attr.flag = '0';
+ attr.credential = this.getZeroId();
}
- private storeMissingAttributes(missing: Attribute[]): any {
- const promises = [];
- let i;
- if (undefined !== missing) {
- for (let attr of missing) {
- if (attr.value === '') {
- continue;
- }
- if (attr.flag === '0') {
- attr.credential = '';
- }
- promises.push(from(this.reclaimService.addAttribute(
- this.identity, attr)));
+ resetStandardAttribute(attr: Attribute) {
+ this.resetAttribute(attr);
+ for (let claim of this.attributes) {
+ if (claim.name === 'email') {
+ return;
}
}
- return promises;
+ attr.name = 'email';
}
- /**
- * FIXME incorporate attested attributes here!
- */
- private storeAttributes() {
- var promises = [];
- promises = promises.concat (this.storeMissingAttributes
(this.missingProfileClaims));
- promises = promises.concat (this.storeMissingAttributes
(this.missingEmailClaims));
- promises = promises.concat (this.storeMissingAttributes
(this.missingPhoneClaims));
- promises = promises.concat (this.storeMissingAttributes
(this.missingAddressClaims));
- promises = promises.concat (this.storeMissingAttributes
(this.missingNonStandardClaims));
- if (undefined !== this.attributes) {
- for (let attr of this.attributes) {
- /*if (attr.flag === '1') {
- continue; //Is an credential
- }*/
- if (attr.flag === '0') {
- attr.credential = '';
- }
- promises.push(
- from(this.reclaimService.addAttribute(this.identity, attr)));
- }
- }
- if (this.newAttribute.value !== '') {
- promises.push(from(this.reclaimService.addAttribute(this.identity,
this.newAttribute)));
- }
-
- return forkJoin(promises);
+ deleteAttribute(attribute) {
+ this.reclaimService.deleteAttribute(this.identity, attribute)
+ .subscribe(res => {
+ //FIXME info dialog
+ this.updateAttributes();
+ },
+ err => {
+ //this.errorInfos.push("Failed to delete attribute ``" + attribute.name
+ "''");
+ console.log(err);
+ });
}
- /**
- * Adds a new attribute, stores all changes and STAYS on this page.
- */
- addAttribute() {
- this.storeAttributes()
- .pipe(
- finalize(() => {
- this.newAttribute.name = '';
- this.newAttribute.value = '';
- this.newAttribute.type = 'STRING';
- this.newAttribute.flag = '0';
- this.updateAttributes();
- }))
+ saveAttribute(attr: Attribute) {
+ this.reclaimService.addAttribute(this.identity, attr)
+ .pipe(
+ finalize(() => {
+ this.updateAttributes();
+ }))
.subscribe(res => {
console.log(res);
},
@@ -445,12 +420,12 @@ export class EditIdentityComponent implements OnInit {
return false;
}
var requestedClaims = this.oidcService.getClaimNamesForRequest();
- for (let claim in requestedClaims) {
+ for (let claim of requestedClaims) {
if (this.isAttributeNameInList(claim, this.missingProfileClaims) ||
this.isAttributeNameInList(claim, this.missingEmailClaims) ||
- this.isAttributeNameInList(claim, this.missingAddressClaims) ||
- this.isAttributeNameInList(claim, this.missingPhoneClaims) ||
- this.isAttributeNameInList(claim, this.missingNonStandardClaims)) {
+ this.isAttributeNameInList(claim, this.missingAddressClaims) ||
+ this.isAttributeNameInList(claim, this.missingPhoneClaims) ||
+ this.isAttributeNameInList(claim,
this.missingNonStandardClaims)) {
return true;
}
}
@@ -555,8 +530,8 @@ export class EditIdentityComponent implements OnInit {
var value = authInfo.split(": ")[1];
newAuthorization[key] = value;
}
- )
- this.authorizations.push(newAuthorization);
+ )
+ this.authorizations.push(newAuthorization);
}
});
}
@@ -593,7 +568,7 @@ export class EditIdentityComponent implements OnInit {
}
this.scopes.push(scopeInterface)
}
- );
+ );
}
loadImportIdProviderFromLocalStorage(){
@@ -603,7 +578,7 @@ export class EditIdentityComponent implements OnInit {
tryImportCredential() {
if (this.importIdProvider.url === '') {
- return;
+ return;
}
const loginOptions: LoginOptions = {
customHashFragment: "?code="+localStorage.getItem("credentialCode") +
"&state=" + localStorage.getItem("credentialState") + "&session_state="+
localStorage.getItem("credentialSession_State"),
@@ -657,8 +632,8 @@ export class EditIdentityComponent implements OnInit {
for (let attr of cred.attributes) {
if ((attr.name == "sub") ||
(attr.name == "nonce") ||
- (attr.name == "email_verified") ||
- (attr.name == "phone_number_verified")) {
+ (attr.name == "email_verified") ||
+ (attr.name == "phone_number_verified")) {
continue;
}
//New attribute with name == claim name
@@ -673,7 +648,6 @@ export class EditIdentityComponent implements OnInit {
}
promises.push(
from(this.reclaimService.addAttribute(this.identity,
attestation)));
- //promises = promises.concat (this.storeAttribute(attestation));
}
forkJoin(promises)
.pipe(
@@ -711,7 +685,7 @@ export class EditIdentityComponent implements OnInit {
if ((null == emailAddr) ||
!emailAddr.includes('@')) {
this.validImportEmail = false;
- return;
+ return;
}
if (emailAddr.length - emailAddr.indexOf('@') < 4) {
this.validImportEmail = false;
@@ -733,11 +707,11 @@ export class EditIdentityComponent implements OnInit {
this.credentialService.getLink(account).subscribe (idProvider => {
this.importIdProvider = new IdProvider((idProvider.links[0]).href,
(idProvider.links[0]).href.split('//')[1]);
- localStorage.setItem('importIdProviderURL', this.importIdProvider.url);
- this.getImportScopes();
- console.log(this.importIdProvider.url);
- this.validImportEmail = true;
- this.tryImportCredential();
+
localStorage.setItem('importIdProviderURL', this.importIdProvider.url);
+ this.getImportScopes();
+
console.log(this.importIdProvider.url);
+ this.validImportEmail = true;
+ this.tryImportCredential();
},
error => {
this.validImportEmail = false;
@@ -786,7 +760,7 @@ export class EditIdentityComponent implements OnInit {
this.scopes.push(scopeInterface)
});
localStorage.setItem("scopes", JSON.stringify(this.scopes));
- });
+ });
}
getZeroId() {
@@ -802,8 +776,16 @@ export class EditIdentityComponent implements OnInit {
credentialClaimSelected(claim: Attribute, eventValue) {
claim.value = eventValue;
if (claim.name !== '') {
- this.addAttribute();
+ this.saveAttribute(claim);
}
}
+ getMissingStandardClaims() {
+ var claims = [];
+ claims = claims.concat(this.missingProfileClaims);
+ claims = claims.concat(this.missingEmailClaims);
+ claims = claims.concat(this.missingAddressClaims);
+ claims = claims.concat(this.missingPhoneClaims);
+ return claims;
+ }
}
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index b506390..f8cceee 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -53,6 +53,10 @@
"edit_credentials_ts@noAccount": "No account found with this email",
"edit_credentials_ts@errorWrongAddress": "An Error has occured - This may
have been caused by a wrong e-mail address.",
"edit_identity_html@basicInfo": "Basic user information",
+ "edit_identity_html@addAttributes": "Add new attributes",
+ "edit_identity_html@addStandardClaim": "Common, standardized attributes:",
+ "edit_identity_html@addCustomClaim": "Custom attributes:",
+ "edit_identity_html@addRequestedMissingClaim": "Requested but missing
attributes:",
"edit_identity_html@importInfo": "Your email address indicates that you
may be able to import attributes from an external account at
``{{ISSUERNAME}}´´.",
"edit_identity_html@linkAccount": "Import attributes",
"edit_identity_html@standardScopes": "The attributes below correspond to
the standard scopes of the\nOpenID Connect specification: ``profile'',
``email'', ``phone'' and ``address''.",
@@ -60,9 +64,12 @@
"edit_identity_html@importFrom": "Try import from ``{{ISSUERNAME}}´´",
"edit_identity_html@unset": "Unset",
"edit_identity_html@attribute": "Attribute",
+ "edit_identity_html@selectAttribute": "<Select attribute name>",
+ "edit_identity_html@storedAttributes": "Stored attributes",
+ "edit_identity_html@name": "Name",
"edit_identity_html@plain": "Plain",
"edit_identity_html@credential": "Credential",
- "edit_identity_html@selectSource": "Select credential source",
+ "edit_identity_html@selectSource": "<Select credential source>",
"edit_identity_html@noCredentialSource": "You haven't added any credential
sources yet.",
"edit_identity_html@selectClaim": "Select claim",
"edit_identity_html@additionalInfo": "Additional information",
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [reclaim-ui] 371/459: attribute import done, (continued)
- [reclaim-ui] 371/459: attribute import done, gnunet, 2021/06/11
- [reclaim-ui] 404/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 368/459: settings page, experiments tweaks, gnunet, 2021/06/11
- [reclaim-ui] 395/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 382/459: style adjustments, gnunet, 2021/06/11
- [reclaim-ui] 373/459: fix credential string lowercase, gnunet, 2021/06/11
- [reclaim-ui] 393/459: display all missing claims, gnunet, 2021/06/11
- [reclaim-ui] 380/459: quality of life improvements, gnunet, 2021/06/11
- [reclaim-ui] 383/459: better credential selection, gnunet, 2021/06/11
- [reclaim-ui] 396/459: relax attribute requirements, gnunet, 2021/06/11
- [reclaim-ui] 388/459: significantly simplify identity edit,
gnunet <=
- [reclaim-ui] 418/459: more cleanup, gnunet, 2021/06/11
- [reclaim-ui] 431/459: Added translation using Weblate (Portuguese), gnunet, 2021/06/11
- [reclaim-ui] 430/459: mini fix, gnunet, 2021/06/11
- [reclaim-ui] 405/459: fix search icon, gnunet, 2021/06/11
- [reclaim-ui] 381/459: even more quality of life improvements, gnunet, 2021/06/11
- [reclaim-ui] 416/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 392/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 411/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 410/459: enable filtering, gnunet, 2021/06/11
- [reclaim-ui] 389/459: update, gnunet, 2021/06/11