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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* 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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* 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] <support@github.com>

Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Max Peintner <max@caos.ch>

* 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] <support@github.com>

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 <florian@caos.ch>

* Update console/src/assets/i18n/en.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/en.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/en.json

Co-authored-by: Florian Forster <florian@caos.ch>

* finnaly fix fckntimestamp picker

* optional key expiry

* small state badge

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

* Update console/src/assets/i18n/de.json

Co-authored-by: Florian Forster <florian@caos.ch>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Silvan <silvan.reusser@gmail.com>
Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
Max Peintner
2020-11-25 16:53:14 +01:00
committed by GitHub
parent 42f50de790
commit ae26999834
191 changed files with 3622 additions and 2109 deletions

View File

@@ -1,9 +1,9 @@
<div class="max-width-container">
<h2>{{ 'GRANTS.TITLE' | translate }}</h2>
<h1>{{ 'GRANTS.TITLE' | translate }}</h1>
<p class="desc">{{'GRANTS.DESC' | translate }}</p>
<app-user-grants
[displayedColumns]="['select', 'user', 'org', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
<app-user-grants [displayedColumns]="['select', 'user', 'org', 'projectId', 'dates', 'roleNamesList']"
[disableWrite]="((['user.grant.write$'] | hasRole) | async) == false"
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false">
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) == false"
[refreshOnPreviousRoutes]="['/grant-create']">
</app-user-grants>
</div>

View File

@@ -1,3 +1,7 @@
h1 {
margin-top: 0;
}
.desc {
color: var(--grey);
margin-bottom: 2rem;

View File

@@ -19,11 +19,6 @@
padding-right: 0;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
}

View File

@@ -59,7 +59,6 @@ export class IamMembersComponent {
}
public removeMemberSelection(): void {
console.log(this.selection);
Promise.all(this.selection.map(member => {
return this.adminService.RemoveIamMember(member.userId).then(() => {
this.toast.showInfo('IAM.TOAST.MEMBERREMOVED', true);

View File

@@ -19,11 +19,6 @@
padding-right: 0;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
}

View File

@@ -6,19 +6,18 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { PolicyGridModule } from 'src/app/modules/policy-grid/policy-grid.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
@@ -46,10 +45,9 @@ import { IamComponent } from './iam.component';
MatCheckboxModule,
MetaLayoutModule,
MatIconModule,
MatTabsModule,
MatTableModule,
MatPaginatorModule,
MatFormFieldModule,
InputModule,
MatSortModule,
MatTooltipModule,
ReactiveFormsModule,

View File

@@ -12,17 +12,18 @@
<ng-container *ngIf="!forSelf">
<ng-container *ngIf="currentCreateStep == 1">
<h1>{{'ORG.PAGES.ORGDETAIL_TITLE' | translate}}</h1>
<h1>{{'ORG.PAGES.ORGDETAIL_TITLE' | translate}} </h1>
<form [formGroup]="orgForm" (ngSubmit)="next()">
<div class="content">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'ORG_DETAIL.DETAIL.NAME' | translate }}</mat-label>
<input matInput formControlName="name" />
</mat-form-field>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'ORG_DETAIL.DETAIL.DOMAIN' | translate }}</mat-label>
<input matInput formControlName="domain" />
</mat-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'ORG_DETAIL.DETAIL.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'ORG_DETAIL.DETAIL.DOMAIN' | translate }}</cnsl-label>
<input cnslInput formControlName="domain" />
</cnsl-form-field>
</div>
<div class="btn-container">
@@ -42,67 +43,67 @@
<form [formGroup]="userForm" class="form">
<div class="content">
<p class="section">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
<input matInput formControlName="userName" required />
<mat-error *ngIf="userName?.invalid && userName?.errors?.required">
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'USER.PROFILE.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-form-field>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.EMAIL' | translate }}</mat-label>
<input matInput formControlName="email" required />
<mat-error *ngIf="email?.invalid && email?.errors?.required">
</span>
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}</cnsl-label>
<input cnslInput formControlName="email" required />
<span cnsl-error *ngIf="email?.invalid && email?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
<input matInput formControlName="firstName" required />
<mat-error *ngIf="firstName?.invalid && firstName?.errors?.required">
</span>
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<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="outline">
<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="outline">
<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="outline">
<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="outline">
<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="outline">
<mat-label>{{ 'USER.PROFILE.GENDER' | translate }}</mat-label>
<cnsl-form-field class="formfield" appearance="outline">
<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="outline">
<mat-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</mat-label>
</span>
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<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
<span cnsl-error
*ngIf="preferredLanguage?.invalid && preferredLanguage?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
</span>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<mat-checkbox class="checkbox" [(ngModel)]="usePassword"
[ngModelOptions]="{standalone: true}" (change)="initPwdValidators()">
@@ -116,28 +117,28 @@
</app-password-complexity-view>
<form [formGroup]="pwdForm" class="form">
<mat-form-field class="formfield" *ngIf="password" appearance="outline">
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
<input autocomplete="off" name="firstpassword" matInput
<cnsl-form-field class="formfield" *ngIf="password" appearance="outline">
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
<input cnslInput autocomplete="off" name="firstpassword"
formControlName="password" type="password" />
<mat-error *ngIf="password?.errors?.required">
<span cnsl-error *ngIf="password?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
</span>
</mat-form-field>
<mat-form-field class="formfield" *ngIf="confirmPassword" appearance="outline">
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
<input autocomplete="off" name="confirmPassword" matInput
</cnsl-form-field>
<cnsl-form-field class="formfield" *ngIf="confirmPassword" appearance="outline">
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
<input cnslInput autocomplete="off" name="confirmPassword"
formControlName="confirmPassword" type="password" />
<mat-error *ngIf="confirmPassword?.errors?.required">
<span cnsl-error *ngIf="confirmPassword?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.notequal">
</span>
<span cnsl-error *ngIf="confirmPassword?.errors?.notequal">
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
</mat-error>
</mat-form-field>
</span>
</cnsl-form-field>
</form>
</ng-container>
</div>
@@ -157,13 +158,14 @@
<ng-template appHasRole [appHasRole]="['org.create']">
<div *ngIf="forSelf">
<ng-container *ngIf="currentCreateStep == 1">
<h1>{{'ORG.PAGES.ORGDETAIL_TITLE' | translate}}</h1>
<h1>{{'ORG.PAGES.ORGDETAIL_TITLE_WITHOUT_DOMAIN' | translate}} </h1>
<form [formGroup]="orgForm" (ngSubmit)="createOrgForSelf()">
<div class="content">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'ORG_DETAIL.DETAIL.NAME' | translate }}</mat-label>
<input matInput formControlName="name" />
</mat-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'ORG_DETAIL.DETAIL.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
</div>
<div class="btn-container">

View File

@@ -107,8 +107,15 @@ export class OrgCreateComponent {
this.adminService
.SetUpOrg(createOrgRequest, humanRequest)
.then((data: OrgSetUpResponse) => {
this.router.navigate(['orgs', data.toObject().org?.id]);
.then((org: OrgSetUpResponse) => {
this.router.navigate(['/org/overview']);
// const orgResp = org.getOrg();
// if (orgResp) {
// this.authService.setActiveOrg(orgResp.toObject());
// this.router.navigate(['/org']);
// } else {
// this.router.navigate(['/org', 'overview']);
// }
})
.catch(error => {
this.toast.showError(error);
@@ -193,7 +200,12 @@ export class OrgCreateComponent {
public createOrgForSelf(): void {
if (this.name && this.name.value) {
this.mgmtService.CreateOrg(this.name.value).then((org) => {
this.router.navigate(['orgs', org.toObject().id]);
this.router.navigate(['/org/overview']);
// const newOrg = org.toObject();
// setTimeout(() => {
// this.authService.setActiveOrg(newOrg);
// this.router.navigate(['/org']);
// }, 1000);
}).catch(error => {
this.toast.showError(error);
});

View File

@@ -3,13 +3,12 @@ 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 { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { PasswordComplexityViewModule } from 'src/app/modules/password-complexity-view/password-complexity-view.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
@@ -23,8 +22,7 @@ import { OrgCreateComponent } from './org-create.component';
CommonModule,
FormsModule,
ReactiveFormsModule,
MatInputModule,
MatFormFieldModule,
InputModule,
MatButtonModule,
MatIconModule,
MatSelectModule,

View File

@@ -2,10 +2,10 @@
<div mat-dialog-content>
<p class="desc"> {{'ORG.DOMAINS.ADD.DESCRIPTION' | translate}}</p>
<mat-form-field label="Domain" required="true" class="form-field" appearance="outline">
<mat-label>Domain</mat-label>
<input matInput [(ngModel)]="newdomain" />
</mat-form-field>
<cnsl-form-field label="Domain" required="true" class="form-field" appearance="outline">
<cnsl-label>Domain</cnsl-label>
<input cnslInput [(ngModel)]="newdomain" />
</cnsl-form-field>
</div>
<div mat-dialog-actions class="action">
<button mat-button (click)="closeDialog()">

View File

@@ -2,9 +2,8 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { AddDomainDialogComponent } from './add-domain-dialog.component';
@@ -14,8 +13,7 @@ import { AddDomainDialogComponent } from './add-domain-dialog.component';
CommonModule,
TranslateModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
InputModule,
FormsModule,
],
})

View File

@@ -38,7 +38,6 @@
color="primary">{{ 'ORG.PAGES.DOWNLOAD_FILE' | translate }}</button>
<button color="primary" class="verify-button" type="submit" mat-raised-button (click)="validate()">
<span>{{ 'ACTIONS.VERIFY' | translate }}</span>
<mat-spinner class="spinner" *ngIf="!validating" diameter="20" mode="indeterminate"></mat-spinner>
</button>
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
</div>

View File

@@ -10,7 +10,6 @@
.domain {
display: flex;
align-items: center;
padding: .5rem 0;
flex-wrap: wrap;
.title {
@@ -55,6 +54,7 @@
&:hover {
.rem-button {
visibility: visible;
transition: none;
}
}
}

View File

@@ -5,11 +5,11 @@
<app-refresh-table *ngIf="dataSource" (refreshed)="refresh()" [dataSize]="dataSource.data.length"
[loading]="loading$ | async">
<mat-form-field @appearfade *ngIf="orgSearchKey != undefined" actions class="filter">
<mat-label>{{'ORG.PAGES.FILTER' | translate}}</mat-label>
<input matInput (keyup)="applyFilter($event)" placeholder="{{'ORG.PAGES.FILTERPLACEHOLDER' | translate}}"
<cnsl-form-field @appearfade *ngIf="orgSearchKey != undefined" actions class="filter">
<cnsl-label>{{'ORG.PAGES.FILTER' | translate}}</cnsl-label>
<input cnslInput (keyup)="applyFilter($event)" placeholder="{{'ORG.PAGES.FILTERPLACEHOLDER' | translate}}"
#input>
</mat-form-field>
</cnsl-form-field>
<table [dataSource]="dataSource" mat-table class="table" matSort aria-label="Elements">

View File

@@ -23,11 +23,6 @@ h1 {
padding-right: 0;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
.pointer {

View File

@@ -1,5 +1,4 @@
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { MatInput } from '@angular/material/input';
import { AfterViewInit, Component, Input, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
@@ -23,7 +22,7 @@ export class OrgListComponent implements AfterViewInit {
@ViewChild(MatPaginator) public paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild('input') public filter!: MatInput;
@ViewChild('input') public filter!: Input;
public dataSource!: MatTableDataSource<Org.AsObject>;
public displayedColumns: string[] = ['select', 'id', 'name'];

View File

@@ -2,15 +2,14 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } 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 { MatPaginatorModule } from '@angular/material/paginator';
import { MatRadioModule } from '@angular/material/radio';
import { MatSortModule } from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
@@ -34,8 +33,7 @@ import { OrgListComponent } from './org-list.component';
MatButtonModule,
MatTooltipModule,
MatRadioModule,
MatFormFieldModule,
MatInputModule,
InputModule,
FormsModule,
],
})

View File

@@ -1,6 +1,6 @@
<form>
<mat-form-field appearance="outline" class="full-width">
<mat-label>Role Name</mat-label>
<cnsl-form-field appearance="outline" class="full-width">
<cnsl-label>Role Name</cnsl-label>
<mat-select [formControl]="myControl" multiple>
<mat-option *ngIf="isLoading" class="is-loading">
@@ -10,5 +10,5 @@
{{ role }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
</form>

View File

@@ -2,12 +2,11 @@ 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 { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { OrgMemberRolesAutocompleteComponent } from './org-member-roles-autocomplete.component';
@@ -17,9 +16,8 @@ import { OrgMemberRolesAutocompleteComponent } from './org-member-roles-autocomp
CommonModule,
MatButtonModule,
MatSelectModule,
MatFormFieldModule,
InputModule,
MatIconModule,
MatInputModule,
ReactiveFormsModule,
MatProgressSpinnerModule,
FormsModule,

View File

@@ -4,9 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
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 { MatMenuModule } from '@angular/material/menu';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTabsModule } from '@angular/material/tabs';
@@ -17,6 +15,7 @@ import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { MemberCreateDialogModule } from 'src/app/modules/add-member-dialog/member-create-dialog.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { PolicyGridModule } from 'src/app/modules/policy-grid/policy-grid.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
@@ -37,8 +36,7 @@ import { OrgsRoutingModule } from './orgs-routing.module';
OrgsRoutingModule,
FormsModule,
HasRoleModule,
MatFormFieldModule,
MatInputModule,
InputModule,
MatButtonModule,
MatDialogModule,
CardModule,

View File

@@ -21,18 +21,18 @@
<ng-template matStepLabel>{{'APP.OIDC.NAMEANDTYPESECTION' | translate}}</ng-template>
<p class="step-title">{{'APP.OIDC.TITLEFIRST' | translate}}</p>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.NAME' | translate }}</mat-label>
<input matInput formControlName="name" />
<mat-error *ngIf="name?.errors?.required">{{'PROJECT.APP.NAMEREQUIRED' | translate}}</mat-error>
</mat-form-field>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
<span cnsl-error *ngIf="name?.errors?.required">{{'PROJECT.APP.NAMEREQUIRED' | translate}}</span>
</cnsl-form-field>
<p class="step-title">{{'APP.OIDC.TYPETITLE' | translate}}</p>
<mat-radio-group color="primary" aria-labelledby="radio-group-label" class="radio-group"
formControlName="applicationType">
<mat-radio-button class="radio-button" *ngFor="let type of oidcAppTypes | keyvalue"
[value]="type.value">
<div>{{'APP.OIDC.APPTYPE'+type.key | translate}}</div>
<div>{{('APP.OIDC.APPTYPE'+type.key.toString()) | translate}}</div>
</mat-radio-button>
</mat-radio-group>
<div class="actions">
@@ -89,19 +89,24 @@
<p class="step-description" *ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<mat-form-field appearance="outline" class="full-width">
<mat-label>{{ 'APP.OIDC.REDIRECT' | translate }}</mat-label>
<mat-chip-list #chipRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.redirectUrisList" selected removable
[matTooltip]="!uri.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!uri.startsWith('https://') ? 'warn': 'white'" (removed)="removeUri(uri, 'REDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipRedirectList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true" [formControl]="redirectControl"
(matChipInputTokenEnd)="addUri($event, 'REDIRECT')">
</mat-chip-list>
</mat-form-field>
<form class="chip-form" (ngSubmit)="addUri(redInput, 'REDIRECT')">
<cnsl-form-field appearance="outline" class="full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<input #redInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="redirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list #chipRedirectList aria-label="uri selection">
<mat-chip #redInput class="chip" *ngFor="let uri of oidcApp.redirectUrisList" selected removable
[matTooltip]="!uri?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!uri?.startsWith('https://') ? 'warn': 'white'" (removed)="removeUri(uri, 'REDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="redirectControl.invalid" class="error">{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<p class="step-title">{{'APP.OIDC.POSTREDIRECTTITLE' | translate}}</p>
@@ -112,20 +117,25 @@
*ngIf="oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || oidcApp.applicationType === OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<mat-form-field appearance="outline" class="full-width">
<mat-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</mat-label>
<mat-chip-list #chipPostRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.postLogoutRedirectUrisList"
[matTooltip]="!uri.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
removable (removed)="removeUri(uri, 'POSTREDIRECT')" selected
[color]="!uri.startsWith('https://') ? 'warn': 'white'">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipPostRedirectList" [formControl]="postRedirectControl"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addUri($event, 'POSTREDIRECT')">
</mat-chip-list>
</mat-form-field>
<form class="chip-form" (ngSubmit)="addUri(postInput, 'POSTREDIRECT')">
<cnsl-form-field appearance="outline" class="full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<input #postInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="postRedirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list #chipPostRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.postLogoutRedirectUrisList"
[matTooltip]="!uri?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
removable (removed)="removeUri(uri, 'POSTREDIRECT')" selected
[color]="!uri?.startsWith('https://') ? 'warn': 'white'">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<p *ngIf="postRedirectControl.invalid" class="error">{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<div class="actions">
@@ -223,71 +233,72 @@
<div *ngIf="devmode" class="dev">
<form [formGroup]="form" (ngSubmit)="saveOIDCApp()">
<div class="content">
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.NAME' | translate }}</mat-label>
<input matInput formControlName="name" />
</mat-form-field>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.APPTYPE' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.APPTYPE' | translate }}</cnsl-label>
<mat-select formControlName="applicationType">
<mat-option *ngFor="let type of oidcAppTypes" [value]="type">
{{ 'APP.OIDC.APPTYPE'+type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.GRANT' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.GRANT' | translate }}</cnsl-label>
<mat-select formControlName="grantTypesList" multiple>
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant.type">
{{ ('APP.OIDC.GRANT' + grant.type) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.RESPONSE' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.RESPONSE' | translate }}</cnsl-label>
<mat-select formControlName="responseTypesList" multiple>
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type.type">
{{ 'APP.OIDC.RESPONSE'+type.type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.AUTHMETHOD' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.AUTHMETHOD' | translate }}</cnsl-label>
<mat-select formControlName="authMethodType">
<mat-option *ngFor="let type of oidcAuthMethodType" [value]="type.type">
{{ 'APP.OIDC.AUTHMETHOD'+type.type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield full-width">
<mat-label>{{ 'APP.OIDC.REDIRECT' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<mat-chip-list #chipRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.redirectUrisList" removable
(removed)="removeUri(uri, 'REDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipRedirectList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addUri($event, 'REDIRECT')">
<input cnslInput [matChipInputFor]="chipRedirectList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addUri($event, 'REDIRECT')">
</mat-chip-list>
</mat-form-field>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield full-width">
<mat-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</mat-label>
<cnsl-form-field appearance="outline" class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<mat-chip-list #chipPostRedirectList aria-label="uri selection">
<mat-chip class="chip" *ngFor="let uri of oidcApp.postLogoutRedirectUrisList" removable
(removed)="removeUri(uri, 'POSTREDIRECT')">
{{uri}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipPostRedirectList"
<input cnslInput [matChipInputFor]="chipPostRedirectList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addUri($event, 'POSTREDIRECT')">
</mat-chip-list>
</mat-form-field>
</cnsl-form-field>
</div>

View File

@@ -56,8 +56,9 @@ p.desc {
margin: 0 -1.5rem;
.step-title {
font-size: 1.2rem;
color: var(--grey);
font-size: 1rem;
text-transform: uppercase;
letter-spacing: .05em;
}
.step-description {
@@ -65,12 +66,31 @@ p.desc {
color: var(--grey);
}
.chip-form {
width: 100%;
display: flex;
align-items: center;
.formfield {
flex: 1;
}
button {
margin-top: 1rem;
}
}
.error {
font-size: 13px;
color: #f44336;
margin-top: 0;
}
.chip {
border-radius: 4px;
height: 40px;
}
.chip[color='white'] {
background-color: #fafafa;
}

View File

@@ -1,8 +1,7 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { MatChipInputEvent } from '@angular/material/chips';
import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Subscription } from 'rxjs';
@@ -216,9 +215,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
}
}
public addUri(event: MatChipInputEvent, target: string): void {
const input = event.input;
const value = event.value.trim();
public addUri(input: any, target: string): void {
const value = input.value.trim();
if (value !== '') {
if (target === 'REDIRECT' && this.redirectControl.valid) {

View File

@@ -1,182 +1,207 @@
<div class="max-width-container">
<div class="head">
<a [routerLink]="['/projects', projectId]" mat-icon-button>
<mat-icon class="icon">arrow_back</mat-icon>
</a>
<h1>{{ 'APP.PAGES.TITLE' | translate }} {{app?.name}}</h1>
<app-meta-layout>
<div class="max-width-container">
<div class="head">
<a [routerLink]="['/projects', projectId]" mat-icon-button>
<mat-icon class="icon">arrow_back</mat-icon>
</a>
<h1>{{ 'APP.PAGES.TITLE' | translate }} {{app?.name}}</h1>
<p class="desc">{{ 'APP.PAGES.DESCRIPTION' | translate }}</p>
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
</div>
<span *ngIf="errorMessage" class="err-container">{{errorMessage}}</span>
<app-card title="{{ 'APP.PAGES.DETAIL.TITLE' | translate }}" *ngIf="app">
<form [formGroup]="appNameForm" (ngSubmit)="saveApp()">
<div class="content">
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
<mat-button-toggle [value]="AppState.APPSTATE_INACTIVE"
matTooltip="{{ 'ACTIONS.DEACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_INACTIVE | translate}}
</mat-button-toggle>
<mat-button-toggle [value]="AppState.APPSTATE_ACTIVE"
matTooltip="{{ 'ACTIONS.REACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_ACTIVE | translate}}
</mat-button-toggle>
</mat-button-toggle-group>
<mat-form-field class="formfield">
<mat-label>{{ 'APP.NAME' | translate }}</mat-label>
<input matInput formControlName="name" />
</mat-form-field>
<p class="docs-line" *ngIf="docs?.discoveryEndpoint">Discovery Endpoint: {{docs.discoveryEndpoint}}</p>
<p class="docs-line" *ngIf="docs?.issuer">Issuer: {{docs.issuer}}</p>
</div>
<div class="btn-container">
<button class="submit-button" type="submit" color="primary"
[disabled]="appNameForm.invalid || name?.disabled"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</form>
</app-card>
<app-card title="{{ 'APP.OIDC.TITLE' | translate }}" *ngIf="app && app.oidcConfig">
<div card-actions *ngIf="app?.oidcConfig?.authMethodType !== OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE">
<button [disabled]="!canWrite" mat-stroked-button
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
<p class="desc">{{ 'APP.PAGES.DESCRIPTION' | translate }}</p>
<p *ngIf="isZitadel" class="zitadel-warning">{{'PROJECT.PAGES.ZITADELPROJECT' | translate}}</p>
</div>
<div class="compliance">
<p class="problem" *ngFor="let problem of app.oidcConfig.complianceProblemsList">
{{problem.localizedMessage}}
</p>
</div>
<form *ngIf="appForm" [formGroup]="appForm" (ngSubmit)="saveOIDCApp()">
<div class="content">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'APP.OIDC.CLIENTID' | translate }}</mat-label>
<input matInput formControlName="clientId" />
</mat-form-field>
<span *ngIf="errorMessage" class="err-container">{{errorMessage}}</span>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'APP.OIDC.RESPONSE' | translate }}</mat-label>
<mat-select formControlName="responseTypesList" multiple>
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type">
{{ 'APP.OIDC.RESPONSE'+type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<app-card title="{{ 'APP.PAGES.DETAIL.TITLE' | translate }}" *ngIf="app">
<form [formGroup]="appNameForm" (ngSubmit)="saveApp()">
<div class="content">
<mat-button-toggle-group formControlName="state" class="toggle" (change)="changeState($event)">
<mat-button-toggle [value]="AppState.APPSTATE_INACTIVE"
matTooltip="{{ 'ACTIONS.DEACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_INACTIVE | translate}}
</mat-button-toggle>
<mat-button-toggle [value]="AppState.APPSTATE_ACTIVE"
matTooltip="{{ 'ACTIONS.REACTIVATE' | translate}}">
{{'APP.PAGES.DETAIL.STATE.'+AppState.APPSTATE_ACTIVE | translate}}
</mat-button-toggle>
</mat-button-toggle-group>
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'APP.OIDC.GRANT' | translate }}</mat-label>
<mat-select formControlName="grantTypesList" multiple>
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant">
{{ 'APP.OIDC.GRANT'+grant | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.APPTYPE' | translate }}</mat-label>
<mat-select formControlName="applicationType">
<mat-option *ngFor="let type of oidcAppTypes" [value]="type">
{{ 'APP.OIDC.APPTYPE'+type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<p class="docs-line" *ngIf="docs?.discoveryEndpoint">Discovery Endpoint: {{docs.discoveryEndpoint}}
</p>
<p class="docs-line" *ngIf="docs?.issuer">Issuer: {{docs.issuer}}</p>
</div>
<div class="btn-container">
<button class="submit-button" type="submit" color="primary"
[disabled]="appNameForm.invalid || name?.disabled"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</form>
</app-card>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.AUTHMETHOD' | translate }}</mat-label>
<mat-select formControlName="authMethodType">
<mat-option *ngFor="let type of oidcAuthMethodType" [value]="type">
{{ 'APP.OIDC.AUTHMETHOD'+type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<app-card title="{{ 'APP.OIDC.TITLE' | translate }}" *ngIf="app && app.oidcConfig">
<div card-actions *ngIf="app?.oidcConfig?.authMethodType !== OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE">
<button [disabled]="!canWrite" mat-stroked-button
(click)="regenerateOIDCClientSecret()">{{'APP.OIDC.REGENERATESECRET' | translate}}</button>
</div>
<div class="divider"></div>
<div class="compliance">
<p class="problem" *ngFor="let problem of app.oidcConfig.complianceProblemsList">
{{problem.localizedMessage}}
</p>
</div>
<form *ngIf="appForm" [formGroup]="appForm" (ngSubmit)="saveOIDCApp()">
<div class="content">
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'APP.OIDC.CLIENTID' | translate }}</cnsl-label>
<input cnslInput formControlName="clientId" />
</cnsl-form-field>
<p class="full-width section-title">{{'APP.OIDC.TOKENSECTIONTITLE' | translate}}</p>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'APP.OIDC.RESPONSE' | translate }}</cnsl-label>
<mat-select formControlName="responseTypesList" multiple>
<mat-option *ngFor="let type of oidcResponseTypes" [value]="type">
{{ 'APP.OIDC.RESPONSE'+type | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'APP.OIDC.TOKENTYPE' | translate }}</mat-label>
<mat-select formControlName="accessTokenType">
<mat-option *ngFor="let type of oidcTokenTypes" [value]="type">
{{ 'APP.OIDC.TOKENTYPE'+type | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'APP.OIDC.GRANT' | translate }}</cnsl-label>
<mat-select formControlName="grantTypesList" multiple>
<mat-option *ngFor="let grant of oidcGrantTypes" [value]="grant">
{{ 'APP.OIDC.GRANT'+grant | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<mat-checkbox *ngIf="accessTokenType?.value === OIDCTokenType.OIDCTOKENTYPE_JWT" class="full-width"
formControlName="accessTokenRoleAssertion">
{{'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate}}</mat-checkbox>
<p class="full-width desc">{{'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
<mat-checkbox class="full-width" formControlName="idTokenRoleAssertion">
{{'APP.OIDC.IDTOKENROLEASSERTION' | translate}}</mat-checkbox>
<p class="full-width desc">{{'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.APPTYPE' | translate }}</cnsl-label>
<mat-select formControlName="applicationType">
<mat-option *ngFor="let type of oidcAppTypes" [value]="type">
{{ 'APP.OIDC.APPTYPE'+type | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<div class="divider"></div>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.AUTHMETHOD' | translate }}</cnsl-label>
<mat-select formControlName="authMethodType">
<mat-option *ngFor="let type of oidcAuthMethodType" [value]="type">
{{ 'APP.OIDC.AUTHMETHOD'+type | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<p class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</p>
<div class="divider"></div>
<mat-slide-toggle color="primary" class="devmode" formControlName="devMode" name="devMode">
{{ 'APP.OIDC.DEVMODE' | translate }}
</mat-slide-toggle>
<p class="full-width section-title">{{'APP.OIDC.TOKENSECTIONTITLE' | translate}}</p>
<p class="step-description" style="margin-bottom: 2rem;">{{'APP.OIDC.DEVMODEDESC' | translate}}</p>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</p>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'APP.OIDC.TOKENTYPE' | translate }}</cnsl-label>
<mat-select formControlName="accessTokenType">
<mat-option *ngFor="let type of oidcTokenTypes" [value]="type">
{{ 'APP.OIDC.TOKENTYPE'+type | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<mat-form-field class="formfield full-width" appearance="outline">
<mat-label>{{ 'APP.OIDC.REDIRECT' | translate }}</mat-label>
<mat-chip-list [disabled]="!canWrite" #chipRedirectList>
<mat-checkbox *ngIf="accessTokenType?.value === OIDCTokenType.OIDCTOKENTYPE_JWT" class="full-width"
formControlName="accessTokenRoleAssertion" color="primary">
{{'APP.OIDC.ACCESSTOKENROLEASSERTION' | translate}}</mat-checkbox>
<p class="full-width desc">{{'APP.OIDC.ACCESSTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
<mat-checkbox class="full-width" formControlName="idTokenRoleAssertion" color="primary">
{{'APP.OIDC.IDTOKENROLEASSERTION' | translate}}</mat-checkbox>
<p class="full-width desc">{{'APP.OIDC.IDTOKENROLEASSERTION_DESCRIPTION' | translate}}</p>
<div class="divider"></div>
<p class="full-width section-title">{{'APP.OIDC.REDIRECTSECTIONTITLE' | translate}}</p>
<mat-slide-toggle color="primary" class="devmode" formControlName="devMode" name="devMode">
{{ 'APP.OIDC.DEVMODE' | translate }}
</mat-slide-toggle>
<p class="step-description" style="margin-bottom: 2rem;">{{'APP.OIDC.DEVMODEDESC' | translate}}</p>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE">
{{'APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate}}</p>
<p class="step-description"
*ngIf="applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB || applicationType?.value == OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT">
{{'APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate}}</p>
<form class="chip-form" (ngSubmit)="add(redInput, RedirectType.REDIRECT)">
<cnsl-form-field class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.REDIRECT' | translate }}</cnsl-label>
<input #redInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="redirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list class="chiplist formfield full-width" [disabled]="!canWrite" #chipRedirectList>
<mat-chip class="chip" *ngFor="let redirect of redirectUrisList" selected
[matTooltip]="!redirect.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect.startsWith('https://') ? 'warn': 'green'"
[matTooltip]="!redirect?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect?.startsWith('https://') ? 'warn': 'green'"
(removed)="remove(redirect, RedirectType.REDIRECT)">
{{redirect}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipRedirectList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur" [formControl]="redirectControl"
(matChipInputTokenEnd)="add($event, RedirectType.REDIRECT)">
</mat-chip-list>
</mat-form-field>
<p *ngIf="redirectControl.value && redirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<p *ngIf="redirectControl.value && redirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<mat-form-field class="formfield full-width" appearance="outline">
<mat-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</mat-label>
<mat-chip-list [disabled]="!canWrite" #chipPostRedirectList>
<form class="chip-form" (ngSubmit)="add(postInput, RedirectType.POSTREDIRECT)">
<cnsl-form-field class="formfield full-width">
<cnsl-label>{{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }}</cnsl-label>
<input #postInput cnslInput placeholder="{{'APP.OIDC.COMMAORENTERSEPERATION' | translate}}"
[formControl]="postRedirectControl">
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</form>
<mat-chip-list class="chiplist formfield full-width" [disabled]="!canWrite" #chipPostRedirectList>
<mat-chip class="chip" *ngFor="let redirect of postLogoutRedirectUrisList" selected
(removed)="remove(redirect, RedirectType.POSTREDIRECT)"
[matTooltip]="!redirect.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect.startsWith('https://') ? 'warn': 'green'">
[matTooltip]="!redirect?.startsWith('https://') ? ('APP.OIDC.UNSECUREREDIRECT' | translate): ''"
[color]="!redirect?.startsWith('https://') ? 'warn': 'green'">
{{redirect}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input [matChipInputFor]="chipPostRedirectList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event, RedirectType.POSTREDIRECT)"
[formControl]="postRedirectControl">
</mat-chip-list>
</mat-form-field>
<p *ngIf="postRedirectControl.value && postRedirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
<p *ngIf="postRedirectControl.value && postRedirectControl.invalid" class="error">
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
</div>
<div class="btn-container">
<button class="submit-button" type="submit" color="primary"
[disabled]="appForm.invalid || !canWrite"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</form>
</app-card>
</div>
<div class="side" metainfo>
<div class="details">
<div class="row">
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
<span *ngIf="app && app.state !== undefined"
[ngClass]="{'active': app.state === AppState.APPSTATE_ACTIVE, 'inactive': app.state === AppState.APPSTATE_INACTIVE}"
class="state">{{'APP.PAGES.DETAIL.STATE.'+app.state | translate}}</span>
</div>
<div class="btn-container">
</div>
<button class="submit-button" type="submit" color="primary" [disabled]="appForm.invalid || !canWrite"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</form>
</app-card>
</div>
<app-changes *ngIf="app" [changeType]="ChangeType.APP" [id]="projectId" [secId]="app.id"></app-changes>
</div>
</app-meta-layout>

View File

@@ -60,6 +60,24 @@
}
}
.chiplist {
margin-bottom: 1rem;
}
.chip-form {
width: 100%;
display: flex;
align-items: center;
.formfield {
flex: 1;
}
button {
margin-top: 1rem;
}
}
.section-title {
margin-bottom: 1.5rem;
}
@@ -103,7 +121,7 @@
.toggle {
outline: none;
align-self: flex-start;
margin-bottom: 1rem;
margin-top: 1rem;
margin-right: 1rem;
border-radius: .5rem;
@@ -127,6 +145,11 @@
}
}
.chip {
border-radius: 4px;
height: 40px;
}
.chip[color='green'] {
background-color: #56a392 !important;
}
@@ -137,3 +160,54 @@
height: 1px;
background-color: var(--grey);
}
.side {
.details {
margin-bottom: 1rem;
border-bottom: 1px solid #81868a40;
padding-bottom: 1rem;
.row {
display: flex;
margin-bottom: .5rem;
align-items: center;
.first {
flex: 1;
font-size: 13px;
margin-right: .5rem;
}
.fill-space {
flex: 1;
}
.state {
border-radius: 50vw;
padding: 2px .5rem;
letter-spacing: .05em;
font-size: 13px;
background-color: #8795a120;
&.active {
background-color: #85d996;
color: black;
}
&.inactive {
background-color: #ff8981;
color: black;
}
}
}
}
.mat-tab-label {
min-width: 100px !important;
}
.flex-col {
display: flex;
flex-direction: column;
}
}

View File

@@ -3,12 +3,12 @@ import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatButtonToggleChange } from '@angular/material/button-toggle';
import { MatChipInputEvent } from '@angular/material/chips';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Subscription } from 'rxjs';
import { take } from 'rxjs/operators';
import { ChangeType } from 'src/app/modules/changes/changes.component';
import {
Application,
AppState,
@@ -91,7 +91,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
public redirectControl: FormControl = new FormControl({ value: '', disabled: true });
public postRedirectControl: FormControl = new FormControl({ value: '', disabled: true });
public ChangeType: any = ChangeType;
constructor(
public translate: TranslateService,
private route: ActivatedRoute,
@@ -180,19 +180,17 @@ export class AppDetailComponent implements OnInit, OnDestroy {
}
}
public add(event: MatChipInputEvent, target: RedirectType): void {
public add(input: any, target: RedirectType): void {
if (target === RedirectType.POSTREDIRECT && this.postRedirectControl.valid) {
const input = event.input;
if (event.value !== '' && event.value !== ' ' && event.value !== '/') {
this.postLogoutRedirectUrisList.push(event.value);
if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
this.postLogoutRedirectUrisList.push(input.value);
}
if (input) {
input.value = '';
}
} else if (target === RedirectType.REDIRECT && this.redirectControl.valid) {
const input = event.input;
if (event.value !== '' && event.value !== ' ' && event.value !== '/') {
this.redirectUrisList.push(event.value);
if (input.value !== '' && input.value !== ' ' && input.value !== '/') {
this.redirectUrisList.push(input.value);
}
if (input) {
input.value = '';

View File

@@ -6,9 +6,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
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 { MatMenuModule } from '@angular/material/menu';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -21,6 +19,9 @@ import { TranslateModule } from '@ngx-translate/core';
import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { AppCreateComponent } from './app-create/app-create.component';
import { AppDetailComponent } from './app-detail/app-detail.component';
@@ -40,8 +41,6 @@ import { AppsRoutingModule } from './apps-routing.module';
TranslateModule,
ReactiveFormsModule,
HasRoleModule,
MatFormFieldModule,
MatInputModule,
MatMenuModule,
MatChipsModule,
MatIconModule,
@@ -59,6 +58,9 @@ import { AppsRoutingModule } from './apps-routing.module';
MatRadioModule,
CopyToClipboardModule,
MatSlideToggleModule,
InputModule,
MetaLayoutModule,
ChangesModule,
],
exports: [TranslateModule],
})

View File

@@ -17,7 +17,7 @@
description="{{'GRANTS.PROJECT.DESCRIPTION' | translate }}">
<app-user-grants *ngIf="projectId && grantId" [context]="UserGrantContext.GRANTED_PROJECT"
[projectId]="projectId" [grantId]="grantId"
[displayedColumns]="['select','user', 'projectId', 'creationDate', 'changeDate', 'roleNamesList']"
[displayedColumns]="['select','user', 'projectId', 'dates', 'roleNamesList']"
[disableWrite]="(['user.grant.write$','user.grant.write:'+grantId] | hasRole | async) == false"
[disableDelete]="(['user.grant.delete$','user.grant.delete:'+grantId] | hasRole | async) == false"
refreshOnPreviousRoutes="['/grant-create/project/{{projectId}}/grant/{{grantId}}']">
@@ -29,22 +29,22 @@
<div class="details">
<div class="row">
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
<span *ngIf="project && project.state !== undefined"
class="second">{{'PROJECT.STATE.'+project.state | translate}}</span>
<span *ngIf="project && project.state !== undefined" class="state"
[ngClass]="{'active': project.state === ProjectState.PROJECTSTATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECTSTATE_INACTIVE}">{{'PROJECT.STATE.'+project.state | translate}}</span>
</div>
</div>
<mat-tab-group mat-stretch-tabs class="tab-group" disablePagination="true">
<mat-tab label="Details">
<app-contributors *ngIf="project" [totalResult]="totalMemberResult" [loading]="loading$ | async"
<app-contributors *ngIf="project" [loading]="loading$ | async" [totalResult]="totalMemberResult"
[membersSubject]="membersSubject" title="{{ 'PROJECT.MEMBER.TITLE' | translate }}"
description="{{ 'PROJECT.MEMBER.TITLEDESC' | translate }}" (addClicked)="openAddMember()"
(showDetailClicked)="showDetail()" (refreshClicked)="loadMembers()"
[disabled]="(['project.grant.member.write$', 'project.grant.member.write:'+ project.projectId]| hasRole | async) == false">
[disabled]="(['project.member.write$', 'project.member.write:'+ project.projectId]| hasRole | async) == false">
</app-contributors>
</mat-tab>
<mat-tab label="{{ 'CHANGES.PROJECT.TITLE' | translate }}" class="flex-col">
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.id"></app-changes>
<app-changes *ngIf="project" [changeType]="ChangeType.PROJECT" [id]="project.projectId"></app-changes>
</mat-tab>
</mat-tab-group>
</div>

View File

@@ -53,7 +53,7 @@
.first {
flex: 1;
font-size: .8rem;
font-size: 13px;
margin-right: .5rem;
}
@@ -61,11 +61,22 @@
flex: 1;
}
.second {
font-size: .8rem;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 1rem;
.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;
}
}
}
}

View File

@@ -1,5 +1,5 @@
<div class="view-toggle">
<button (click)="changedView.emit(true)" mat-icon-button>
<button (click)="changedView.emit(true)" matTooltip="{{'PROJECT.TABLE.SHOWTABLE' | translate}}" mat-icon-button>
<i class="show list view las la-th-list"></i>
</button>
</div>

View File

@@ -3,7 +3,8 @@
</app-granted-project-grid>
<div *ngIf="!grid" class="view-toggle">
<button class="icon-button" (click)="grid = true" mat-icon-button>
<button class="icon-button" (click)="grid = true" mat-icon-button
matTooltip="{{'PROJECT.TABLE.SHOWGRID' | translate}}">
<i matTooltip="show grid view" class="las la-th-large"></i>
</button>
</div>
@@ -67,6 +68,10 @@
[routerLink]="['/granted-projects', row.projectId, 'grant', row.id]"></tr>
</table>
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
<i class="las la-exclamation"></i>
<span>{{'PROJECT.TABLE.EMPTY' | translate}}</span>
</div>
<mat-paginator class="paginator" #paginator [length]="totalResult" [pageSize]="10"
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></mat-paginator>
</div>

View File

@@ -31,11 +31,6 @@
padding-right: 0;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
}

View File

@@ -3,9 +3,7 @@ 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 { 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 { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
@@ -53,16 +52,15 @@ import { GrantedProjectsComponent } from './granted-projects.component';
HasRoleModule,
MatTableModule,
MatPaginatorModule,
MatFormFieldModule,
MatInputModule,
InputModule,
ChangesModule,
MatIconModule,
MatSelectModule,
MatButtonModule,
MatTabsModule,
MatProgressSpinnerModule,
MetaLayoutModule,
MatProgressBarModule,
MatTabsModule,
ProjectRolesModule,
MatCheckboxModule,
CardModule,

View File

@@ -7,7 +7,7 @@
</div>
<div class="app-container">
<div class="sp-container" *ngIf="(loading$ | async)">
<mat-spinner color="accent" diameter="50"></mat-spinner>
<mat-spinner color="primary" diameter="50"></mat-spinner>
</div>
<div [routerLink]="['/projects', projectId, 'apps', app.id ]" class="app-wrap"

View File

@@ -5,7 +5,7 @@
$primary: map-get($theme, primary);
$primary-dark: mat-color($primary, A900);
$accent: map-get($theme, accent);
$accent-color: mat-color($accent, 500);
$accent-color: mat-color($primary, 500);
/* stylelint-enable */
.app-grid-header {
@@ -48,8 +48,9 @@
height: 80px;
width: 80px;
margin: 1rem;
text-transform: uppercase;
border-radius: .5rem;
border: 1px solid $accent-color;
border: 2px solid $accent-color;
font-weight: 800;
background-color: $primary-dark;
transition: background-color box-shadow .3s ease-in;
@@ -59,12 +60,12 @@
background-size: 100% 12px, 12px 100%;
&:hover {
background-color: rgba($accent-color, .2);
box-shadow: 0 5px 10px rgba(0, 0, 0, .12);
background-color: rgba($accent-color, .1);
}
&.add {
background: $accent-color;
color: white;
&:hover {
background-color: rgba($accent-color, .8);

View File

@@ -19,11 +19,6 @@
}
}
.selection {
width: 50px;
max-width: 50px;
}
.margin-neg {
margin-left: -1rem;
}

View File

@@ -33,12 +33,13 @@
<div class="full-width">
<div class="line">
<ng-container *ngIf="editstate">
<mat-form-field *ngIf="editstate && project?.name" class="formfield"
<cnsl-form-field *ngIf="editstate && project?.name" class="formfield"
hintLabel="The name is required!">
<mat-label>{{'PROJECT.NAME' | translate}}</mat-label>
<input matInput [(ngModel)]="project.name" name="name" />
</mat-form-field>
<button class="icon-button" *ngIf="editstate" mat-icon-button (click)="updateName()">
<cnsl-label>{{'PROJECT.NAME' | translate}}</cnsl-label>
<input cnslInput [(ngModel)]="project.name" name="name" />
</cnsl-form-field>
<button matTooltip="{{'ACTIONS.SAVE' | translate}}" class="icon-button" *ngIf="editstate"
mat-icon-button (click)="updateName()">
<mat-icon>check</mat-icon>
</button>
</ng-container>
@@ -80,10 +81,11 @@
<app-card title="{{ 'PROJECT.ROLE.TITLE' | translate }}"
description="{{ 'PROJECT.ROLE.DESCRIPTION' | translate }}">
<p>{{'PROJECT.ROLE.OPTIONS' | translate}}</p>
<mat-checkbox [(ngModel)]="project.projectRoleAssertion" (change)="saveProject()">
<mat-checkbox [(ngModel)]="project.projectRoleAssertion" (change)="saveProject()"
color="primary">
{{'PROJECT.ROLE.ASSERTION' | translate}}</mat-checkbox>
<p class="desc">{{'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate}}</p>
<mat-checkbox [(ngModel)]="project.projectRoleCheck" (change)="saveProject()">
<mat-checkbox [(ngModel)]="project.projectRoleCheck" (change)="saveProject()" color="primary">
{{'PROJECT.ROLE.CHECK' | translate}}</mat-checkbox>
<p class="desc">{{'PROJECT.ROLE.CHECK_DESCRIPTION' | translate}}</p>
<div class="divider"></div>
@@ -111,8 +113,8 @@
<div class="details">
<div class="row">
<span class="first">{{'PROJECT.STATE.TITLE' | translate}}:</span>
<span *ngIf="project && project.state !== undefined"
class="second">{{'PROJECT.STATE.'+project.state | translate}}</span>
<span *ngIf="project && project.state !== undefined" class="state"
[ngClass]="{'active': project.state === ProjectState.PROJECTSTATE_ACTIVE, 'inactive': project.state === ProjectState.PROJECTSTATE_INACTIVE}">{{'PROJECT.STATE.'+project.state | translate}}</span>
</div>
</div>

View File

@@ -41,6 +41,19 @@
}
}
.line {
.formfield {
flex: 1;
}
button {
margin-top: 1rem;
}
display: flex;
align-items: center;
}
.side {
.details {
margin-bottom: 1rem;
@@ -54,15 +67,26 @@
.first {
flex: 1;
font-size: .8rem;
font-size: 13px;
margin-right: .5rem;
}
.second {
font-size: .8rem;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 1rem;
.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;
}
}
}
}

View File

@@ -1,6 +1,6 @@
import { SelectionModel } from '@angular/cdk/collections';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, EventEmitter, OnDestroy, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Params, Router } from '@angular/router';
@@ -73,6 +73,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
= new BehaviorSubject<ProjectMemberView.AsObject[]>([]);
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
public refreshChanges$: EventEmitter<void> = new EventEmitter();
constructor(
public translate: TranslateService,
@@ -139,6 +140,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
this.mgmtService.ReactivateProject(this.projectId).then(() => {
this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true);
this.project.state = ProjectState.PROJECTSTATE_ACTIVE;
this.refreshChanges$.emit();
}).catch(error => {
this.toast.showError(error);
});
@@ -160,6 +162,7 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
this.mgmtService.DeactivateProject(this.projectId).then(() => {
this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true);
this.project.state = ProjectState.PROJECTSTATE_INACTIVE;
this.refreshChanges$.emit();
}).catch(error => {
this.toast.showError(error);
});
@@ -194,9 +197,9 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy {
}
public saveProject(): void {
console.log(this.project);
this.mgmtService.UpdateProject(this.project.projectId, this.project).then(() => {
this.toast.showInfo('PROJECT.TOAST.UPDATED', true);
this.refreshChanges$.emit();
}).catch(error => {
this.toast.showError(error);
});

View File

@@ -4,9 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatRippleModule } from '@angular/material/core';
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 { MatSelectModule } from '@angular/material/select';
@@ -19,6 +17,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 { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
@@ -48,11 +47,10 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
TranslateModule,
ReactiveFormsModule,
HasRoleModule,
MatInputModule,
MatTabsModule,
MatButtonModule,
MatIconModule,
ContributorsModule,
MatTabsModule,
WarnDialogModule,
MatTooltipModule,
ProjectRolesModule,
@@ -60,7 +58,7 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
UserGrantsModule,
TimestampToDatePipeModule,
MatTableModule,
MatFormFieldModule,
InputModule,
CardModule,
MatPaginatorModule,
MatRippleModule,

View File

@@ -40,33 +40,33 @@
{{grant.grantedOrgName}} </td>
</ng-container>
<ng-container matColumnDef="creationDate">
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.GRANT.CREATIONDATE' | translate }} </th>
<ng-container matColumnDef="dates">
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.GRANT.DATES' | translate }} </th>
<td [routerLink]="['/projects',grant.projectId,'grant', grant.id]" class="pointer" mat-cell
*matCellDef="let grant">
{{grant.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} </td>
</ng-container>
<ng-container matColumnDef="changeDate">
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.GRANT.CHANGEDATE' | translate }} </th>
<td [routerLink]="['/projects',grant.projectId,'grant', grant.id]" class="pointer" mat-cell
*matCellDef="let grant">
{{grant.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }} </td>
<div class="date-block">
<span class="date-sub">{{ 'PROJECT.GRANT.CREATIONDATE' | translate }}:</span>
<span>{{grant.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}</span>
</div>
<div class="date-block">
<span class="date-sub">{{ 'PROJECT.GRANT.CHANGEDATE' | translate }}</span>
<span>{{grant.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}</span>
</div>
</ng-container>
<ng-container matColumnDef="roleNamesList">
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }} </th>
<td class="pointer" mat-cell *matCellDef="let grant">
<mat-form-field class="form-field" appearance="outline" *ngIf="grant.roleKeysList">
<mat-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</mat-label>
<th mat-header-cell *matHeaderCellDef class="role-row"> {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}
</th>
<td class="pointer role-row" mat-cell *matCellDef="let grant">
<cnsl-form-field class="form-field" appearance="outline" *ngIf="grant.roleKeysList">
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
<mat-select [(ngModel)]="grant.roleKeysList" multiple [disabled]="disabled"
(selectionChange)="updateRoles(grant, $event)">
<mat-option *ngFor="let role of memberRoleOptions" [value]="role.key">
{{role.key}}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
</td>
</ng-container>
@@ -75,6 +75,11 @@
</tr>
</table>
<div *ngIf="(dataSource.loading$ | async) == false && !dataSource?.totalResult" class="no-content-row">
<i class="las la-exclamation"></i>
<span>{{'PROJECT.GRANT.EMPTY' | translate}}</span>
</div>
<mat-paginator class="paginator" #paginator [pageSize]="50" [pageSizeOptions]="[25, 50, 100, 250]"
[length]="dataSource.totalResult" (page)="loadGrantsPage($event.pageIndex, $event.pageSize)">
</mat-paginator>

View File

@@ -39,11 +39,6 @@
tr.detail-row {
height: 0;
}
.selection {
width: 50px;
max-width: 50px;
}
}
}
@@ -51,3 +46,19 @@
outline: none;
cursor: pointer;
}
.role-row {
min-width: 100px;
}
.date-block {
margin: .5rem 0;
display: block;
min-width: 120px;
.date-sub {
font-size: 13px;
color: var(--grey);
display: block;
}
}

View File

@@ -34,7 +34,7 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
public memberRoleOptions: ProjectRoleView.AsObject[] = [];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
public displayedColumns: string[] = ['select', 'grantedOrgName', 'creationDate', 'changeDate', 'roleNamesList'];
public displayedColumns: string[] = ['select', 'grantedOrgName', 'dates'];
constructor(private mgmtService: ManagementService, private toast: ToastService) { }

View File

@@ -1,5 +1,5 @@
<div class="view-toggle">
<button (click)="closeGridView()" mat-icon-button>
<button (click)="closeGridView()" mat-icon-button matTooltip="{{'PROJECT.TABLE.SHOWTABLE' | translate}}">
<i class="show list view las la-th-list"></i>
</button>
</div>

View File

@@ -4,7 +4,8 @@
</app-owned-project-grid>
<div *ngIf="!grid" class="view-toggle">
<button (click)="grid = true" mat-icon-button class="icon-button">
<button (click)="grid = true" mat-icon-button class="icon-button"
matTooltip="{{'PROJECT.TABLE.SHOWGRID' | translate}}">
<i matTooltip="show grid view" class="las la-th-large"></i>
</button>
</div>
@@ -77,6 +78,10 @@
[routerLink]="['/projects', row.projectId]"></tr>
</table>
<div *ngIf="(loading$ | async) == false && !dataSource?.data?.length" class="no-content-row">
<i class="las la-exclamation"></i>
<span>{{'PROJECT.TABLE.EMPTY' | translate}}</span>
</div>
<mat-paginator class="paginator" [length]="totalResult" [pageSize]="10" [pageSizeOptions]="[5, 10, 20]"
(page)="changePage($event)"></mat-paginator>
</div>

View File

@@ -40,11 +40,6 @@ h1 {
padding-right: 0;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
}

View File

@@ -73,7 +73,6 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy {
public ngOnInit(): void {
this.route.queryParams.pipe(take(1)).subscribe(params => {
console.log(params);
this.getData();
if (params.deferredReload) {
setTimeout(() => {

View File

@@ -4,9 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
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';
@@ -17,6 +15,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 { UserGrantsModule } from 'src/app/modules/user-grants/user-grants.module';
@@ -48,8 +47,7 @@ import { OwnedProjectsComponent } from './owned-projects.component';
HasRoleModule,
MatTableModule,
MatPaginatorModule,
MatFormFieldModule,
MatInputModule,
InputModule,
MatChipsModule,
MatIconModule,
WarnDialogModule,

View File

@@ -25,14 +25,14 @@
</div>
</div>
<mat-form-field class="formfield" appearance="outline" *ngIf="grant && grant.roleKeysList">
<mat-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</mat-label>
<cnsl-form-field class="formfield" appearance="outline" *ngIf="grant && grant.roleKeysList">
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
<mat-select [(ngModel)]="grant.roleKeysList" multiple (selectionChange)="updateRoles($event)">
<mat-option *ngFor="let role of projectRoleOptions" [value]="role.key">
{{role.key}}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
<div class="divider"></div>

View File

@@ -6,7 +6,6 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -16,6 +15,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MembersTableModule } from 'src/app/modules/members-table/members-table.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
@@ -39,7 +39,7 @@ import {
MatIconModule,
MatTableModule,
MatPaginatorModule,
MatFormFieldModule,
InputModule,
MatTooltipModule,
ReactiveFormsModule,
MatProgressSpinnerModule,

View File

@@ -6,14 +6,14 @@
<app-search-user-autocomplete (selectionChanged)="selectUsers($event)">
</app-search-user-autocomplete>
<mat-form-field class="full-width" appearance="outline">
<mat-label>{{ 'PROJECT.MEMBER.ROLES' | translate }}</mat-label>
<cnsl-form-field class="full-width" appearance="outline">
<cnsl-label>{{ 'PROJECT.MEMBER.ROLES' | translate }}</cnsl-label>
<mat-select [(ngModel)]="roleKeyList" multiple>
<mat-option *ngFor="let key of data.roleKeysList" [value]="key">
{{ key }}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
</div>
<div mat-dialog-actions class="action">
<button mat-button (click)="closeDialog()">

View File

@@ -3,9 +3,9 @@ import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { SearchUserAutocompleteModule } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.module';
import { ProjectGrantMembersCreateDialogComponent } from './project-grant-members-create-dialog.component';
@@ -19,7 +19,7 @@ import { ProjectGrantMembersCreateDialogComponent } from './project-grant-member
MatButtonModule,
TranslateModule,
MatSelectModule,
MatFormFieldModule,
InputModule,
SearchUserAutocompleteModule,
],
})

View File

@@ -32,7 +32,6 @@ export class ProjectGrantMembersDataSource extends DataSource<ProjectMember.AsOb
grantId, pageSize, offset)).pipe(
map(resp => {
const response = resp.toObject();
console.log(response.resultList);
this.totalResult = response.totalResult;
if (response.viewTimestamp) {
this.viewTimestamp = response.viewTimestamp;

View File

@@ -9,12 +9,13 @@
</div>
<h1>{{'PROJECT.PAGES.CREATE_DESC' | translate}}</h1>
<form (ngSubmit)="saveProject()">
<form cdkFocusRegionStart (ngSubmit)="saveProject()">
<div class="column">
<mat-form-field class="formfield" hintLabel="The name is required!">
<mat-label>{{'PROJECT.NAME' | translate}}</mat-label>
<input matInput autofocus [(ngModel)]="project.name" [ngModelOptions]="{ standalone: true }" />
</mat-form-field>
<cnsl-form-field class="formfield" hintLabel="The name is required!">
<cnsl-label>{{'PROJECT.NAME' | translate}}</cnsl-label>
<input cnslInput cdkFocusInitial autofocus [(ngModel)]="project.name"
[ngModelOptions]="{ standalone: true }" />
</cnsl-form-field>
</div>
<button color="primary" mat-raised-button class="continue-button" [disabled]="!project.name" cdkFocusInitial

View File

@@ -38,10 +38,6 @@ h1 {
.formfield {
width: 400px;
input {
font-size: 1.5rem;
}
&.autocomplete {
margin-top: 1rem;
}

View File

@@ -1,11 +1,11 @@
import { A11yModule } from '@angular/cdk/a11y';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } 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 { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { ProjectCreateRoutingModule } from './project-create-routing.module';
import { ProjectCreateComponent } from './project-create.component';
@@ -13,11 +13,11 @@ import { ProjectCreateComponent } from './project-create.component';
@NgModule({
declarations: [ProjectCreateComponent],
imports: [
A11yModule,
ProjectCreateRoutingModule,
CommonModule,
FormsModule,
MatInputModule,
MatFormFieldModule,
InputModule,
MatButtonModule,
MatIconModule,
TranslateModule,

View File

@@ -13,10 +13,10 @@
<p>{{'PROJECT.GRANT.CREATE.SEL_ORG_DESC' | translate}}</p>
<form (ngSubmit)="searchOrg(domain.value)">
<mat-form-field class="org-domain">
<mat-label>{{'PROJECT.GRANT.CREATE.SEL_ORG_FORMFIELD' | translate}}</mat-label>
<input #domain matInput />
</mat-form-field>
<cnsl-form-field class="org-domain">
<cnsl-label>{{'PROJECT.GRANT.CREATE.SEL_ORG_FORMFIELD' | translate}}</cnsl-label>
<input cnslInput #domain />
</cnsl-form-field>
<button [disabled]="domain.value.length == 0" color="primary" type="submit" class="domain-button"
mat-raised-button>

View File

@@ -59,8 +59,6 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
}
public addGrant(): void {
console.log(this.org.id, this.projectId, this.rolesKeyList);
this.mgmtService
.CreateProjectGrant(this.org.id, this.projectId, this.rolesKeyList)
.then((data) => {

View File

@@ -5,13 +5,12 @@ import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatChipsModule } from '@angular/material/chips';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { CardModule } from 'src/app/modules/card/card.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { ProjectRolesModule } from 'src/app/modules/project-roles/project-roles.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
@@ -26,8 +25,7 @@ import { ProjectGrantCreateComponent } from './project-grant-create.component';
MatAutocompleteModule,
MatChipsModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
InputModule,
CardModule,
MatCheckboxModule,
ProjectRolesModule,

View File

@@ -15,18 +15,18 @@
<form @list (ngSubmit)="addRole()">
<div @animate *ngFor="let formGroup of formArray.controls; index as i" class="content">
<ng-container [formGroup]="formGroup">
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'PROJECT.ROLE.KEY' | translate }}</mat-label>
<input matInput formControlName="key" />
</mat-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'PROJECT.ROLE.DISPLAY_NAME' | translate }}</mat-label>
<input matInput formControlName="displayName" />
</mat-form-field>
<mat-form-field appearance="outline" class="formfield">
<mat-label>{{ 'PROJECT.ROLE.GROUP' | translate }}</mat-label>
<input matInput formControlName="group" />
</mat-form-field>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'PROJECT.ROLE.KEY' | translate }}</cnsl-label>
<input cnslInput formControlName="key" />
</cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'PROJECT.ROLE.DISPLAY_NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="displayName" />
</cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'PROJECT.ROLE.GROUP' | translate }}</cnsl-label>
<input cnslInput formControlName="group" />
</cnsl-form-field>
<button *ngIf="i !== 0" mat-icon-button (click)="removeEntry(i)" type="button" color="warn"
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}">
<i class="las la-trash"></i>

View File

@@ -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 { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { ProjectRoleCreateRoutingModule } from './project-role-create-routing.module';
import { ProjectRoleCreateComponent } from './project-role-create.component';
@@ -18,8 +17,7 @@ import { ProjectRoleCreateComponent } from './project-role-create.component';
CommonModule,
FormsModule,
ReactiveFormsModule,
MatInputModule,
MatFormFieldModule,
InputModule,
MatButtonModule,
MatIconModule,
MatTooltipModule,

View File

@@ -46,14 +46,14 @@
<ng-container
*ngIf="(context === UserGrantContext.GRANTED_PROJECT || ((context === UserGrantContext.USER || context === UserGrantContext.NONE) && $any(project)?.id)) && grantRolesKeyList">
<mat-form-field class="form-field" appearance="outline">
<mat-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</mat-label>
<cnsl-form-field class="form-field" appearance="outline">
<cnsl-label>{{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }}</cnsl-label>
<mat-select multiple (selectionChange)="rolesList = $event.value">
<mat-option *ngFor="let role of grantRolesKeyList" [value]="role">
{{role}}
</mat-option>
</mat-select>
</mat-form-field>
</cnsl-form-field>
</ng-container>
</ng-container>

View File

@@ -72,7 +72,6 @@ export class UserGrantCreateComponent implements OnDestroy {
this.context = UserGrantContext.USER;
this.mgmtService.GetUserByID(this.userId).then(resp => {
this.user = resp.toObject();
console.log(this.user);
}).catch((error: any) => {
this.toast.showError(error);
});

View File

@@ -1,11 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatSelectModule } from '@angular/material/select';
import { TranslateModule } from '@ngx-translate/core';
import { CardModule } from 'src/app/modules/card/card.module';
import { InputModule } from 'src/app/modules/input/input.module';
import {
SearchProjectAutocompleteModule,
} from 'src/app/modules/search-project-autocomplete/search-project-autocomplete.module';
@@ -27,7 +27,7 @@ import { UserGrantCreateComponent } from './user-grant-create.component';
MatIconModule,
TranslateModule,
CardModule,
MatFormFieldModule,
InputModule,
MatSelectModule,
SearchProjectAutocompleteModule,
SearchUserAutocompleteModule,

View File

@@ -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"

View File

@@ -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 { }

View File

@@ -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"

View File

@@ -25,6 +25,8 @@
flex-basis: 100%;
color: var(--grey);
font-size: .9rem;
letter-spacing: .05em;
text-transform: uppercase;
}
.formfield {

View File

@@ -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`;
}
}
}

View File

@@ -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 { }

View File

@@ -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>

View File

@@ -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);
});

View File

@@ -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()">

View File

@@ -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>

View File

@@ -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()">

View File

@@ -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();
});

View File

@@ -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()">

View File

@@ -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();
});

View File

@@ -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>

View File

@@ -8,6 +8,7 @@
justify-content: space-between;
align-items: center;
padding: .5rem;
padding-right: 0;
border-bottom: 1px solid #ffffff20;
flex-wrap: wrap;

View File

@@ -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>

View File

@@ -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,

View File

@@ -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"

View File

@@ -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,

View File

@@ -24,4 +24,14 @@
tr {
outline: none;
button {
visibility: hidden;
}
&:hover {
button {
visibility: visible;
}
}
}

View File

@@ -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>

View File

@@ -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 });
}
}

View File

@@ -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 { }

View File

@@ -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);

View File

@@ -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>

View File

@@ -27,11 +27,6 @@
.action {
width: 40px;
}
.selection {
width: 50px;
max-width: 50px;
}
}
}

View File

@@ -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>

View File

@@ -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 {

View File

@@ -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>

View File

@@ -28,6 +28,6 @@
padding: .5rem 4rem;
}
.mat-error {
.cnsl-error {
display: block;
}

View File

@@ -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 { }

View File

@@ -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>

View File

@@ -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;
}
}
}
}

View File

@@ -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);
});

View File

@@ -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,

Some files were not shown because too many files have changed in this diff Show More