mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-12 17:15:15 +00:00
fix(console): formfield changes and ux (#1020)
* cnsl-formfield, cnsl-label, cnsl-input, ch prefix * create user cnsl-fields, add cnsl-error * replace user forms with cnsl-fields * replace all other occurrences of mat-form-field with cnsl-fields * improve hover, active, focus behavior, headlin styling * user-grant refactor * style cleanup * stylelint * fix detail layout flexstart, user table header * input dir * error, input directives instead components, on blur handler * error directive, formfield content children * formfield control directive * use new field for new contact dialog * formfield hint, error directive, scss * hint or error binding, animation after view init * avatar changes, policy header * style lint * lint * input control within formfield, errorstatematcher * use matformcontrol to merge with selects * member table min width, lint * lint * implement from matformcontrol insteat custom, add selector * find error * add focus listener * labelfloat * fix input directive * renaming * rm logs * user search overflow, org create i18n, meta cleanup * sidenav shadow * redirect to org table * lint * lint test files * remove usage of formfieldmodule, use input module, layout optim * replace formfieldmodule usage with inputmodule * lint input dir, scss * user grant, user table optimisations * reorganize sidenav, project table empty, tooltips, avatar ch * user grant tooltips, form field error directive accessor * checkbox overflow fix, table dateblock, i18n tooltips * app placeholder, i18n, optimize mobile layout * change refresh table order, i18n, redirect chips * stylelint * chore(deps-dev): bump stylelint from 13.7.2 to 13.8.0 in /console (#1007) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump stylelint from 13.7.2 to 13.8.0 in /console Bumps [stylelint](https://github.com/stylelint/stylelint) from 13.7.2 to 13.8.0. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/master/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint/compare/13.7.2...13.8.0) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @angular/cli from 11.0.1 to 11.0.2 in /console (#1006) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump @angular/cli from 11.0.1 to 11.0.2 in /console Bumps [@angular/cli](https://github.com/angular/angular-cli) from 11.0.1 to 11.0.2. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/compare/v11.0.1...v11.0.2) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump google-proto-files from 2.2.0 to 2.3.0 in /console (#1005) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps): bump google-proto-files from 2.2.0 to 2.3.0 in /console Bumps [google-proto-files](https://github.com/googleapis/nodejs-proto-files) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/googleapis/nodejs-proto-files/releases) - [Changelog](https://github.com/googleapis/nodejs-proto-files/blob/master/CHANGELOG.md) - [Commits](https://github.com/googleapis/nodejs-proto-files/compare/v2.2.0...v2.3.0) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/node from 14.14.6 to 14.14.9 in /console (#1004) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump @types/node from 14.14.6 to 14.14.9 in /console Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.6 to 14.14.9. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @angular/language-service from 11.0.0 to 11.0.2 in /console (#999) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump @angular/language-service in /console Bumps [@angular/language-service](https://github.com/angular/angular/tree/HEAD/packages/language-service) from 11.0.0 to 11.0.2. - [Release notes](https://github.com/angular/angular/releases) - [Changelog](https://github.com/angular/angular/blob/master/CHANGELOG.md) - [Commits](https://github.com/angular/angular/commits/11.0.2/packages/language-service) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @angular-devkit/build-angular from 0.1100.1 to 0.1100.2 in /console (#1003) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump @angular-devkit/build-angular in /console Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1100.1 to 0.1100.2. - [Release notes](https://github.com/angular/angular-cli/releases) - [Commits](https://github.com/angular/angular-cli/commits) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * chore(deps-dev): bump prettier from 2.1.2 to 2.2.0 in /console (#1002) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump prettier from 2.1.2 to 2.2.0 in /console Bumps [prettier](https://github.com/prettier/prettier) from 2.1.2 to 2.2.0. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.1.2...2.2.0) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/jasmine from 3.6.1 to 3.6.2 in /console (#1001) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps-dev): bump @types/jasmine from 3.6.1 to 3.6.2 in /console Bumps [@types/jasmine](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jasmine) from 3.6.1 to 3.6.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jasmine) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * chore(deps): bump file-saver from 2.0.2 to 2.0.5 in /console (#1000) * fix: add project validation (#996) * fix: project add validation (#997) * fix: add project validation * fix: removed loop * chore(deps): bump file-saver from 2.0.2 to 2.0.5 in /console Bumps [file-saver](https://github.com/eligrey/FileSaver.js) from 2.0.2 to 2.0.5. - [Release notes](https://github.com/eligrey/FileSaver.js/releases) - [Changelog](https://github.com/eligrey/FileSaver.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/eligrey/FileSaver.js/commits) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Silvan <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Max Peintner <[email protected]> * chore(deps-dev): bump jasmine-spec-reporter in /console (#974) Bumps [jasmine-spec-reporter](https://github.com/bcaudan/jasmine-spec-reporter) from 5.0.2 to 6.0.0. - [Release notes](https://github.com/bcaudan/jasmine-spec-reporter/releases) - [Changelog](https://github.com/bcaudan/jasmine-spec-reporter/blob/master/CHANGELOG.md) - [Commits](https://github.com/bcaudan/jasmine-spec-reporter/compare/v5.0.2...v6.0.0) Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * input field border improvements, primary color * redirect form, conventional ux * redirects inputs on app create * fix dynamic suffix padding, user grant layout, lint * input style accessor, contact view optim, ext idp, card fixes * hide error on untouched formfield, border red on error touched * fix change detector * change, user, form validation, delete refresh * safari font weight adjustment, change refresh emitter * key validation * remove tabls layout from projects * app changes, refactor project, app state, meta layout * add key dialog validation, startdate, rever change tabs * stylelint * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster <[email protected]> * finnaly fix fckntimestamp picker * optional key expiry * small state badge * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Silvan <[email protected]> Co-authored-by: Florian Forster <[email protected]>
This commit is contained in:
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Florian Forster
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Silvan
parent
42f50de790
commit
ae26999834
+18
-18
@@ -4,27 +4,27 @@
|
||||
|
||||
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||
<div class="content">
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" required />
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="userName" required />
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
</span>
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.NAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
<mat-error *ngIf="name?.invalid && name?.errors?.required">
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="name" required />
|
||||
<span cnsl-error *ngIf="name?.invalid && name?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</mat-label>
|
||||
<input matInput formControlName="description" />
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="description" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="btn-container">
|
||||
<button color="primary" [disabled]="userForm.invalid" type="submit"
|
||||
|
||||
@@ -3,15 +3,14 @@ import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { UserCreateMachineRoutingModule } from './user-create-machine-routing.module';
|
||||
import { UserCreateMachineComponent } from './user-create-machine.component';
|
||||
@@ -25,8 +24,6 @@ import { UserCreateMachineComponent } from './user-create-machine.component';
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
@@ -36,6 +33,7 @@ import { UserCreateMachineComponent } from './user-create-machine.component';
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
InputModule,
|
||||
],
|
||||
})
|
||||
export class UserCreateMachineModule { }
|
||||
|
||||
@@ -5,83 +5,87 @@
|
||||
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||
<div class="content">
|
||||
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.EMAIL' | translate }}</mat-label>
|
||||
<input matInput formControlName="email" required />
|
||||
<mat-error *ngIf="email?.invalid && email?.errors?.required">
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}*</cnsl-label>
|
||||
<input cnslInput matRipple formControlName="email" required />
|
||||
<span cnsl-error *ngIf="email?.invalid && !email?.errors?.required">
|
||||
{{ 'USER.VALIDATION.NOTANEMAIL' | translate }}
|
||||
</span>
|
||||
<span cnsl-error *ngIf="email?.invalid && email?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" required />
|
||||
<span *ngIf="envSuffix" matSuffix>{{envSuffix}}</span>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}*</cnsl-label>
|
||||
<input cnslInput formControlName="userName" required
|
||||
[ngStyle]="{'padding-right': suffixPadding ? suffixPadding : '10px'}" />
|
||||
<span #suffix *ngIf="envSuffixLabel" cnslSuffix (click)="logsuff()">{{envSuffixLabel}}</span>
|
||||
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
</span>
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="content">
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="firstName" required />
|
||||
<mat-error *ngIf="firstName?.invalid && firstName?.errors?.required">
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}*</cnsl-label>
|
||||
<input cnslInput formControlName="firstName" required />
|
||||
<span cnsl-error *ngIf="firstName?.invalid && firstName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="lastName" required />
|
||||
<mat-error *ngIf="lastName?.invalid && lastName?.errors?.required">
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}*</cnsl-label>
|
||||
<input cnslInput formControlName="lastName" required />
|
||||
<span cnsl-error *ngIf="lastName?.invalid && lastName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="nickName" />
|
||||
<mat-error *ngIf="nickName?.invalid && nickName?.errors?.required">
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="nickName" />
|
||||
<span cnsl-error *ngIf="nickName?.invalid && nickName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<p class="section">{{ 'USER.CREATE.GENDERLANGSECTION' | translate }}</p>
|
||||
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.GENDER' | translate }}</mat-label>
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.GENDER' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="gender">
|
||||
<mat-option *ngFor="let gender of genders" [value]="gender">
|
||||
{{ 'GENDERS.'+gender | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="gender?.invalid && gender?.errors?.required">
|
||||
<span cnsl-error *ngIf="gender?.invalid && gender?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</mat-label>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="preferredLanguage">
|
||||
<mat-option *ngFor="let language of languages" [value]="language">
|
||||
{{ 'LANGUAGES.'+language | translate }}
|
||||
</mat-option>
|
||||
<mat-error *ngIf="preferredLanguage?.invalid && preferredLanguage?.errors?.required">
|
||||
<span cnsl-error *ngIf="preferredLanguage?.invalid && preferredLanguage?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</span>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</cnsl-form-field>
|
||||
|
||||
<p class="section">{{ 'USER.CREATE.ADDRESSANDPHONESECTION' | translate }}</p>
|
||||
|
||||
<mat-form-field class="formfield" appearance="fill">
|
||||
<mat-label>{{ 'USER.PROFILE.PHONE' | translate }}</mat-label>
|
||||
<input matInput formControlName="phone" />
|
||||
<mat-error *ngIf="phone?.invalid && phone?.errors?.required">
|
||||
<cnsl-form-field class="formfield" appearance="fill">
|
||||
<cnsl-label>{{ 'USER.PROFILE.PHONE' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="phone" />
|
||||
<span cnsl-error *ngIf="phone?.invalid && phone?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="btn-container">
|
||||
<button color="primary" [disabled]="userForm.invalid" type="submit"
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
flex-basis: 100%;
|
||||
color: var(--grey);
|
||||
font-size: .9rem;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.formfield {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
@@ -40,12 +40,13 @@ export class UserCreateComponent implements OnDestroy {
|
||||
public genders: Gender[] = [Gender.GENDER_FEMALE, Gender.GENDER_MALE, Gender.GENDER_UNSPECIFIED];
|
||||
public languages: string[] = ['de', 'en'];
|
||||
public userForm!: FormGroup;
|
||||
|
||||
public envSuffixLabel: string = '';
|
||||
private sub: Subscription = new Subscription();
|
||||
|
||||
public userLoginMustBeDomain: boolean = false;
|
||||
public loading: boolean = false;
|
||||
|
||||
@ViewChild('suffix') public suffix!: any;
|
||||
private primaryDomain!: OrgDomain.AsObject;
|
||||
|
||||
constructor(
|
||||
@@ -53,6 +54,7 @@ export class UserCreateComponent implements OnDestroy {
|
||||
private toast: ToastService,
|
||||
private fb: FormBuilder,
|
||||
private mgmtService: ManagementService,
|
||||
private changeDetRef: ChangeDetectorRef,
|
||||
) {
|
||||
this.loading = true;
|
||||
this.loadOrg();
|
||||
@@ -60,10 +62,14 @@ export class UserCreateComponent implements OnDestroy {
|
||||
this.userLoginMustBeDomain = iampolicy.toObject().userLoginMustBeDomain;
|
||||
this.initForm();
|
||||
this.loading = false;
|
||||
this.envSuffixLabel = this.envSuffix();
|
||||
this.changeDetRef.detectChanges();
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
this.initForm();
|
||||
this.loading = false;
|
||||
this.envSuffixLabel = this.envSuffix();
|
||||
this.changeDetRef.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,6 +98,11 @@ export class UserCreateComponent implements OnDestroy {
|
||||
preferredLanguage: [''],
|
||||
phone: [''],
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public logsuff(): void {
|
||||
console.log((this.suffix.nativeElement as HTMLElement), (this.suffix.nativeElement as HTMLElement).offsetWidth);
|
||||
}
|
||||
|
||||
public createUser(): void {
|
||||
@@ -123,7 +134,6 @@ export class UserCreateComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
@@ -167,11 +177,17 @@ export class UserCreateComponent implements OnDestroy {
|
||||
return this.userForm.get('country');
|
||||
}
|
||||
|
||||
public get envSuffix(): string {
|
||||
private envSuffix(): string {
|
||||
if (this.userLoginMustBeDomain && this.primaryDomain?.domain) {
|
||||
return `@${this.primaryDomain.domain}`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
public get suffixPadding(): string | undefined {
|
||||
if (this.suffix?.nativeElement.offsetWidth) {
|
||||
return `${(this.suffix.nativeElement as HTMLElement).offsetWidth + 10}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,19 @@ import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { UserCreateRoutingModule } from './user-create-routing.module';
|
||||
import { UserCreateComponent } from './user-create.component';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [UserCreateComponent],
|
||||
imports: [
|
||||
@@ -25,8 +23,6 @@ import { UserCreateComponent } from './user-create.component';
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatInputModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
@@ -36,6 +32,8 @@ import { UserCreateComponent } from './user-create.component';
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
InputModule,
|
||||
MatRippleModule,
|
||||
],
|
||||
})
|
||||
export class UserCreateModule { }
|
||||
|
||||
+3
-2
@@ -56,7 +56,7 @@
|
||||
<app-card *ngIf="user?.id" title="{{ 'GRANTS.USER.TITLE' | translate }}"
|
||||
description="{{'GRANTS.USER.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [userId]="user.id" [context]="USERGRANTCONTEXT"
|
||||
[displayedColumns]="['select', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[displayedColumns]="['select', 'projectId', 'dates', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
@@ -74,6 +74,7 @@
|
||||
<app-memberships [user]="user"></app-memberships>
|
||||
</ng-template>
|
||||
|
||||
<app-changes class="changes" [changeType]="ChangeType.MYUSER" [id]="user.id"></app-changes>
|
||||
<app-changes class="changes" [refresh]="refreshChanges$" [changeType]="ChangeType.MYUSER" [id]="user.id">
|
||||
</app-changes>
|
||||
</div>
|
||||
</app-meta-layout>
|
||||
+6
-1
@@ -1,4 +1,4 @@
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import { Component, EventEmitter, OnDestroy } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
@@ -41,6 +41,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
public UserState: any = UserState;
|
||||
|
||||
public USERGRANTCONTEXT: UserGrantContext = UserGrantContext.USER;
|
||||
public refreshChanges$: EventEmitter<void> = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
@@ -53,6 +54,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
refreshUser(): void {
|
||||
this.refreshChanges$.emit();
|
||||
this.userService.GetMyUser().then(user => {
|
||||
this.user = user.toObject();
|
||||
this.loading = false;
|
||||
@@ -86,6 +88,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
.then((data: UserProfile) => {
|
||||
this.toast.showInfo('USER.TOAST.SAVED', true);
|
||||
this.user = Object.assign(this.user, data.toObject());
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -122,6 +125,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
public resendPhoneVerification(): void {
|
||||
this.userService.ResendPhoneVerification().then(() => {
|
||||
this.toast.showInfo('USER.TOAST.PHONEVERIFICATIONSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
@@ -130,6 +134,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
public resendEmailVerification(): void {
|
||||
this.userService.ResendMyEmailVerificationMail().then(() => {
|
||||
this.toast.showInfo('USER.TOAST.EMAILVERIFICATIONSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
|
||||
+4
-4
@@ -3,10 +3,10 @@
|
||||
</h1>
|
||||
<p class="desc">{{'USER.CODEDIALOG.DESCRIPTION' | translate}}</p>
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.CODEDIALOG.CODE' | translate }}</mat-label>
|
||||
<input matInput [(ngModel)]="code" />
|
||||
</mat-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.CODEDIALOG.CODE' | translate }}</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="code" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button cdkFocusInitial color="primary" mat-button class="ok-button" (click)="closeDialog()">
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@
|
||||
<qrcode *ngIf="data" class="qrcode" [qrdata]="data" [width]="150" [errorCorrectionLevel]="'M'"></qrcode>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="form-field" label="Access Code" required="true">
|
||||
<mat-label>Code</mat-label>
|
||||
<input matInput [(ngModel)]="code" />
|
||||
</mat-form-field>
|
||||
<cnsl-form-field class="form-field" label="Access Code" required="true">
|
||||
<cnsl-label>Code</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="code" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button mat-button (click)="closeDialog()"><span translate>ACTIONS.CLOSE</span></button>
|
||||
|
||||
+4
-4
@@ -3,10 +3,10 @@
|
||||
</h1>
|
||||
<p class="desc">{{data.descriptionKey | translate}}</p>
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{data.labelKey | translate }}</mat-label>
|
||||
<input matInput [(ngModel)]="value" />
|
||||
</mat-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{data.labelKey | translate }}</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="value" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button cdkFocusInitial color="primary" mat-button class="ok-button" (click)="closeDialog()">
|
||||
|
||||
+7
-7
@@ -1,20 +1,20 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { CodeDialogComponent } from './code-dialog.component';
|
||||
import { EditDialogComponent } from './edit-dialog.component';
|
||||
|
||||
describe('CodeDialogComponent', () => {
|
||||
let component: CodeDialogComponent;
|
||||
let fixture: ComponentFixture<CodeDialogComponent>;
|
||||
let component: EditDialogComponent;
|
||||
let fixture: ComponentFixture<EditDialogComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [CodeDialogComponent],
|
||||
declarations: [EditDialogComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CodeDialogComponent);
|
||||
fixture = TestBed.createComponent(EditDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
+4
-4
@@ -3,10 +3,10 @@
|
||||
</h1>
|
||||
<p class="desc">{{'USER.SENDEMAILDIALOG.DESCRIPTION' | translate}}</p>
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.SENDEMAILDIALOG.NEWEMAIL' | translate }}</mat-label>
|
||||
<input matInput [(ngModel)]="email" />
|
||||
</mat-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.SENDEMAILDIALOG.NEWEMAIL' | translate }}</cnsl-label>
|
||||
<input cnslInput [(ngModel)]="email" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button color="primary" mat-button class="ok-button" (click)="closeDialog()">
|
||||
|
||||
+8
-8
@@ -1,20 +1,20 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { CodeDialogComponent } from './code-dialog.component';
|
||||
import { ResendEmailDialogComponent } from './resend-email-dialog.component';
|
||||
|
||||
describe('CodeDialogComponent', () => {
|
||||
let component: CodeDialogComponent;
|
||||
let fixture: ComponentFixture<CodeDialogComponent>;
|
||||
describe('ResendEmailDialogComponent', () => {
|
||||
let component: ResendEmailDialogComponent;
|
||||
let fixture: ComponentFixture<ResendEmailDialogComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [CodeDialogComponent],
|
||||
declarations: [ResendEmailDialogComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CodeDialogComponent);
|
||||
fixture = TestBed.createComponent(ResendEmailDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<button [disabled]="!canWrite" (click)="openEditDialog(EditDialogType.EMAIL)" mat-icon-button>
|
||||
<button matTooltip="{{'ACTIONS.EDIT' | translate}}" [disabled]="!canWrite"
|
||||
(click)="openEditDialog(EditDialogType.EMAIL)" mat-icon-button>
|
||||
<i class="las la-edit"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: .5rem;
|
||||
padding-right: 0;
|
||||
border-bottom: 1px solid #ffffff20;
|
||||
flex-wrap: wrap;
|
||||
|
||||
|
||||
+18
-18
@@ -1,26 +1,26 @@
|
||||
<form [formGroup]="machineForm" *ngIf="machineForm" (ngSubmit)="submitForm()">
|
||||
<div class="content">
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" required />
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="userName" required />
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
</span>
|
||||
<span cnsl-error *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.NAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required />
|
||||
<mat-error *ngIf="name?.invalid && name?.errors?.required">
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="name" required />
|
||||
<span cnsl-error *ngIf="name?.invalid && name?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield">
|
||||
<mat-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</mat-label>
|
||||
<input matInput formControlName="description" />
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="description" />
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="btn-container">
|
||||
<button type="submit" color="primary" mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
|
||||
+2
-4
@@ -2,11 +2,10 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { DetailFormMachineComponent } from './detail-form-machine.component';
|
||||
|
||||
@@ -20,8 +19,7 @@ import { DetailFormMachineComponent } from './detail-form-machine.component';
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
<form [formGroup]="profileForm" *ngIf="profileForm" (ngSubmit)="submitForm()">
|
||||
<div class="content">
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="userName" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="firstName" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="lastName" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</mat-label>
|
||||
<input matInput formControlName="nickName" />
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.GENDER' | translate }}</mat-label>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="userName" />
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="firstName" />
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="lastName" />
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
||||
<input cnslInput formControlName="nickName" />
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.GENDER' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="gender">
|
||||
<mat-option *ngFor="let gender of genders" [value]="gender">
|
||||
{{ 'GENDERS.'+gender | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</mat-label>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="preferredLanguage">
|
||||
<mat-option *ngFor="let language of languages" [value]="language">
|
||||
{{ 'LANGUAGES.'+language | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="btn-container">
|
||||
<button [disabled]="disabled" class="submit-button" type="submit" color="primary"
|
||||
|
||||
@@ -2,15 +2,13 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
|
||||
import { DetailFormComponent } from './detail-form.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DetailFormComponent,
|
||||
@@ -20,12 +18,11 @@ import { DetailFormComponent } from './detail-form.component';
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
TranslateModule,
|
||||
InputModule,
|
||||
],
|
||||
exports: [
|
||||
DetailFormComponent,
|
||||
|
||||
@@ -24,4 +24,14 @@
|
||||
|
||||
tr {
|
||||
outline: none;
|
||||
|
||||
button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-11
@@ -2,28 +2,32 @@
|
||||
<div mat-dialog-content>
|
||||
<p class="desc"> {{'USER.MACHINE.ADD.DESCRIPTION' | translate}}</p>
|
||||
|
||||
<mat-form-field class="form-field" appearance="outline">
|
||||
<mat-label>{{'USER.MACHINE.TYPE' | translate}}</mat-label>
|
||||
<cnsl-form-field class="form-field" appearance="outline">
|
||||
<cnsl-label>{{'USER.MACHINE.TYPE' | translate}}</cnsl-label>
|
||||
<mat-select [(ngModel)]="type">
|
||||
<mat-option *ngFor="let t of types" [value]="t">
|
||||
{{'USER.MACHINE.KEYTYPES.'+t | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</cnsl-form-field>
|
||||
|
||||
<mat-form-field class="form-field" appearance="outline">
|
||||
<mat-label>{{'USER.MACHINE.CHOOSEEXPIRY' | translate}}</mat-label>
|
||||
<input matInput [matDatepicker]="picker" [(ngModel)]="date">
|
||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<cnsl-form-field class="form-field" appearance="outline">
|
||||
<cnsl-label>{{'USER.MACHINE.CHOOSEEXPIRY' | translate}} (optional)</cnsl-label>
|
||||
<input cnslInput [matDatepicker]="picker" [min]="startDate" [formControl]="dateControl">
|
||||
<mat-datepicker-toggle style="top: 0;" cnslSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>
|
||||
<span cnsl-error *ngIf="dateControl?.errors?.matDatepickerMin?.min">
|
||||
{{'USER.MACHINE.CHOOSEDATEAFTER' | translate}}:
|
||||
{{dateControl?.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM'}}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<div mat-dialog-actions class=" action">
|
||||
<button mat-button (click)="closeDialog()">
|
||||
{{'ACTIONS.CANCEL' | translate}}
|
||||
</button>
|
||||
|
||||
<button color="primary" mat-raised-button class="ok-button" [disabled]="type == undefined"
|
||||
<button color="primary" mat-raised-button class="ok-button" [disabled]="type == undefined || dateControl.invalid"
|
||||
(click)="closeDialogWithSuccess()">
|
||||
{{'ACTIONS.ADD' | translate}}
|
||||
</button>
|
||||
|
||||
+8
-4
@@ -1,6 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Moment } from 'moment';
|
||||
import { MachineKeyType } from 'src/app/proto/generated/management_pb';
|
||||
|
||||
@Component({
|
||||
@@ -9,22 +9,26 @@ import { MachineKeyType } from 'src/app/proto/generated/management_pb';
|
||||
styleUrls: ['./add-key-dialog.component.scss'],
|
||||
})
|
||||
export class AddKeyDialogComponent {
|
||||
public startDate: Date = new Date();
|
||||
types: MachineKeyType[] = [
|
||||
MachineKeyType.MACHINEKEY_JSON,
|
||||
];
|
||||
date!: Moment;
|
||||
public type: MachineKeyType = MachineKeyType.MACHINEKEY_JSON;
|
||||
public dateControl: FormControl = new FormControl('', []);
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AddKeyDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
) { }
|
||||
) {
|
||||
const today = new Date();
|
||||
this.startDate.setDate(today.getDate() + 1);
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
public closeDialogWithSuccess(): void {
|
||||
this.dialogRef.close({ type: this.type, date: this.date });
|
||||
this.dialogRef.close({ type: this.type, date: this.dateControl.value });
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,14 +1,14 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
|
||||
import { AddKeyDialogComponent } from './add-key-dialog.component';
|
||||
|
||||
@@ -18,13 +18,14 @@ import { AddKeyDialogComponent } from './add-key-dialog.component';
|
||||
CommonModule,
|
||||
TranslateModule,
|
||||
MatButtonModule,
|
||||
MatFormFieldModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
FormsModule,
|
||||
MatDatepickerModule,
|
||||
MatMomentDateModule,
|
||||
ReactiveFormsModule,
|
||||
LocalizedDatePipeModule,
|
||||
],
|
||||
})
|
||||
export class AddKeyDialogModule { }
|
||||
|
||||
@@ -87,18 +87,16 @@ export class MachineKeysComponent implements OnInit {
|
||||
|
||||
if (resp.date as Moment) {
|
||||
const ts = new Timestamp();
|
||||
console.log(resp.date.toDate().getTime());
|
||||
console.log(resp.date.toDate());
|
||||
const milliseconds = resp.date.toDate().getTime();
|
||||
const seconds = Math.abs(milliseconds / 1000);
|
||||
const nanos = (milliseconds - seconds * 1000) * 1000 * 1000;
|
||||
ts.setSeconds(seconds);
|
||||
ts.setNanos(nanos);
|
||||
date = ts;
|
||||
console.log(date.toObject());
|
||||
}
|
||||
|
||||
if (type) {
|
||||
console.log(this.userId, type, date);
|
||||
return this.userService.AddMachineKey(this.userId, type, date).then((response) => {
|
||||
if (response) {
|
||||
setTimeout(() => {
|
||||
@@ -126,7 +124,6 @@ export class MachineKeysComponent implements OnInit {
|
||||
this.userService.SearchMachineKeys(this.userId, limit, offset).then(resp => {
|
||||
this.keyResult = resp.toObject();
|
||||
this.dataSource.data = this.keyResult.resultList;
|
||||
console.log(this.keyResult.resultList);
|
||||
this.loadingSubject.next(false);
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
|
||||
+5
-3
@@ -11,12 +11,14 @@
|
||||
<p class="right">{{'USER.MACHINE.KEYTYPES.'+addedKey?.type | translate}}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.EXPIRATIONDATE' | translate}}</p>
|
||||
<p class="right">{{addedKey?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</p>
|
||||
<p class="left">{{'USER.MACHINE.CREATIONDATE' | translate}}</p>
|
||||
<p class="right">{{addedKey?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm' }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p class="left">{{'USER.MACHINE.EXPIRATIONDATE' | translate}}</p>
|
||||
<p class="right">{{addedKey?.expirationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm'}}</p>
|
||||
<p class="right">{{addedKey?.expirationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm'}}
|
||||
</p>
|
||||
</div>
|
||||
<button class="download-button" mat-stroked-button color="primary" (click)="saveFile()">Download</button>
|
||||
</ng-container>
|
||||
|
||||
-5
@@ -27,11 +27,6 @@
|
||||
.action {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.selection {
|
||||
width: 50px;
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="membership-groups">
|
||||
<span class="header">{{ 'USER.MEMBERSHIPS.TITLE' | translate }}</span>
|
||||
<span class="me-header">{{ 'USER.MEMBERSHIPS.TITLE' | translate }}</span>
|
||||
<div class="people" *ngIf="memberships">
|
||||
<div class="img-list" [@cardAnimation]="memberships.totalResult">
|
||||
<mat-spinner class="spinner" diameter="20" *ngIf="loading"></mat-spinner>
|
||||
@@ -34,9 +34,9 @@
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
<span class="fill-space"></span>
|
||||
<button class="refresh-img" (click)="loadManager(user.id)" [disabled]="disabled" mat-icon-button
|
||||
aria-label="refresh contributors">
|
||||
<mat-icon>refresh</mat-icon>
|
||||
<button matTooltip="{{'ACTIONS.REFRESH' | translate}}" class="refresh-img" (click)="loadManager(user.id)"
|
||||
[disabled]="disabled" mat-icon-button aria-label="refresh contributors">
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
/* stylelint-enable */
|
||||
|
||||
.membership-groups {
|
||||
.header {
|
||||
.me-header {
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 400;
|
||||
margin-top: 0;
|
||||
font-size: 14px;
|
||||
letter-spacing: .05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.sub-header {
|
||||
@@ -33,7 +36,6 @@
|
||||
|
||||
.img-list {
|
||||
width: 100%;
|
||||
margin-top: .5rem;
|
||||
margin-left: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -54,7 +56,11 @@
|
||||
|
||||
.refresh-img {
|
||||
float: left;
|
||||
margin: 0 8px 0 -15px;
|
||||
margin: 0 0 0 -15px;
|
||||
|
||||
.icon {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-circle {
|
||||
@@ -97,6 +103,7 @@
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
letter-spacing: .05em;
|
||||
}
|
||||
|
||||
i {
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
<form *ngIf="passwordForm" autocomplete="new-password" [formGroup]="passwordForm"
|
||||
(ngSubmit)="setInitialPassword(userId)">
|
||||
<div class="content center">
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="password" matInput formControlName="password" type="password" />
|
||||
<cnsl-form-field class="formfield" appearance="outline">
|
||||
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
||||
<input cnslInput autocomplete="off" name="password" formControlName="password" type="password" />
|
||||
|
||||
<mat-error *ngIf="password?.errors?.required">
|
||||
<span cnsl-error *ngIf="password?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="passwordRepeat" matInput formControlName="confirmPassword"
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="outline">
|
||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
||||
<input cnslInput autocomplete="off" name="passwordRepeat" formControlName="confirmPassword"
|
||||
type="password" />
|
||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">
|
||||
<span cnsl-error *ngIf="confirmPassword?.errors?.notequal">
|
||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div class="btn-container">
|
||||
<button class="submit-button" [disabled]="passwordForm.invalid" mat-raised-button
|
||||
@@ -37,37 +37,37 @@
|
||||
<ng-template #authUser>
|
||||
<form *ngIf="passwordForm" [formGroup]="passwordForm" (ngSubmit)="setPassword()">
|
||||
<div class="content">
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PASSWORD.OLD' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="password" type="password" matInput
|
||||
<cnsl-form-field class="formfield" appearance="outline">
|
||||
<cnsl-label>{{ 'USER.PASSWORD.OLD' | translate }}</cnsl-label>
|
||||
<input cnslInput autocomplete="off" name="password" type="password"
|
||||
formControlName="currentPassword" />
|
||||
<mat-error *ngIf="currentPassword?.errors?.required">
|
||||
<span cnsl-error *ngIf="currentPassword?.errors?.required">
|
||||
{{ 'USER.PASSWORD.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
|
||||
<div class="validation between" *ngIf="this.policy">
|
||||
<app-password-complexity-view [policy]="this.policy" [password]="newPassword">
|
||||
</app-password-complexity-view>
|
||||
</div>
|
||||
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="new password" type="password" matInput
|
||||
<cnsl-form-field class="formfield" appearance="outline">
|
||||
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
||||
<input cnslInput autocomplete="off" name="new password" type="password"
|
||||
formControlName="newPassword" />
|
||||
|
||||
<mat-error *ngIf="newPassword?.errors?.required">
|
||||
<span cnsl-error *ngIf="newPassword?.errors?.required">
|
||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="formfield" appearance="outline">
|
||||
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
|
||||
<input autocomplete="off" name="password repeating" type="password" matInput
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
<cnsl-form-field class="formfield" appearance="outline">
|
||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
||||
<input cnslInput autocomplete="off" name="password repeating" type="password"
|
||||
formControlName="confirmPassword" />
|
||||
<mat-error *ngIf="confirmPassword?.errors?.notequal">
|
||||
<span cnsl-error *ngIf="confirmPassword?.errors?.notequal">
|
||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<button class="submit-button" [disabled]="passwordForm.invalid" mat-raised-button
|
||||
color="primary">{{ 'USER.PASSWORD.RESET' | translate }}</button>
|
||||
|
||||
@@ -28,6 +28,6 @@
|
||||
padding: .5rem 4rem;
|
||||
}
|
||||
|
||||
.mat-error {
|
||||
.cnsl-error {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
@@ -20,6 +18,7 @@ import { MemberCreateDialogModule } from 'src/app/modules/add-member-dialog/memb
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { ChangesModule } from 'src/app/modules/changes/changes.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
||||
import { PasswordComplexityViewModule } from 'src/app/modules/password-complexity-view/password-complexity-view.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
@@ -83,9 +82,7 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
ShowKeyDialogModule,
|
||||
MatCheckboxModule,
|
||||
HasRolePipeModule,
|
||||
MatFormFieldModule,
|
||||
UserGrantsModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
CardModule,
|
||||
@@ -104,6 +101,7 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component';
|
||||
MemberCreateDialogModule,
|
||||
TimestampToDatePipeModule,
|
||||
LocalizedDatePipeModule,
|
||||
InputModule,
|
||||
],
|
||||
})
|
||||
export class UserDetailModule { }
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<app-card *ngIf="user?.id" title="{{ 'GRANTS.USER.TITLE' | translate }}"
|
||||
description="{{'GRANTS.USER.DESCRIPTION' | translate }}">
|
||||
<app-user-grants [userId]="user.id" [context]="USERGRANTCONTEXT"
|
||||
[displayedColumns]="['select', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
|
||||
[displayedColumns]="['select', 'projectId', 'dates', 'roleNamesList']"
|
||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
|
||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
|
||||
</app-user-grants>
|
||||
@@ -102,12 +102,18 @@
|
||||
<span class="first">{{'USER.PREFERRED_LOGINNAME' | translate}}</span>
|
||||
<span class="second"><span style="display: block;">{{user.preferredLoginName}}</span></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span class="first">{{'ORG.PAGES.STATE' | translate}}</span>
|
||||
<span *ngIf="user && user.state !== undefined" class="state"
|
||||
[ngClass]="{'active': user.state === UserState.USERSTATE_ACTIVE, 'inactive': user.state === UserState.USERSTATE_INACTIVE}">{{'USER.DATA.STATE'+user.state | translate}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.membership.read']">
|
||||
<app-memberships [user]="user" [disabled]="(canWrite$ | async) == false"></app-memberships>
|
||||
</ng-template>
|
||||
|
||||
<app-changes class="changes" [changeType]="ChangeType.USER" [id]="user.id"></app-changes>
|
||||
<app-changes class="changes" [refresh]="refreshChanges$" [changeType]="ChangeType.USER" [id]="user.id">
|
||||
</app-changes>
|
||||
</div>
|
||||
</app-meta-layout>
|
||||
@@ -41,18 +41,36 @@
|
||||
|
||||
.first {
|
||||
flex: 1;
|
||||
font-size: .8rem;
|
||||
font-size: 13px;
|
||||
margin-right: .5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.second {
|
||||
font-size: .8rem;
|
||||
font-size: .13px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
margin-left: 1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.state {
|
||||
border-radius: 50vw;
|
||||
padding: 2px .5rem;
|
||||
letter-spacing: .05em;
|
||||
font-size: 11px;
|
||||
background-color: #8795a120;
|
||||
|
||||
&.active {
|
||||
background-color: #85d996;
|
||||
color: black;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
background-color: #ff8981;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||
@@ -47,6 +47,7 @@ export class UserDetailComponent implements OnInit {
|
||||
public USERGRANTCONTEXT: UserGrantContext = UserGrantContext.USER;
|
||||
|
||||
public EditDialogType: any = EditDialogType;
|
||||
public refreshChanges$: EventEmitter<void> = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
@@ -55,9 +56,11 @@ export class UserDetailComponent implements OnInit {
|
||||
public mgmtUserService: ManagementService,
|
||||
private _location: Location,
|
||||
private dialog: MatDialog,
|
||||
private router: Router,
|
||||
) { }
|
||||
|
||||
refreshUser(): void {
|
||||
this.refreshChanges$.emit();
|
||||
this.route.params.pipe(take(1)).subscribe(params => {
|
||||
const { id } = params;
|
||||
this.mgmtUserService.GetUserByID(id).then(user => {
|
||||
@@ -109,6 +112,7 @@ export class UserDetailComponent implements OnInit {
|
||||
.then((data: UserProfile) => {
|
||||
this.toast.showInfo('USER.TOAST.SAVED', true);
|
||||
this.user = Object.assign(this.user, data.toObject());
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -128,6 +132,7 @@ export class UserDetailComponent implements OnInit {
|
||||
.then((data: MachineResponse) => {
|
||||
this.toast.showInfo('USER.TOAST.SAVED', true);
|
||||
this.user = Object.assign(this.user, data.toObject());
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -138,15 +143,16 @@ export class UserDetailComponent implements OnInit {
|
||||
public resendEmailVerification(): void {
|
||||
this.mgmtUserService.ResendEmailVerification(this.user.id).then(() => {
|
||||
this.toast.showInfo('USER.TOAST.EMAILVERIFICATIONSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public resendPhoneVerification(): void {
|
||||
console.log('resend phone ver', this.user.id);
|
||||
this.mgmtUserService.ResendPhoneVerification(this.user.id).then(() => {
|
||||
this.toast.showInfo('USER.TOAST.PHONEVERIFICATIONSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
@@ -201,6 +207,7 @@ export class UserDetailComponent implements OnInit {
|
||||
this.mgmtUserService.SendSetPasswordNotification(this.user.id, NotificationType.NOTIFICATIONTYPE_EMAIL)
|
||||
.then(() => {
|
||||
this.toast.showInfo('USER.TOAST.PASSWORDNOTIFICATIONSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
@@ -220,7 +227,10 @@ export class UserDetailComponent implements OnInit {
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
this.mgmtUserService.DeleteUser(this.user.id).then(() => {
|
||||
this.navigateBack();
|
||||
const params: Params = {
|
||||
'deferredReload': true,
|
||||
};
|
||||
this.router.navigate(['/users/list', this.user.human ? 'humans' : 'machines'], { queryParams: params });
|
||||
this.toast.showInfo('USER.TOAST.DELETED', true);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
@@ -238,6 +248,7 @@ export class UserDetailComponent implements OnInit {
|
||||
if (resp.send && this.user.id) {
|
||||
this.mgmtUserService.ResendInitialMail(this.user.id, resp.email ?? '').then(() => {
|
||||
this.toast.showInfo('USER.TOAST.INITEMAILSENT', true);
|
||||
this.refreshChanges$.emit();
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
|
||||
@@ -4,9 +4,7 @@ import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
@@ -15,6 +13,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { AvatarModule } from 'src/app/modules/avatar/avatar.module';
|
||||
import { CardModule } from 'src/app/modules/card/card.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { SharedModule } from 'src/app/modules/shared/shared.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
@@ -48,8 +47,7 @@ import { UserTableComponent } from './user-table/user-table.component';
|
||||
TranslateModule,
|
||||
SharedModule,
|
||||
RefreshTableModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
InputModule,
|
||||
],
|
||||
exports: [
|
||||
UserListComponent,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
|
||||
[timestamp]="userResult?.viewTimestamp" [selection]="selection"
|
||||
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes">
|
||||
<mat-form-field @appearfade *ngIf="userSearchKey != undefined" actions class="filtername">
|
||||
<mat-label>{{'USER.PAGES.FILTER' | translate}}</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)"
|
||||
<cnsl-form-field @appearfade *ngIf="userSearchKey != undefined" actions class="filtername">
|
||||
<input cnslInput (keyup)="applyFilter($event)"
|
||||
[placeholder]="('USER.TABLE.FILTER.' + userSearchKey.toString()) | translate" #input>
|
||||
</mat-form-field>
|
||||
</cnsl-form-field>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['user.write']" actions>
|
||||
<button (click)="deactivateSelectedUsers()" matTooltip="{{'USER.TABLE.DEACTIVATE' | translate}}"
|
||||
@@ -119,7 +118,9 @@
|
||||
<ng-container matColumnDef="state">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.DATA.STATE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
||||
{{ 'USER.DATA.STATE'+user.state | translate }} </td>
|
||||
<span class="state"
|
||||
[ngClass]="{'active': user.state === UserState.USERSTATE_ACTIVE, 'inactive': user.state === UserState.USERSTATE_INACTIVE}">{{ 'USER.DATA.STATE'+user.state | translate }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" stickyEnd>
|
||||
@@ -137,6 +138,10 @@
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"> </tr>
|
||||
|
||||
</table>
|
||||
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{'USER.TABLE.EMPTY' | translate}}</span>
|
||||
</div>
|
||||
<mat-paginator #paginator class="paginator" [length]="userResult?.totalResult || 0" [pageSize]="10"
|
||||
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></mat-paginator>
|
||||
</div>
|
||||
@@ -144,7 +149,7 @@
|
||||
|
||||
<ng-template #templateRef let-key="key">
|
||||
<button class="search-button" mat-icon-button (click)="setFilter(key)">
|
||||
<mat-icon *ngIf="this.userSearchKey != key">search</mat-icon>
|
||||
<mat-icon *ngIf="this.userSearchKey == key">search_off</mat-icon>
|
||||
<mat-icon class="icon" *ngIf="this.userSearchKey != key">search</mat-icon>
|
||||
<mat-icon class="icon" *ngIf="this.userSearchKey == key">search_off</mat-icon>
|
||||
</button>
|
||||
</ng-template>
|
||||
@@ -7,21 +7,27 @@
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: .5rem;
|
||||
outline: none;
|
||||
padding-left: .5rem;
|
||||
padding-right: .5rem;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
padding-right: 1rem;
|
||||
padding-right: .5rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.search-button,
|
||||
.dlt-button {
|
||||
th {
|
||||
.search-button {
|
||||
visibility: hidden;
|
||||
width: 30px;
|
||||
|
||||
.icon {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
@@ -33,17 +39,16 @@
|
||||
}
|
||||
|
||||
tr {
|
||||
.dlt-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.dlt-button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selection {
|
||||
width: 50px;
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +65,25 @@
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.state {
|
||||
border-radius: 50vw;
|
||||
padding: 2px .5rem;
|
||||
letter-spacing: .05em;
|
||||
font-size: 11px;
|
||||
background-color: #8795a120;
|
||||
|
||||
&.active {
|
||||
background-color: #85d996;
|
||||
color: black;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
background-color: #ff8981;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { enterAnimations } from 'src/app/animations';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import { UserView } from 'src/app/proto/generated/auth_pb';
|
||||
import { SearchMethod, UserSearchKey, UserSearchQuery, UserSearchResponse } from 'src/app/proto/generated/management_pb';
|
||||
import {
|
||||
SearchMethod,
|
||||
UserSearchKey,
|
||||
UserSearchQuery,
|
||||
UserSearchResponse,
|
||||
UserState,
|
||||
} from 'src/app/proto/generated/management_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
@@ -30,7 +37,7 @@ export class UserTableComponent implements OnInit {
|
||||
@Input() refreshOnPreviousRoutes: string[] = [];
|
||||
@Input() disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
@ViewChild('input') public filter!: MatInput;
|
||||
@ViewChild('input') public filter!: Input;
|
||||
public dataSource: MatTableDataSource<UserView.AsObject> = new MatTableDataSource<UserView.AsObject>();
|
||||
public selection: SelectionModel<UserView.AsObject> = new SelectionModel<UserView.AsObject>(true, []);
|
||||
public userResult!: UserSearchResponse.AsObject;
|
||||
@@ -41,11 +48,14 @@ export class UserTableComponent implements OnInit {
|
||||
@Output() public changedSelection: EventEmitter<Array<UserView.AsObject>> = new EventEmitter();
|
||||
UserSearchKey: any = UserSearchKey;
|
||||
|
||||
public UserState: any = UserState;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private userService: ManagementService,
|
||||
private toast: ToastService,
|
||||
private dialog: MatDialog,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
this.selection.changed.subscribe(() => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
@@ -53,7 +63,14 @@ export class UserTableComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getData(10, 0, this.userType);
|
||||
this.route.queryParams.pipe(take(1)).subscribe(params => {
|
||||
this.getData(10, 0, this.userType);
|
||||
if (params.deferredReload) {
|
||||
setTimeout(() => {
|
||||
this.getData(10, 0, this.userType);
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
@@ -78,7 +95,12 @@ export class UserTableComponent implements OnInit {
|
||||
return this.userService.DeactivateUser(value.id);
|
||||
})).then(() => {
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDDEACTIVATED', true);
|
||||
this.getData(10, 0, this.userType);
|
||||
this.selection.clear();
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -87,7 +109,12 @@ export class UserTableComponent implements OnInit {
|
||||
return this.userService.ReactivateUser(value.id);
|
||||
})).then(() => {
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDREACTIVATED', true);
|
||||
this.getData(10, 0, this.userType);
|
||||
this.selection.clear();
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user