upgrade and migrate to angular 20
This commit is contained in:
Generated
+3342
-4626
File diff suppressed because it is too large
Load Diff
+22
-23
@@ -11,45 +11,44 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^19.2.10",
|
"@angular/animations": "^20.3.10",
|
||||||
"@angular/cdk": "^19.2.15",
|
"@angular/cdk": "^20.2.12",
|
||||||
"@angular/common": "^19.2.10",
|
"@angular/common": "^20.3.10",
|
||||||
"@angular/compiler": "^19.2.10",
|
"@angular/compiler": "^20.3.10",
|
||||||
"@angular/core": "^19.2.10",
|
"@angular/core": "^20.3.10",
|
||||||
"@angular/forms": "^19.2.10",
|
"@angular/forms": "^20.3.10",
|
||||||
"@angular/material": "^19.2.15",
|
"@angular/material": "^20.2.12",
|
||||||
"@angular/material-moment-adapter": "^19.2.15",
|
"@angular/material-moment-adapter": "^20.2.12",
|
||||||
"@angular/platform-browser": "^19.2.10",
|
"@angular/platform-browser": "^20.3.10",
|
||||||
"@angular/platform-browser-dynamic": "^19.2.10",
|
"@angular/platform-browser-dynamic": "^20.3.10",
|
||||||
"@angular/router": "^19.2.10",
|
"@angular/router": "^20.3.10",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"ng-qrcode": "^19.0.1",
|
"ng-qrcode": "^20.0.1",
|
||||||
"openpgp": "^6.1.0",
|
"openpgp": "^6.2.2",
|
||||||
"qr-scanner": "^1.4.2",
|
"qr-scanner": "^1.4.2",
|
||||||
"rxjs": "~7.8.2",
|
"rxjs": "~7.8.2",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"unique-names-generator": "^4.7.1",
|
"unique-names-generator": "^4.7.1",
|
||||||
"zone.js": "~0.15.0"
|
"zone.js": "~0.15.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^19.2.11",
|
"@angular-devkit/build-angular": "^20.3.9",
|
||||||
"@angular/cli": "^19.2.11",
|
"@angular/cli": "^20.3.9",
|
||||||
"@angular/compiler-cli": "^19.2.10",
|
"@angular/compiler-cli": "^20.3.10",
|
||||||
"@angular/localize": "^19.2.10",
|
"@angular/localize": "^20.3.10",
|
||||||
"@types/jasmine": "^5.1.8",
|
"@types/jasmine": "^5.1.12",
|
||||||
"@types/jasminewd2": "^2.0.13",
|
"@types/jasminewd2": "^2.0.13",
|
||||||
"@types/node": "^22.15.17",
|
"@types/node": "^24.10.0",
|
||||||
"@types/openpgp": "^5.0.0",
|
"@types/openpgp": "^5.0.0",
|
||||||
"jasmine-core": "~5.7.1",
|
"jasmine-core": "~5.12.1",
|
||||||
"jasmine-spec-reporter": "~7.0.0",
|
"jasmine-spec-reporter": "~7.0.0",
|
||||||
"karma": "^6.4.4",
|
"karma": "^6.4.4",
|
||||||
"karma-chrome-launcher": "~3.2.0",
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
"karma-coverage-istanbul-reporter": "~3.0.3",
|
"karma-coverage-istanbul-reporter": "~3.0.3",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "^2.1.0",
|
"karma-jasmine-html-reporter": "^2.1.0",
|
||||||
"protractor": "~7.0.0",
|
|
||||||
"ts-node": "~10.9.2",
|
"ts-node": "~10.9.2",
|
||||||
"tslint": "~6.1.3",
|
"tslint": "~6.1.3",
|
||||||
"typescript": "~5.8.3"
|
"typescript": "~5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,23 @@
|
|||||||
[active]="rlasecurity.isActive">{{'security' | i18n}}</a>
|
[active]="rlasecurity.isActive">{{'security' | i18n}}</a>
|
||||||
<a mat-tab-link routerLink="voucher" routerLinkActive #rlavoucher="routerLinkActive"
|
<a mat-tab-link routerLink="voucher" routerLinkActive #rlavoucher="routerLinkActive"
|
||||||
[active]="rlavoucher.isActive">{{'vouchers' | i18n}}</a>
|
[active]="rlavoucher.isActive">{{'vouchers' | i18n}}</a>
|
||||||
<a *ngIf="advancedView" mat-tab-link routerLink="aliases" #rlaaliases="routerLinkActive" routerLinkActive
|
@if (advancedView) {
|
||||||
|
<a mat-tab-link routerLink="aliases" #rlaaliases="routerLinkActive" routerLinkActive
|
||||||
[active]="rlaaliases.isActive">{{'user.aliases' | i18n}}</a>
|
[active]="rlaaliases.isActive">{{'user.aliases' | i18n}}</a>
|
||||||
<a *ngIf="advancedView" mat-tab-link routerLink="domains" #rladomains="routerLinkActive" routerLinkActive
|
}
|
||||||
|
@if (advancedView) {
|
||||||
|
<a mat-tab-link routerLink="domains" #rladomains="routerLinkActive" routerLinkActive
|
||||||
[active]="rladomains.isActive">{{'user.domains' | i18n}}</a>
|
[active]="rladomains.isActive">{{'user.domains' | i18n}}</a>
|
||||||
<a *ngIf="advancedView" mat-tab-link routerLink="dyndns" #rladyndns="routerLinkActive" routerLinkActive
|
}
|
||||||
|
@if (advancedView) {
|
||||||
|
<a mat-tab-link routerLink="dyndns" #rladyndns="routerLinkActive" routerLinkActive
|
||||||
[active]="rladyndns.isActive">{{'user.dyndns' | i18n}}</a>
|
[active]="rladyndns.isActive">{{'user.dyndns' | i18n}}</a>
|
||||||
|
}
|
||||||
<a style="align-self: center;">
|
<a style="align-self: center;">
|
||||||
<mat-slide-toggle [(ngModel)]="advancedView">
|
<mat-slide-toggle [(ngModel)]="advancedView">
|
||||||
<span *ngIf="!advancedView">{{'account.advanced' | i18n}}</span>
|
@if (!advancedView) {
|
||||||
|
<span>{{'account.advanced' | i18n}}</span>
|
||||||
|
}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -11,10 +11,12 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="visibility"> {{'visibility' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="visibility"> {{'visibility' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let alias">
|
<td mat-cell *matCellDef="let alias">
|
||||||
<mat-select [(ngModel)]="alias.visibility" (selectionChange)="updateAlias(alias)">
|
<mat-select [(ngModel)]="alias.visibility" (selectionChange)="updateAlias(alias)">
|
||||||
<mat-option *ngFor="let visibility of visibilities" [value]="visibility">
|
@for (visibility of visibilities; track visibility) {
|
||||||
|
<mat-option [value]="visibility">
|
||||||
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
||||||
visibility | i18n}}
|
visibility | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-select-trigger>
|
<mat-select-trigger>
|
||||||
<mat-icon inline="true">{{'visibility.' + alias.visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
<mat-icon inline="true">{{'visibility.' + alias.visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
||||||
@@ -41,8 +43,11 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'user.aliases.info' | i18n}}</p>
|
<p>{{'user.aliases.info' | i18n}}</p>
|
||||||
<p *ngIf="!aliasCreation">{{'user.aliases.noQuota' | i18n}}</p>
|
@if (!aliasCreation) {
|
||||||
<div *ngIf="aliasCreation">
|
<p>{{'user.aliases.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (aliasCreation) {
|
||||||
|
<div>
|
||||||
<p>{{'user.aliases.left' | i18n:aliasCreation}}</p>
|
<p>{{'user.aliases.left' | i18n:aliasCreation}}</p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'user.aliases.alias' | i18n}}</mat-label>
|
<mat-label>{{'user.aliases.alias' | i18n}}</mat-label>
|
||||||
@@ -54,11 +59,12 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'visibility' | i18n}}</mat-label>
|
<mat-label>{{'visibility' | i18n}}</mat-label>
|
||||||
<mat-select [(ngModel)]="alias.visibility" formControlName="visibility">
|
<mat-select [(ngModel)]="alias.visibility" formControlName="visibility">
|
||||||
<mat-option *ngFor="let visibility of visibilities" [value]="visibility">
|
@for (visibility of visibilities; track visibility) {
|
||||||
|
<mat-option [value]="visibility">
|
||||||
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
||||||
visibility | i18n}}
|
visibility | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
<mat-select-trigger>
|
<mat-select-trigger>
|
||||||
<mat-icon inline="true">{{'visibility.' + alias.visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
<mat-icon inline="true">{{'visibility.' + alias.visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
||||||
alias.visibility | i18n}}
|
alias.visibility | i18n}}
|
||||||
@@ -66,12 +72,15 @@
|
|||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="aliasCreation && !working" mat-raised-button color="primary"
|
@if (aliasCreation && !working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary"
|
||||||
[disabled]="form.invalid">
|
[disabled]="form.invalid">
|
||||||
{{'user.aliases.create' | i18n}}
|
{{'user.aliases.create' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#aliases" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/webstly#aliases" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -50,9 +50,11 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid">
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="form.invalid">
|
||||||
{{'user.domains.create' | i18n}}
|
{{'user.domains.create' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#domains" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/webstly#domains" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -3,15 +3,23 @@
|
|||||||
<form (ngSubmit)="create()" #formDirective="ngForm" #dyndnsForm>
|
<form (ngSubmit)="create()" #formDirective="ngForm" #dyndnsForm>
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p *ngIf="dyndnsToken && !dyndnsToken.token">{{'user.dyndns.token.exists' | i18n}}</p>
|
@if (dyndnsToken && !dyndnsToken.token) {
|
||||||
<a *ngIf="dyndnsToken && dyndnsToken.token" mat-button (click)="copySecret()"
|
<p>{{'user.dyndns.token.exists' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (dyndnsToken && dyndnsToken.token) {
|
||||||
|
<a mat-button (click)="copySecret()"
|
||||||
matTooltip="{{'user.dyndns.token.copy' | i18n}}" matTooltipPosition="above">{{ dyndnsToken.token}}</a>
|
matTooltip="{{'user.dyndns.token.copy' | i18n}}" matTooltipPosition="above">{{ dyndnsToken.token}}</a>
|
||||||
<p *ngIf="dyndnsToken && dyndnsToken.token">{{'user.dyndns.token.store' | i18n}}</p>
|
}
|
||||||
|
@if (dyndnsToken && dyndnsToken.token) {
|
||||||
|
<p>{{'user.dyndns.token.store' | i18n}}</p>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary">
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary">
|
||||||
{{(dyndnsToken ? 'user.dyndns.new' : 'user.dyndns.create') | i18n}}
|
{{(dyndnsToken ? 'user.dyndns.new' : 'user.dyndns.create') | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#dyndns" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/webstly#dyndns" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
{{'security.2fa.totp.hint' | i18n}}
|
{{'security.2fa.totp.hint' | i18n}}
|
||||||
|
|
||||||
<qr-code *ngIf="data.qrData" [value]="data.qrData" size="400" errorCorrectionLevel="'M'"
|
@if (data.qrData) {
|
||||||
|
<qr-code [value]="data.qrData" size="400" errorCorrectionLevel="'M'"
|
||||||
title="{{data.qrData}}"></qr-code>
|
title="{{data.qrData}}"></qr-code>
|
||||||
|
}
|
||||||
|
|
||||||
{{'security.2fa.totp.activate' | i18n}}
|
{{'security.2fa.totp.activate' | i18n}}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
|
|||||||
@@ -5,19 +5,25 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password.current' | i18n}}</mat-label>
|
<mat-label>{{'password.current' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="oldPassword" [(ngModel)]="model.old">
|
<input matInput type="password" formControlName="oldPassword" [(ngModel)]="model.old">
|
||||||
<mat-error *ngFor="let error of passwordForm.get('oldPassword').errors | keyvalue">
|
@for (error of passwordForm.get('oldPassword').errors | keyvalue; track error) {
|
||||||
|
<mat-error>
|
||||||
{{error.key}}
|
{{error.key}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-hint *ngIf="success">
|
}
|
||||||
|
@if (success) {
|
||||||
|
<mat-hint>
|
||||||
{{'password.changed' | i18n}}
|
{{'password.changed' | i18n}}
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password" [(ngModel)]="model.password">
|
<input matInput type="password" formControlName="password" [(ngModel)]="model.password">
|
||||||
<mat-error *ngFor="let error of passwordForm.get('password').errors | keyvalue">
|
@for (error of passwordForm.get('password').errors | keyvalue; track error) {
|
||||||
|
<mat-error>
|
||||||
{{error.key}}
|
{{error.key}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
||||||
@@ -28,10 +34,14 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="passwordForm.invalid">
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="passwordForm.invalid">
|
||||||
{{'password.change' | i18n}}
|
{{'password.change' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</form>
|
</form>
|
||||||
@@ -44,21 +54,29 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'security.status' | i18n}}</mat-label>
|
<mat-label>{{'security.status' | i18n}}</mat-label>
|
||||||
<mat-select [(ngModel)]="model.status" formControlName="status">
|
<mat-select [(ngModel)]="model.status" formControlName="status">
|
||||||
<mat-option *ngFor="let status of statuses" [value]="status">
|
@for (status of statuses; track status) {
|
||||||
|
<mat-option [value]="status">
|
||||||
{{'security.status.' + status | i18n}}
|
{{'security.status.' + status | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<mat-hint *ngIf="successStatus">
|
@if (successStatus) {
|
||||||
|
<mat-hint>
|
||||||
{{'security.status.success' | i18n}}
|
{{'security.status.success' | i18n}}
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-label>{{'security.status.' + model.status + '.hint' | i18n}}</mat-label>
|
<mat-label>{{'security.status.' + model.status + '.hint' | i18n}}</mat-label>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="statusForm.invalid">
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="statusForm.invalid">
|
||||||
{{'security.status.change' | i18n}}
|
{{'security.status.change' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#status" class="help-button"
|
<a href="https://wiki.bstly.de/services/webstly#status" class="help-button"
|
||||||
@@ -75,10 +93,14 @@
|
|||||||
<p>{{'security.2fa.info' | i18n}}</p>
|
<p>{{'security.2fa.info' | i18n}}</p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a *ngIf="!totp" (click)="createTotp()" mat-raised-button color="accent">{{'security.2fa.totp.create' |
|
@if (!totp) {
|
||||||
|
<a (click)="createTotp()" mat-raised-button color="accent">{{'security.2fa.totp.create' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
<a *ngIf="totp" (click)="removeTotp()" mat-raised-button color="warn">{{'security.2fa.totp.remove' |
|
}
|
||||||
|
@if (totp) {
|
||||||
|
<a (click)="removeTotp()" mat-raised-button color="warn">{{'security.2fa.totp.remove' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#2fa" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/webstly#2fa" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
<p>{{'vouchers.info' | i18n}}</p>
|
<p>{{'vouchers.info' | i18n}}</p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a *ngFor="let name of available" mat-raised-button (click)="create(name)" matTooltip="{{'vouchers.' + name + '.text' | i18n}}">
|
@for (name of available; track name) {
|
||||||
|
<a mat-raised-button (click)="create(name)" matTooltip="{{'vouchers.' + name + '.text' | i18n}}">
|
||||||
{{'vouchers.' + name | i18n}}
|
{{'vouchers.' + name | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#voucher" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/webstly#voucher" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
@@ -15,7 +17,8 @@
|
|||||||
</mat-card-footer>
|
</mat-card-footer>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<div *ngIf="vouchers && vouchers[0]">
|
@if (vouchers && vouchers[0]) {
|
||||||
|
<div>
|
||||||
<h3>{{'vouchers.temp' | i18n}}</h3>
|
<h3>{{'vouchers.temp' | i18n}}</h3>
|
||||||
<p>{{'vouchers.temp.info' | i18n}}</p>
|
<p>{{'vouchers.temp.info' | i18n}}</p>
|
||||||
<table mat-table [dataSource]="voucherSource">
|
<table mat-table [dataSource]="voucherSource">
|
||||||
@@ -23,13 +26,12 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef> {{'voucher.type' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'voucher.type' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let voucher">{{voucher.type}}</td>
|
<td mat-cell *matCellDef="let voucher">{{voucher.type}}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="code">
|
<ng-container matColumnDef="code">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'voucher.code' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'voucher.code' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let voucher">{{voucher.code}}</td>
|
<td mat-cell *matCellDef="let voucher">{{voucher.code}}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="voucherColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="voucherColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: voucherColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: voucherColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -71,22 +71,24 @@
|
|||||||
{{'borrow.items.emailNotification' | i18n}}
|
{{'borrow.items.emailNotification' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
|
||||||
<mat-form-field *ngIf="form.get('emailNotification').value" fxFlex="1 1 0%">
|
@if (form.get('emailNotification').value) {
|
||||||
|
<mat-form-field fxFlex="1 1 0%">
|
||||||
<mat-label>{{'borrow.items.email' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.email' | i18n}}</mat-label>
|
||||||
<input matInput type="email" formControlName="email">
|
<input matInput type="email" formControlName="email">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'borrow.items.error.email' | i18n}}
|
{{'borrow.items.error.email' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="form.get('availability').value == 'MANUAL'">
|
@if (form.get('availability').value == 'MANUAL') {
|
||||||
<mat-divider></mat-divider><br>
|
<mat-divider></mat-divider><br>
|
||||||
<label>{{'borrow.items.slot.MANUAL' | i18n}}</label>
|
<label>{{'borrow.items.slot.MANUAL' | i18n}}</label>
|
||||||
<a mat-icon-button (click)="addManualSlot('','','')" title="{{'borrow.items.slot.add' | i18n}}">
|
<a mat-icon-button (click)="addManualSlot('','','')" title="{{'borrow.items.slot.add' | i18n}}">
|
||||||
<mat-icon>control_point_duplicate</mat-icon>
|
<mat-icon>control_point_duplicate</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<ng-container *ngFor="let slotForm of slots.controls; let i = index">
|
@for (slotForm of slots.controls; track slotForm; let i = $index) {
|
||||||
<div [formGroup]="slotForm" class="flex wrap" fxLayoutAlign="start stretch" fxLayoutGap="24px grid">
|
<div [formGroup]="slotForm" class="flex wrap" fxLayoutAlign="start stretch" fxLayoutGap="24px grid">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.start' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.start' | i18n}}</mat-label>
|
||||||
@@ -95,7 +97,6 @@
|
|||||||
{{'borrow.items.error.slot.start' | i18n}}
|
{{'borrow.items.error.slot.start' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.end' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.end' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" formControlName="end">
|
<input matInput type="datetime-local" formControlName="end">
|
||||||
@@ -103,7 +104,6 @@
|
|||||||
{{'borrow.items.error.slot.end' | i18n}}
|
{{'borrow.items.error.slot.end' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<a mat-icon-button (click)="dublicateSlot(i)" title="{{'borrow.items.slot.dublicate' | i18n}}">
|
<a mat-icon-button (click)="dublicateSlot(i)" title="{{'borrow.items.slot.dublicate' | i18n}}">
|
||||||
<mat-icon>control_point_duplicate</mat-icon>
|
<mat-icon>control_point_duplicate</mat-icon>
|
||||||
@@ -113,29 +113,30 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
}
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
<ng-container *ngIf="form.get('availability').value == 'PERIOD'">
|
@if (form.get('availability').value == 'PERIOD') {
|
||||||
<mat-divider></mat-divider><br>
|
<mat-divider></mat-divider><br>
|
||||||
<label>{{'borrow.items.slot.PERIOD' | i18n}}</label>
|
<label>{{'borrow.items.slot.PERIOD' | i18n}}</label>
|
||||||
<a mat-icon-button (click)="addPeriodSlot('','','','','')" title="{{'borrow.items.slot.add' | i18n}}">
|
<a mat-icon-button (click)="addPeriodSlot('','','','','')" title="{{'borrow.items.slot.add' | i18n}}">
|
||||||
<mat-icon>control_point_duplicate</mat-icon>
|
<mat-icon>control_point_duplicate</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<ng-container *ngFor="let slotForm of slots.controls; let i = index">
|
@for (slotForm of slots.controls; track slotForm; let i = $index) {
|
||||||
<div [formGroup]="slotForm" class="flex wrap" fxLayoutAlign="start stretch" fxLayoutGap="12px grid">
|
<div [formGroup]="slotForm" class="flex wrap" fxLayoutAlign="start stretch" fxLayoutGap="12px grid">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.startDay' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.startDay' | i18n}}</mat-label>
|
||||||
<mat-select formControlName="startDay">
|
<mat-select formControlName="startDay">
|
||||||
<mat-option *ngFor="let day of weekdays" [value]="day">
|
@for (day of weekdays; track day) {
|
||||||
|
<mat-option [value]="day">
|
||||||
{{'borrow.items.slot.day.' + day | i18n}}
|
{{'borrow.items.slot.day.' + day | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'borrow.items.error.slot.startDay' | i18n}}
|
{{'borrow.items.error.slot.startDay' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.startTime' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.startTime' | i18n}}</mat-label>
|
||||||
<input matInput format="24" [ngxMatTimepicker]="startTimePicker" formControlName="startTime">
|
<input matInput format="24" [ngxMatTimepicker]="startTimePicker" formControlName="startTime">
|
||||||
@@ -147,19 +148,19 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<ngx-mat-timepicker #startTimePicker></ngx-mat-timepicker>
|
<ngx-mat-timepicker #startTimePicker></ngx-mat-timepicker>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.endDay' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.endDay' | i18n}}</mat-label>
|
||||||
<mat-select formControlName="endDay">
|
<mat-select formControlName="endDay">
|
||||||
<mat-option *ngFor="let day of weekdays" [value]="day">
|
@for (day of weekdays; track day) {
|
||||||
|
<mat-option [value]="day">
|
||||||
{{'borrow.items.slot.day.' + day | i18n}}
|
{{'borrow.items.slot.day.' + day | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'borrow.items.error.slot.endDay' | i18n}}
|
{{'borrow.items.error.slot.endDay' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.slot.endTime' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.slot.endTime' | i18n}}</mat-label>
|
||||||
<input matInput format="24" [ngxMatTimepicker]="endTimePicker" formControlName="endTime">
|
<input matInput format="24" [ngxMatTimepicker]="endTimePicker" formControlName="endTime">
|
||||||
@@ -171,7 +172,6 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<ngx-mat-timepicker #endTimePicker></ngx-mat-timepicker>
|
<ngx-mat-timepicker #endTimePicker></ngx-mat-timepicker>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<a mat-icon-button (click)="dublicateSlot(i)" title="{{'borrow.items.slot.dublicate' | i18n}}">
|
<a mat-icon-button (click)="dublicateSlot(i)" title="{{'borrow.items.slot.dublicate' | i18n}}">
|
||||||
<mat-icon>control_point_duplicate</mat-icon>
|
<mat-icon>control_point_duplicate</mat-icon>
|
||||||
@@ -181,8 +181,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
}
|
||||||
</ng-container>
|
}
|
||||||
</form>
|
</form>
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
@@ -193,9 +193,11 @@
|
|||||||
<mat-icon>save</mat-icon>{{(create ? 'borrow.items.create' : 'borrow.items.save') | i18n}}
|
<mat-icon>save</mat-icon>{{(create ? 'borrow.items.create' : 'borrow.items.save') | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a *ngIf="borrowItemId" mat-button color="warn" (click)="confirmDelete()">
|
@if (borrowItemId) {
|
||||||
|
<a mat-button color="warn" (click)="confirmDelete()">
|
||||||
<mat-icon>delete</mat-icon> {{ 'borrow.items.delete' |
|
<mat-icon>delete</mat-icon> {{ 'borrow.items.delete' |
|
||||||
i18n}}
|
i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</mat-dialog-actions>
|
</mat-dialog-actions>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<h3>{{'borrow.items' | i18n}}</h3>
|
<h3>{{'borrow.items' | i18n}}</h3>
|
||||||
<div *ngIf="borrowItems">
|
@if (borrowItems) {
|
||||||
|
<div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.items.search' | i18n}}</mat-label>
|
<mat-label>{{'borrow.items.search' | i18n}}</mat-label>
|
||||||
@@ -13,49 +14,55 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'borrow.items.name' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'borrow.items.name' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowItem"> {{ borrowItem.name}} </td>
|
<td mat-cell *matCellDef="let borrowItem"> {{ borrowItem.name}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="description">
|
<ng-container matColumnDef="description">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.description' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.description' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowItem"> {{ borrowItem.description}} </td>
|
<td mat-cell *matCellDef="let borrowItem"> {{ borrowItem.description}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="availability">
|
<ng-container matColumnDef="availability">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.availability' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.availability' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowItem"> {{ 'borrow.items.availability.' + borrowItem.availability | i18n}}
|
<td mat-cell *matCellDef="let borrowItem"> {{ 'borrow.items.availability.' + borrowItem.availability | i18n}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="url">
|
<ng-container matColumnDef="url">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.url' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.items.url' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowItem">
|
<td mat-cell *matCellDef="let borrowItem">
|
||||||
<a *ngIf="borrowItem.url" mat-button color="accent" href="{{ borrowItem.url }}" target="_blank">
|
@if (borrowItem.url) {
|
||||||
|
<a mat-button color="accent" href="{{ borrowItem.url }}" target="_blank">
|
||||||
{{ borrowItem.url }}
|
{{ borrowItem.url }}
|
||||||
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'borrow.items.actions' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'borrow.items.actions' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowItem" class="text-right">
|
<td mat-cell *matCellDef="let borrowItem" class="text-right">
|
||||||
<a mat-icon-button *ngIf="borrowItem.owner == userId" (click)="request(borrowItem)">
|
@if (borrowItem.owner == userId) {
|
||||||
|
<a mat-icon-button (click)="request(borrowItem)">
|
||||||
<mat-icon>pending_actions</mat-icon>
|
<mat-icon>pending_actions</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a mat-icon-button *ngIf="borrowItem.owner == userId" (click)="edit(borrowItem)">
|
}
|
||||||
|
@if (borrowItem.owner == userId) {
|
||||||
|
<a mat-icon-button (click)="edit(borrowItem)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a mat-icon-button *ngIf="borrowItem.owner == userId" (click)="confirmDelete(borrowItem)">
|
}
|
||||||
|
@if (borrowItem.owner == userId) {
|
||||||
|
<a mat-icon-button (click)="confirmDelete(borrowItem)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a mat-icon-button *ngIf="borrowItem.owner != userId" (click)="request(borrowItem)">
|
}
|
||||||
|
@if (borrowItem.owner != userId) {
|
||||||
|
<a mat-icon-button (click)="request(borrowItem)">
|
||||||
<mat-icon>pending_actions</mat-icon>
|
<mat-icon>pending_actions</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="borrowItemColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="borrowItemColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: borrowItemColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: borrowItemColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="borrowItems.totalElements" [pageSize]="borrowItems.size"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="borrowItems.totalElements" [pageSize]="borrowItems.size"
|
||||||
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -4,9 +4,11 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'borrow.proving.camera' | i18n}}</mat-label>
|
<mat-label>{{'borrow.proving.camera' | i18n}}</mat-label>
|
||||||
<mat-select [formControl]="camera" name="camera">
|
<mat-select [formControl]="camera" name="camera">
|
||||||
<mat-option *ngFor="let camera of cameras" [value]="camera.id">
|
@for (camera of cameras; track camera) {
|
||||||
|
<mat-option [value]="camera.id">
|
||||||
{{camera.label || camera.id}}
|
{{camera.label || camera.id}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
@@ -16,7 +18,8 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<mat-card class="warn" *ngIf="initialized && noCamera">
|
@if (initialized && noCamera) {
|
||||||
|
<mat-card class="warn">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>
|
<mat-card-title>
|
||||||
<mat-icon>no_photography</mat-icon>
|
<mat-icon>no_photography</mat-icon>
|
||||||
@@ -29,3 +32,4 @@
|
|||||||
</p>
|
</p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
@@ -2,9 +2,15 @@
|
|||||||
<mat-card [ngClass]="result.success ? 'success' : (result.response.status == 412 ? 'accent' : 'warn')">
|
<mat-card [ngClass]="result.success ? 'success' : (result.response.status == 412 ? 'accent' : 'warn')">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>
|
<mat-card-title>
|
||||||
<mat-icon *ngIf="!result.success && result.response.status != 412">block</mat-icon>
|
@if (!result.success && result.response.status != 412) {
|
||||||
<mat-icon *ngIf="!result.success && result.response.status == 412">help_outline</mat-icon>
|
<mat-icon>block</mat-icon>
|
||||||
<mat-icon *ngIf="result.success">check</mat-icon>
|
}
|
||||||
|
@if (!result.success && result.response.status == 412) {
|
||||||
|
<mat-icon>help_outline</mat-icon>
|
||||||
|
}
|
||||||
|
@if (result.success) {
|
||||||
|
<mat-icon>check</mat-icon>
|
||||||
|
}
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
<mat-card-subtitle>{{'borrow.proving.' + (result.success ? 'valid' : 'invalid') | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'borrow.proving.' + (result.success ? 'valid' : 'invalid') | i18n}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
@@ -12,20 +18,29 @@
|
|||||||
<p>
|
<p>
|
||||||
{{'borrow.proving.' + (result.success ? 'valid' : 'invalid') + '.text' | i18n}}
|
{{'borrow.proving.' + (result.success ? 'valid' : 'invalid') + '.text' | i18n}}
|
||||||
</p>
|
</p>
|
||||||
<p *ngFor="let error of result.response.error">
|
@for (error of result.response.error; track error) {
|
||||||
<ng-container [ngSwitch]="error.field">
|
<p>
|
||||||
<span *ngSwitchCase="'nbf'">
|
@switch (error.field) {
|
||||||
|
@case ('nbf') {
|
||||||
|
<span>
|
||||||
{{'borrow.proving.error.' + error.code | i18n:(error.defaultMessage | datef)}}
|
{{'borrow.proving.error.' + error.code | i18n:(error.defaultMessage | datef)}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchCase="'exp'">
|
}
|
||||||
|
@case ('exp') {
|
||||||
|
<span>
|
||||||
{{'borrow.proving.error.' + error.code | i18n:(error.defaultMessage | datef)}}
|
{{'borrow.proving.error.' + error.code | i18n:(error.defaultMessage | datef)}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchDefault>
|
}
|
||||||
|
@default {
|
||||||
|
<span>
|
||||||
{{'borrow.proving.error.default.' + error.code | i18n:error.defaultMessage}}
|
{{'borrow.proving.error.default.' + error.code | i18n:error.defaultMessage}}
|
||||||
</span>
|
</span>
|
||||||
</ng-container>
|
}
|
||||||
|
}
|
||||||
</p>
|
</p>
|
||||||
<table *ngIf="result.success">
|
}
|
||||||
|
@if (result.success) {
|
||||||
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{'borrow.request.user' | i18n}}</th>
|
<th>{{'borrow.request.user' | i18n}}</th>
|
||||||
<td>{{result.response.user}}</td>
|
<td>{{result.response.user}}</td>
|
||||||
@@ -47,6 +62,7 @@
|
|||||||
<td>{{result.response.exp | datef}}</td>
|
<td>{{result.response.exp | datef}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a mat-raised-button [mat-dialog-close]="false">{{'ok' | i18n}}</a>
|
<a mat-raised-button [mat-dialog-close]="false">{{'ok' | i18n}}</a>
|
||||||
|
|||||||
@@ -4,22 +4,25 @@
|
|||||||
<h3>{{borrowRequest.borrowItem.name}}</h3>
|
<h3>{{borrowRequest.borrowItem.name}}</h3>
|
||||||
<p>{{borrowRequest.borrowItem.description}}</p>
|
<p>{{borrowRequest.borrowItem.description}}</p>
|
||||||
|
|
||||||
<a *ngIf="borrowRequest.borrowItem.url" mat-button color="accent" href="{{ borrowRequest.borrowItem.url }}"
|
@if (borrowRequest.borrowItem.url) {
|
||||||
|
<a mat-button color="accent" href="{{ borrowRequest.borrowItem.url }}"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
{{ borrowRequest.borrowItem.url }}
|
{{ borrowRequest.borrowItem.url }}
|
||||||
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<ng-container *ngIf="borrowRequest.id">
|
@if (borrowRequest.id) {
|
||||||
<mat-chip-listbox *ngSwitch="borrowRequest.status">
|
<mat-chip-listbox >
|
||||||
<mat-chip *ngSwtichCase="'PENDING'" color="primary" selected></mat-chip>
|
@if (borrowRequest.status === 'PENDING') {
|
||||||
|
<mat-chip color="primary" selected></mat-chip>
|
||||||
|
}
|
||||||
<mat-chip color="accent" selected>Accent fish</mat-chip>
|
<mat-chip color="accent" selected>Accent fish</mat-chip>
|
||||||
</mat-chip-listbox>
|
</mat-chip-listbox>
|
||||||
|
}
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
@@ -55,9 +58,11 @@
|
|||||||
<mat-icon>save</mat-icon>{{(create ? 'borrow.request.create' : 'borrow.request.save') | i18n}}
|
<mat-icon>save</mat-icon>{{(create ? 'borrow.request.create' : 'borrow.request.save') | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<a *ngIf="borrowRequest.id" mat-button color="warn" (click)="confirmDelete()">
|
@if (borrowRequest.id) {
|
||||||
|
<a mat-button color="warn" (click)="confirmDelete()">
|
||||||
<mat-icon>delete</mat-icon> {{ 'borrow.request.delete' |
|
<mat-icon>delete</mat-icon> {{ 'borrow.request.delete' |
|
||||||
i18n}}
|
i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</mat-dialog-actions>
|
</mat-dialog-actions>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<h3>{{'borrow.requests' | i18n}}</h3>
|
<h3>{{'borrow.requests' | i18n}}</h3>
|
||||||
<div *ngIf="borrowRequests">
|
@if (borrowRequests) {
|
||||||
|
<div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<mat-slide-toggle [formControl]="ownerFormControl">{{'borrow.requests.mine' | i18n}}</mat-slide-toggle>
|
<mat-slide-toggle [formControl]="ownerFormControl">{{'borrow.requests.mine' | i18n}}</mat-slide-toggle>
|
||||||
</div>
|
</div>
|
||||||
@@ -8,43 +9,45 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'borrow.item.name' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'borrow.item.name' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.borrowItem.name}} </td>
|
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.borrowItem.name}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="starts">
|
<ng-container matColumnDef="starts">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.starts' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.starts' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.starts | datef}}
|
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.starts | datef}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="ends">
|
<ng-container matColumnDef="ends">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.ends' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.ends' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.ends | datef}}
|
<td mat-cell *matCellDef="let borrowRequest"> {{ borrowRequest.ends | datef}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="status">
|
<ng-container matColumnDef="status">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.status' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'borrow.requests.status' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowRequest"> {{ 'borrow.requests.status.' + borrowRequest.status | i18n}}
|
<td mat-cell *matCellDef="let borrowRequest"> {{ 'borrow.requests.status.' + borrowRequest.status | i18n}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'borrow.requests.actions' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'borrow.requests.actions' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let borrowRequest" class="text-right">
|
<td mat-cell *matCellDef="let borrowRequest" class="text-right">
|
||||||
<a mat-icon-button *ngIf="borrowRequest.user == userId" (click)="edit(borrowRequest)">
|
@if (borrowRequest.user == userId) {
|
||||||
|
<a mat-icon-button (click)="edit(borrowRequest)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a mat-icon-button *ngIf="borrowRequest.user == userId" (click)="confirmDelete(borrowRequest)">
|
}
|
||||||
|
@if (borrowRequest.user == userId) {
|
||||||
|
<a mat-icon-button (click)="confirmDelete(borrowRequest)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a mat-icon-button *ngIf="borrowRequest.item.owner != userId" (click)="updateStatus(borrowRequest)">
|
}
|
||||||
|
@if (borrowRequest.item.owner != userId) {
|
||||||
|
<a mat-icon-button (click)="updateStatus(borrowRequest)">
|
||||||
<mat-icon>pending_actions</mat-icon>
|
<mat-icon>pending_actions</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="borrowRequestColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="borrowRequestColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: borrowRequestColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: borrowRequestColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="borrowRequests.totalElements"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="borrowRequests.totalElements"
|
||||||
[pageSize]="borrowRequests.size" (page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
[pageSize]="borrowRequests.size" (page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -4,22 +4,28 @@
|
|||||||
<h2>{{'security.2fa.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
<h2>{{'security.2fa.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</h2>
|
</h2>
|
||||||
<mat-error *ngIf="loginInvalid">
|
@if (loginInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'security.2fa.invalid' | i18n}}
|
{{'security.2fa.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<input id="provider" name="provider" matInput hidden [value]="selectedProvider.id">
|
<input id="provider" name="provider" matInput hidden [value]="selectedProvider.id">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'security.2fa.provider' | i18n}}</mat-label>
|
<mat-label>{{'security.2fa.provider' | i18n}}</mat-label>
|
||||||
<mat-select [(ngModel)]="selectedProvider" [ngModelOptions]="{standalone: true}">
|
<mat-select [(ngModel)]="selectedProvider" [ngModelOptions]="{standalone: true}">
|
||||||
<mat-option *ngFor="let provider of providers" [value]="provider">
|
@for (provider of providers; track provider) {
|
||||||
|
<mat-option [value]="provider">
|
||||||
{{'security.2fa.' + provider.id | i18n}}
|
{{'security.2fa.' + provider.id | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@if (selectedProvider && selectedProvider.request) {
|
||||||
<a mat-raised-button (click)="request()"
|
<a mat-raised-button (click)="request()"
|
||||||
*ngIf="selectedProvider && selectedProvider.request">{{'security.2fa.' + selectedProvider.id +
|
>{{'security.2fa.' + selectedProvider.id +
|
||||||
'.request'
|
'.request'
|
||||||
| i18n}}</a>
|
| i18n}}</a>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'security.2fa.code' | i18n}}</mat-label>
|
<mat-label>{{'security.2fa.code' | i18n}}</mat-label>
|
||||||
<input id="code" name="code" matInput required matAutofocus>
|
<input id="code" name="code" matInput required matAutofocus>
|
||||||
@@ -27,9 +33,11 @@
|
|||||||
{{'security.2fa.missing' | i18n}}
|
{{'security.2fa.missing' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-slide-toggle #toggle *ngIf="keep" [checked]="true" [disabled]="true">
|
@if (keep) {
|
||||||
|
<mat-slide-toggle #toggle [checked]="true" [disabled]="true">
|
||||||
{{'security.2fa.keepSession' | i18n}}
|
{{'security.2fa.keepSession' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
}
|
||||||
<input class="hidden" type="checkbox" id="keep" name="keep" [checked]="keep">
|
<input class="hidden" type="checkbox" id="keep" name="keep" [checked]="keep">
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'security.oidc' | i18n}}</h2>
|
<h2>{{'security.oidc' | i18n}}</h2>
|
||||||
<mat-error *ngIf="loginInvalid">
|
@if (loginInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'security.oidc.login.invalid' | i18n}}
|
{{'security.oidc.login.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<input id="code" name="code" type="hidden" formControlName="code" required>
|
<input id="code" name="code" type="hidden" formControlName="code" required>
|
||||||
<input id="state" name="state" type="hidden" formControlName="state" required>
|
<input id="state" name="state" type="hidden" formControlName="state" required>
|
||||||
<input id="client_id" name="client_id" type="hidden" formControlName="client_id" required>
|
<input id="client_id" name="client_id" type="hidden" formControlName="client_id" required>
|
||||||
@@ -14,19 +16,21 @@
|
|||||||
<input id="nonce" name="nonce" type="hidden" formControlName="nonce">
|
<input id="nonce" name="nonce" type="hidden" formControlName="nonce">
|
||||||
<input id="prompt" name="prompt" type="hidden" formControlName="prompt">
|
<input id="prompt" name="prompt" type="hidden" formControlName="prompt">
|
||||||
<input id="login_hint" name="login_hint" type="hidden" formControlName="login_hint">
|
<input id="login_hint" name="login_hint" type="hidden" formControlName="login_hint">
|
||||||
<ng-container *ngIf="authorize">
|
@if (authorize) {
|
||||||
<h3>{{'security.oidc.authorize' | i18n}}</h3>
|
<h3>{{'security.oidc.authorize' | i18n}}</h3>
|
||||||
<p>{{'security.oidc.authorize.hint' | i18n}}</p>
|
<p>{{'security.oidc.authorize.hint' | i18n}}</p>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="alias">
|
@if (alias) {
|
||||||
<h3>{{'security.oidc.alias' | i18n}}</h3>
|
<h3>{{'security.oidc.alias' | i18n}}</h3>
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<mat-list-item (click)="setAlias('')"
|
<mat-list-item (click)="setAlias('')"
|
||||||
[ngClass]="{'active' : !selectedAlias || selectedAlias == ''}">{{auth.name}}</mat-list-item>
|
[ngClass]="{'active' : !selectedAlias || selectedAlias == ''}">{{auth.name}}</mat-list-item>
|
||||||
<mat-list-item *ngFor="let userAlias of aliases" (click)="setAlias(userAlias.alias)"
|
@for (userAlias of aliases; track userAlias) {
|
||||||
|
<mat-list-item (click)="setAlias(userAlias.alias)"
|
||||||
[ngClass]="{'active' : selectedAlias == userAlias.alias}">{{userAlias.alias}}</mat-list-item>
|
[ngClass]="{'active' : selectedAlias == userAlias.alias}">{{userAlias.alias}}</mat-list-item>
|
||||||
|
}
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
<h2>{{'login.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
<h2>{{'login.external' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</h2>
|
</h2>
|
||||||
<mat-error *ngIf="loginInvalid">
|
@if (loginInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'login.invalid' | i18n}}
|
{{'login.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'username' | i18n}}</mat-label>
|
<mat-label>{{'username' | i18n}}</mat-label>
|
||||||
<input id="username" name="username" matInput required matAutofocus>
|
<input id="username" name="username" matInput required matAutofocus>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<mat-card-title>{{'invites.register' | i18n}}</mat-card-title>
|
<mat-card-title>{{'invites.register' | i18n}}</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<ng-container *ngIf="invite">
|
@if (invite) {
|
||||||
<h3>
|
<h3>
|
||||||
<mat-icon inline="true">{{'invites.quota.' + invite.quota + ".icon" | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'invites.quota.' + invite.quota + ".icon" | i18n}}</mat-icon>
|
||||||
{{'invites.quota.'
|
{{'invites.quota.'
|
||||||
@@ -11,21 +11,26 @@
|
|||||||
invite.quota
|
invite.quota
|
||||||
| i18n}}
|
| i18n}}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<p>{{'invites.quota.' + invite.quota +
|
<p>{{'invites.quota.' + invite.quota +
|
||||||
".text" | i18n}}</p>
|
".text" | i18n}}</p>
|
||||||
<p *ngIf="invite.url">
|
@if (invite.url) {
|
||||||
|
<p>
|
||||||
<a mat-button href="{{invite.url}}" target="_blank" color="accent">{{'invites.register.url' |
|
<a mat-button href="{{invite.url}}" target="_blank" color="accent">{{'invites.register.url' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
</p>
|
</p>
|
||||||
|
}
|
||||||
<ng-container *ngIf="!success">
|
@if (!success) {
|
||||||
<blockquote *ngIf="invite.message && auth.principal.userId != invite.owner" class="message">
|
@if (invite.message && auth.principal.userId != invite.owner) {
|
||||||
|
<blockquote class="message">
|
||||||
{{invite.message}}</blockquote>
|
{{invite.message}}</blockquote>
|
||||||
<blockquote *ngIf="invite.note && auth.principal.userId != invite.owner" class="note">{{invite.note}}
|
}
|
||||||
|
@if (invite.note && auth.principal.userId != invite.owner) {
|
||||||
|
<blockquote class="note">{{invite.note}}
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<form [formGroup]="form" *ngIf="!error">
|
}
|
||||||
<ng-container *ngIf="!auth.authenticated">
|
@if (!error) {
|
||||||
|
<form [formGroup]="form">
|
||||||
|
@if (!auth.authenticated) {
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'username' | i18n}}</mat-label>
|
<mat-label>{{'username' | i18n}}</mat-label>
|
||||||
<input matInput formControlName="username" matAutofocus tabindex="1">
|
<input matInput formControlName="username" matAutofocus tabindex="1">
|
||||||
@@ -40,9 +45,11 @@
|
|||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password" tabindex="2">
|
<input matInput type="password" formControlName="password" tabindex="2">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
<div *ngFor="let error of form.get('password').errors | keyvalue">
|
@for (error of form.get('password').errors | keyvalue; track error) {
|
||||||
|
<div>
|
||||||
{{'password.error.' + error.key | i18n}}<br>
|
{{'password.error.' + error.key | i18n}}<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
@@ -52,8 +59,8 @@
|
|||||||
{{'password.not-match' | i18n}}
|
{{'password.not-match' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="auth.principal.userId == invite.owner">
|
@if (auth.principal.userId == invite.owner) {
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'invite.message' | i18n}}</mat-label>
|
<mat-label>{{'invite.message' | i18n}}</mat-label>
|
||||||
<textarea matInput formControlName="message"></textarea>
|
<textarea matInput formControlName="message"></textarea>
|
||||||
@@ -68,38 +75,44 @@
|
|||||||
{{'invites.error.note' | i18n}}
|
{{'invites.error.note' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</ng-container>
|
}
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="success">
|
}
|
||||||
|
@if (success) {
|
||||||
<h2>{{'invites.register.success' | i18n}}</h2>
|
<h2>{{'invites.register.success' | i18n}}</h2>
|
||||||
<p>{{'invites.register.success.text' | i18n}}</p>
|
<p>{{'invites.register.success.text' | i18n}}</p>
|
||||||
</ng-container>
|
}
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="error">
|
@if (error) {
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'invites.register.error.' + error | i18n}}
|
{{'invites.register.error.' + error | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</ng-container>
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<ng-container *ngIf="!success && invite">
|
@if (!success && invite) {
|
||||||
<a *ngIf="!working && !auth.authenticated && !error" mat-raised-button color="primary"
|
@if (!working && !auth.authenticated && !error) {
|
||||||
|
<a mat-raised-button color="primary"
|
||||||
[disabled]="form.invalid" (click)="register()" tabindex="4">
|
[disabled]="form.invalid" (click)="register()" tabindex="4">
|
||||||
{{'invites.register' | i18n}}
|
{{'invites.register' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<a *ngIf="auth.principal.userId == invite.owner && !error" mat-raised-button color="primary"
|
@if (auth.principal.userId == invite.owner && !error) {
|
||||||
|
<a mat-raised-button color="primary"
|
||||||
(click)="save()" tabindex="4">
|
(click)="save()" tabindex="4">
|
||||||
{{'invites.edit.save' | i18n}}
|
{{'invites.edit.save' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
}
|
||||||
<ng-container *ngIf="success">
|
}
|
||||||
|
@if (success) {
|
||||||
<a routerLink="/login" mat-raised-button color="primary">
|
<a routerLink="/login" mat-raised-button color="primary">
|
||||||
{{'invites.register.login' | i18n}}
|
{{'invites.register.login' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</ng-container>
|
}
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#invite" class="help-button"
|
<a href="https://wiki.bstly.de/services/webstly#invite" class="help-button"
|
||||||
@@ -109,11 +122,15 @@
|
|||||||
</mat-card-footer>
|
</mat-card-footer>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<div *ngIf="!success && permissions && permissions[0] && !error">
|
@if (!success && permissions && permissions[0] && !error) {
|
||||||
|
<div>
|
||||||
<h3>{{'permissions' | i18n}}</h3>
|
<h3>{{'permissions' | i18n}}</h3>
|
||||||
<app-permissions [permissions]="permissions"></app-permissions>
|
<app-permissions [permissions]="permissions"></app-permissions>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!success && quotas && quotas[0] && !error">
|
}
|
||||||
|
@if (!success && quotas && quotas[0] && !error) {
|
||||||
|
<div>
|
||||||
<h3>{{'quotas' | i18n}}</h3>
|
<h3>{{'quotas' | i18n}}</h3>
|
||||||
<app-quotas [quotas]="quotas"></app-quotas>
|
<app-quotas [quotas]="quotas"></app-quotas>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '../../../../variables.scss';
|
@use '../../../../variables.scss' as vars;
|
||||||
|
|
||||||
|
|
||||||
mat-form-field {
|
mat-form-field {
|
||||||
@@ -14,10 +14,10 @@ blockquote {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
||||||
&.message {
|
&.message {
|
||||||
border-left: 2px solid $accent;
|
border-left: 2px solid vars.$accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.note {
|
&.note {
|
||||||
border-left: 2px solid $primary;
|
border-left: 2px solid vars.$primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<h2 mat-dialog-title>{{'invites.edit' | i18n}}</h2>
|
<h2 mat-dialog-title>{{'invites.edit' | i18n}}</h2>
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<mat-error *ngIf="error">
|
@if (error) {
|
||||||
|
<mat-error>
|
||||||
{{'invites.register.error.' + error | i18n}}
|
{{'invites.register.error.' + error | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'invite.message' | i18n}}</mat-label>
|
<mat-label>{{'invite.message' | i18n}}</mat-label>
|
||||||
<textarea matInput formControlName="message"></textarea>
|
<textarea matInput formControlName="message"></textarea>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<h3>{{'invites' | i18n}}</h3>
|
<h3>{{'invites' | i18n}}</h3>
|
||||||
|
|
||||||
<div *ngIf="invites">
|
@if (invites) {
|
||||||
|
<div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'invites.search' | i18n}}</mat-label>
|
<mat-label>{{'invites.search' | i18n}}</mat-label>
|
||||||
@@ -16,58 +17,69 @@
|
|||||||
<mat-option value="false">
|
<mat-option value="false">
|
||||||
<mat-icon>person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
<mat-icon>person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<mat-select-trigger [ngSwitch]="redeemedFormControl.value">
|
<mat-select-trigger>
|
||||||
<span *ngSwitchCase="'true'">
|
@switch (redeemedFormControl.value) {
|
||||||
|
@case ('true') {
|
||||||
|
<span>
|
||||||
<mat-icon inline="true">how_to_reg</mat-icon>{{'invites.redeemed.filter.true' | i18n}}
|
<mat-icon inline="true">how_to_reg</mat-icon>{{'invites.redeemed.filter.true' | i18n}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchCase="'false'">
|
}
|
||||||
|
@case ('false') {
|
||||||
|
<span>
|
||||||
<mat-icon inline="true">person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
<mat-icon inline="true">person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchDefault>{{'invites.redeemed.filter.none' | i18n}}</span>
|
}
|
||||||
|
@default {
|
||||||
|
<span>{{'invites.redeemed.filter.none' | i18n}}</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
</mat-select-trigger>
|
</mat-select-trigger>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<table mat-table matSort [dataSource]="invites.content">
|
<table mat-table matSort [dataSource]="invites.content">
|
||||||
|
|
||||||
<ng-container matColumnDef="starts">
|
<ng-container matColumnDef="starts">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.starts' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.starts' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite"> {{ invite.starts | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let invite"> {{ invite.starts | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="expires">
|
<ng-container matColumnDef="expires">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.expires' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.expires' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite"> {{ invite.expires | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let invite"> {{ invite.expires | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="link">
|
<ng-container matColumnDef="link">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.link' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.link' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite">
|
<td mat-cell *matCellDef="let invite">
|
||||||
<a href="{{ invite.codeLink }}" target="_blank" mat-button color="accent">{{invite.code}}</a>
|
<a href="{{ invite.codeLink }}" target="_blank" mat-button color="accent">{{invite.code}}</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="note">
|
<ng-container matColumnDef="note">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.note' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.note' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite"> <span *ngIf="invite.note">{{ invite.note}}</span> <i
|
<td mat-cell *matCellDef="let invite"> @if (invite.note) {
|
||||||
*ngIf="!invite.note">{{ 'invite.noNote' | i18n}}</i>
|
<span>{{ invite.note}}</span>
|
||||||
|
} @if (!invite.note) {
|
||||||
|
<i
|
||||||
|
>{{ 'invite.noNote' | i18n}}</i>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="message">
|
<ng-container matColumnDef="message">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.message' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.message' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite"> <i *ngIf="!invite.message">{{ 'invite.noMessage' | i18n}}</i>
|
<td mat-cell *matCellDef="let invite"> @if (!invite.message) {
|
||||||
<mat-icon matTooltip="{{ invite.message}}" inline="true" *ngIf="invite.message">article</mat-icon>
|
<i>{{ 'invite.noMessage' | i18n}}</i>
|
||||||
|
}
|
||||||
|
@if (invite.message) {
|
||||||
|
<mat-icon matTooltip="{{ invite.message}}" inline="true">article</mat-icon>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="redeemed">
|
<ng-container matColumnDef="redeemed">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.redeemed' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.redeemed' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite">
|
<td mat-cell *matCellDef="let invite">
|
||||||
<mat-icon *ngIf="invite.redeemed">how_to_reg</mat-icon>
|
@if (invite.redeemed) {
|
||||||
|
<mat-icon>how_to_reg</mat-icon>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.actions' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.actions' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite">
|
<td mat-cell *matCellDef="let invite">
|
||||||
@@ -76,32 +88,38 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="inviteColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="inviteColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: inviteColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: inviteColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="invites.totalElements" [pageSize]="invites.size"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="invites.totalElements" [pageSize]="invites.size"
|
||||||
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'invites.info' | i18n}}</p>
|
<p>{{'invites.info' | i18n}}</p>
|
||||||
<p *ngIf="!inviteQuota">{{'invites.noQuota' | i18n}}</p>
|
@if (!inviteQuota) {
|
||||||
<div *ngIf="inviteQuota">
|
<p>{{'invites.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (inviteQuota) {
|
||||||
|
<div>
|
||||||
<p>{{'invites.left' | i18n:inviteQuota}}</p>
|
<p>{{'invites.left' | i18n:inviteQuota}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a *ngIf="inviteQuota && !working" mat-raised-button color="primary" (click)="create()">
|
@if (inviteQuota && !working) {
|
||||||
|
<a mat-raised-button color="primary" (click)="create()">
|
||||||
{{'invite.create' | i18n}}
|
{{'invite.create' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<div *ngIf="others && others.content">
|
@if (others && others.content) {
|
||||||
|
<div>
|
||||||
<h4>{{'invites.others' | i18n}}</h4>
|
<h4>{{'invites.others' | i18n}}</h4>
|
||||||
|
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'invites.search' | i18n}}</mat-label>
|
<mat-label>{{'invites.search' | i18n}}</mat-label>
|
||||||
@@ -117,14 +135,22 @@
|
|||||||
<mat-option value="false">
|
<mat-option value="false">
|
||||||
<mat-icon>person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
<mat-icon>person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<mat-select-trigger [ngSwitch]="redeemedOthersFormControl.value">
|
<mat-select-trigger>
|
||||||
<span *ngSwitchCase="'true'">
|
@switch (redeemedOthersFormControl.value) {
|
||||||
|
@case ('true') {
|
||||||
|
<span>
|
||||||
<mat-icon inline="true">how_to_reg</mat-icon>{{'invites.redeemed.filter.true' | i18n}}
|
<mat-icon inline="true">how_to_reg</mat-icon>{{'invites.redeemed.filter.true' | i18n}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchCase="'false'">
|
}
|
||||||
|
@case ('false') {
|
||||||
|
<span>
|
||||||
<mat-icon inline="true">person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
<mat-icon inline="true">person_remove</mat-icon>{{'invites.redeemed.filter.false' | i18n}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngSwitchDefault>{{'invites.redeemed.filter.none' | i18n}}</span>
|
}
|
||||||
|
@default {
|
||||||
|
<span>{{'invites.redeemed.filter.none' | i18n}}</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
</mat-select-trigger>
|
</mat-select-trigger>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@@ -132,20 +158,25 @@
|
|||||||
<table mat-table matSort [dataSource]="others.content">
|
<table mat-table matSort [dataSource]="others.content">
|
||||||
<ng-container matColumnDef="note">
|
<ng-container matColumnDef="note">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.note' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.note' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite"> <span *ngIf="invite.note">{{ invite.note}}</span> <i
|
<td mat-cell *matCellDef="let invite"> @if (invite.note) {
|
||||||
*ngIf="!invite.note">{{ 'invite.noNote' | i18n}}</i> </td>
|
<span>{{ invite.note}}</span>
|
||||||
|
} @if (!invite.note) {
|
||||||
|
<i
|
||||||
|
>{{ 'invite.noNote' | i18n}}</i>
|
||||||
|
} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="redeemed">
|
<ng-container matColumnDef="redeemed">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'invite.redeemed' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'invite.redeemed' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let invite">
|
<td mat-cell *matCellDef="let invite">
|
||||||
<mat-icon *ngIf="invite.redeemed">how_to_reg</mat-icon>
|
@if (invite.redeemed) {
|
||||||
|
<mat-icon>how_to_reg</mat-icon>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="otherColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="otherColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: otherColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: otherColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="others.totalElements" [pageSize]="others.size"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="others.totalElements" [pageSize]="others.size"
|
||||||
(page)="updateOthers($event)" showFirstLastButtons></mat-paginator>
|
(page)="updateOthers($event)" showFirstLastButtons></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<h3>{{'jitsi.rooms' | i18n}}</h3>
|
<h3>{{'jitsi.rooms' | i18n}}</h3>
|
||||||
|
|
||||||
<div *ngIf="jitsiRooms">
|
@if (jitsiRooms) {
|
||||||
|
<div>
|
||||||
<table mat-table matSort [dataSource]="jitsiRooms.content" (matSortChange)="updateSort($event)">
|
<table mat-table matSort [dataSource]="jitsiRooms.content" (matSortChange)="updateSort($event)">
|
||||||
|
|
||||||
<ng-container matColumnDef="share">
|
<ng-container matColumnDef="share">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'jitsi.share' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'jitsi.share' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom">
|
<td mat-cell *matCellDef="let jitsiRoom">
|
||||||
@@ -11,62 +11,62 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="room">
|
<ng-container matColumnDef="room">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="room"> {{'jitsi.rooms.room' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="room"> {{'jitsi.rooms.room' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom">
|
<td mat-cell *matCellDef="let jitsiRoom">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<a *ngIf="open(jitsiRoom, false)" mat-button color="accent" href="{{ jitsiRoom.url }}" target="_blank">
|
@if (open(jitsiRoom, false)) {
|
||||||
|
<a mat-button color="accent" href="{{ jitsiRoom.url }}" target="_blank">
|
||||||
{{ jitsiRoom.room }}
|
{{ jitsiRoom.room }}
|
||||||
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<a *ngIf="!open(jitsiRoom, false)" mat-button matTooltip="{{'jitsi.rooms.notStarted' | i18n}}"
|
@if (!open(jitsiRoom, false)) {
|
||||||
|
<a mat-button matTooltip="{{'jitsi.rooms.notStarted' | i18n}}"
|
||||||
(click)="copyRoomUrlToClipboard(jitsiRoom)">
|
(click)="copyRoomUrlToClipboard(jitsiRoom)">
|
||||||
{{ jitsiRoom.room }}
|
{{ jitsiRoom.room }}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<a *ngIf="!jitsiRoom.code && shortenedUrlQuota" mat-icon-button (click)="createShortenedUrl(jitsiRoom)" inline
|
@if (!jitsiRoom.code && shortenedUrlQuota) {
|
||||||
|
<a mat-icon-button (click)="createShortenedUrl(jitsiRoom)" inline
|
||||||
matTooltip="{{'urlshortener.create' | i18n}}">
|
matTooltip="{{'urlshortener.create' | i18n}}">
|
||||||
<mat-icon>add_link</mat-icon>
|
<mat-icon>add_link</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
<ng-container matColumnDef="starts">
|
<ng-container matColumnDef="starts">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="starts"> {{'jitsi.rooms.starts' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="starts"> {{'jitsi.rooms.starts' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom">{{ jitsiRoom.starts | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let jitsiRoom">{{ jitsiRoom.starts | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="moderationStarts">
|
<ng-container matColumnDef="moderationStarts">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="moderationStarts"> {{'jitsi.rooms.moderationStarts' |
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="moderationStarts"> {{'jitsi.rooms.moderationStarts' |
|
||||||
i18n}} </th>
|
i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom">{{ jitsiRoom.moderationStarts | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let jitsiRoom">{{ jitsiRoom.moderationStarts | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="expires">
|
<ng-container matColumnDef="expires">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="expires"> {{'jitsi.rooms.expires' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="expires"> {{'jitsi.rooms.expires' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom"> {{ jitsiRoom.expires | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let jitsiRoom"> {{ jitsiRoom.expires | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="moderationUrl">
|
<ng-container matColumnDef="moderationUrl">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="moderationUrl"> {{'jitsi.rooms.moderationUrl' | i18n}}
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="moderationUrl"> {{'jitsi.rooms.moderationUrl' | i18n}}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom">
|
<td mat-cell *matCellDef="let jitsiRoom">
|
||||||
<a *ngIf="open(jitsiRoom, true)" mat-button color="primary" href="{{ jitsiRoom.moderationUrl}}" target="_blank">
|
@if (open(jitsiRoom, true)) {
|
||||||
|
<a mat-button color="primary" href="{{ jitsiRoom.moderationUrl}}" target="_blank">
|
||||||
<span class="url">{{ jitsiRoom.moderationUrl }}</span>
|
<span class="url">{{ jitsiRoom.moderationUrl }}</span>
|
||||||
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
<mat-icon style="font-size: 1em;">open_in_new</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<a *ngIf="!open(jitsiRoom, true)" mat-button color="primary" disabled
|
@if (!open(jitsiRoom, true)) {
|
||||||
|
<a mat-button color="primary" disabled
|
||||||
matTooltip="{{'jitsi.rooms.notStarted' | i18n}}" matTooltipPosition="above">
|
matTooltip="{{'jitsi.rooms.notStarted' | i18n}}" matTooltipPosition="above">
|
||||||
<span class="url">{{ jitsiRoom.moderationUrl }}</span>
|
<span class="url">{{ jitsiRoom.moderationUrl }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="edit">
|
<ng-container matColumnDef="edit">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'jitsi.rooms.edit' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'jitsi.rooms.edit' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom" class="text-right">
|
<td mat-cell *matCellDef="let jitsiRoom" class="text-right">
|
||||||
@@ -75,7 +75,6 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="delete">
|
<ng-container matColumnDef="delete">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'jitsi.rooms.delete' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'jitsi.rooms.delete' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let jitsiRoom" class="text-right">
|
<td mat-cell *matCellDef="let jitsiRoom" class="text-right">
|
||||||
@@ -84,21 +83,23 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="jitsiRoomsColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="jitsiRoomsColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: jitsiRoomsColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: jitsiRoomsColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="jitsiRooms.totalElements" [pageSize]="jitsiRooms.size"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="jitsiRooms.totalElements" [pageSize]="jitsiRooms.size"
|
||||||
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<form [formGroup]="form" (ngSubmit)="create()" #formDirective="ngForm">
|
<form [formGroup]="form" (ngSubmit)="create()" #formDirective="ngForm">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'jitsi.rooms.info' | i18n}}</p>
|
<p>{{'jitsi.rooms.info' | i18n}}</p>
|
||||||
<p *ngIf="!jitsiRoomsQuota">{{'jitsi.rooms.noQuota' | i18n}}</p>
|
@if (!jitsiRoomsQuota) {
|
||||||
<div *ngIf="jitsiRoomsQuota">
|
<p>{{'jitsi.rooms.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (jitsiRoomsQuota) {
|
||||||
|
<div>
|
||||||
<p>{{'jitsi.rooms.left' | i18n:jitsiRoomsQuota}}</p>
|
<p>{{'jitsi.rooms.left' | i18n:jitsiRoomsQuota}}</p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.room' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.room' | i18n}}</mat-label>
|
||||||
@@ -107,7 +108,6 @@
|
|||||||
{{'jitsi.rooms.error.room' | i18n}}
|
{{'jitsi.rooms.error.room' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.starts' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.starts' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.starts" formControlName="starts">
|
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.starts" formControlName="starts">
|
||||||
@@ -115,15 +115,15 @@
|
|||||||
{{'jitsi.rooms.error.starts' | i18n}}
|
{{'jitsi.rooms.error.starts' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@if (jitsiRoom.starts) {
|
||||||
<mat-form-field *ngIf="jitsiRoom.starts">
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.moderationStarts' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.moderationStarts' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.moderationStarts" formControlName="moderationStarts">
|
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.moderationStarts" formControlName="moderationStarts">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'jitsi.rooms.error.moderationStarts' | i18n}}
|
{{'jitsi.rooms.error.moderationStarts' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.expires' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.expires' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.expires" formControlName="expires">
|
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.expires" formControlName="expires">
|
||||||
@@ -131,14 +131,16 @@
|
|||||||
{{'jitsi.rooms.error.expires' | i18n}}
|
{{'jitsi.rooms.error.expires' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="jitsiRoomsQuota && !working" mat-raised-button color="primary"
|
@if (jitsiRoomsQuota && !working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary"
|
||||||
[disabled]="form.invalid">
|
[disabled]="form.invalid">
|
||||||
{{'jitsi.rooms.create' | i18n}}
|
{{'jitsi.rooms.create' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/jitsi#rooms" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/jitsi#rooms" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -19,13 +19,15 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field *ngIf="jitsiRoom.starts">
|
@if (jitsiRoom.starts) {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.moderationStarts' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.moderationStarts' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.moderationStarts" formControlName="moderationStarts">
|
<input matInput type="datetime-local" [(ngModel)]="jitsiRoom.moderationStarts" formControlName="moderationStarts">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'jitsi.rooms.error.moderationStarts' | i18n}}
|
{{'jitsi.rooms.error.moderationStarts' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'jitsi.rooms.expires' | i18n}}</mat-label>
|
<mat-label>{{'jitsi.rooms.expires' | i18n}}</mat-label>
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
<div *ngIf="active">
|
@if (active) {
|
||||||
|
<div>
|
||||||
<form (submit)="search()">
|
<form (submit)="search()">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<ng-container *ngIf="!checking">
|
@if (!checking) {
|
||||||
<mat-card-title-group *ngIf="currentTrack">
|
@if (currentTrack) {
|
||||||
<img *ngIf="getImageUrl(currentTrack)" mat-card-sm-image [src]="getImageUrl(currentTrack)">
|
<mat-card-title-group>
|
||||||
|
@if (getImageUrl(currentTrack)) {
|
||||||
|
<img mat-card-sm-image [src]="getImageUrl(currentTrack)">
|
||||||
|
}
|
||||||
<mat-card-title><small>{{'jukebox.current' | i18n}}</small></mat-card-title>
|
<mat-card-title><small>{{'jukebox.current' | i18n}}</small></mat-card-title>
|
||||||
<mat-card-title>{{currentTrack.name}}</mat-card-title>
|
<mat-card-title>{{currentTrack.name}}</mat-card-title>
|
||||||
<mat-card-subtitle>
|
<mat-card-subtitle>
|
||||||
<span *ngFor="let artist of currentTrack.artists; let i = index">
|
@for (artist of currentTrack.artists; track artist; let i = $index) {
|
||||||
{{artist.name}}<span *ngIf="(i+1) < currentTrack.artists.length">, </span>
|
<span>
|
||||||
|
{{artist.name}}@if ((i+1) < currentTrack.artists.length) {
|
||||||
|
<span>, </span>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
|
}
|
||||||
</mat-card-subtitle>
|
</mat-card-subtitle>
|
||||||
</mat-card-title-group>
|
</mat-card-title-group>
|
||||||
|
}
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<br />
|
<br />
|
||||||
@@ -35,64 +44,86 @@
|
|||||||
<mat-icon>refresh</mat-icon>
|
<mat-icon>refresh</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</mat-card-footer>
|
</mat-card-footer>
|
||||||
</ng-container>
|
}
|
||||||
|
@if (checking) {
|
||||||
<ng-container *ngIf="checking">
|
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</ng-container>
|
}
|
||||||
|
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</form>
|
</form>
|
||||||
|
@if (timeout) {
|
||||||
<p *ngIf="timeout">{{'jukebox.timeout' | i18n:timeout}}</p>
|
<p>{{'jukebox.timeout' | i18n:timeout}}</p>
|
||||||
|
}
|
||||||
<div *ngIf="searchResult && searchResult.items">
|
@if (searchResult && searchResult.items) {
|
||||||
<mat-card class="track" *ngFor="let track of searchResult.items; let i = index" (click)="queue(track)">
|
<div>
|
||||||
|
@for (track of searchResult.items; track track; let i = $index) {
|
||||||
|
<mat-card class="track" (click)="queue(track)">
|
||||||
<mat-card-title-group>
|
<mat-card-title-group>
|
||||||
<img *ngIf="getImageUrl(track)" mat-card-sm-image [src]="getImageUrl(track)">
|
@if (getImageUrl(track)) {
|
||||||
|
<img mat-card-sm-image [src]="getImageUrl(track)">
|
||||||
|
}
|
||||||
<mat-card-title>{{track.name}}</mat-card-title>
|
<mat-card-title>{{track.name}}</mat-card-title>
|
||||||
<mat-card-subtitle>
|
<mat-card-subtitle>
|
||||||
<span *ngFor="let artist of track.artists; let i = index">
|
@for (artist of track.artists; track artist; let i = $index) {
|
||||||
{{artist.name}}<span *ngIf="(i+1) < track.artists.length">, </span>
|
<span>
|
||||||
|
{{artist.name}}@if ((i+1) < track.artists.length) {
|
||||||
|
<span>, </span>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
|
}
|
||||||
</mat-card-subtitle>
|
</mat-card-subtitle>
|
||||||
</mat-card-title-group>
|
</mat-card-title-group>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
<mat-card *ngIf="searchResult && ((searchResult.offset + searchResult.limit) < searchResult.total)">
|
@if (searchResult && ((searchResult.offset + searchResult.limit) < searchResult.total)) {
|
||||||
|
<mat-card>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a mat-button (click)="searchMore()"> {{'jukebox.search.more' | i18n}}</a>
|
<a mat-button (click)="searchMore()"> {{'jukebox.search.more' | i18n}}</a>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card class="accent" *ngIf="wait">
|
@if (wait) {
|
||||||
|
<mat-card class="accent">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
||||||
<mat-card-subtitle>{{'jukebox.wait' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'jukebox.wait' | i18n}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-card-title-group *ngIf="currentTrack">
|
@if (currentTrack) {
|
||||||
<img *ngIf="getImageUrl(currentTrack)" mat-card-sm-image [src]="getImageUrl(currentTrack)">
|
<mat-card-title-group>
|
||||||
|
@if (getImageUrl(currentTrack)) {
|
||||||
|
<img mat-card-sm-image [src]="getImageUrl(currentTrack)">
|
||||||
|
}
|
||||||
<mat-card-title><small>{{'jukebox.current' | i18n}}</small></mat-card-title>
|
<mat-card-title><small>{{'jukebox.current' | i18n}}</small></mat-card-title>
|
||||||
<mat-card-title>{{currentTrack.name}}</mat-card-title>
|
<mat-card-title>{{currentTrack.name}}</mat-card-title>
|
||||||
<mat-card-subtitle>
|
<mat-card-subtitle>
|
||||||
<span *ngFor="let artist of currentTrack.artists; let i = index">
|
@for (artist of currentTrack.artists; track artist; let i = $index) {
|
||||||
{{artist.name}}<span *ngIf="(i+1) < currentTrack.artists.length">, </span>
|
<span>
|
||||||
|
{{artist.name}}@if ((i+1) < currentTrack.artists.length) {
|
||||||
|
<span>, </span>
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
|
}
|
||||||
</mat-card-subtitle>
|
</mat-card-subtitle>
|
||||||
</mat-card-title-group>
|
</mat-card-title-group>
|
||||||
<p *ngIf="timeout">{{'jukebox.timeout' | i18n:timeout}}</p>
|
}
|
||||||
|
@if (timeout) {
|
||||||
|
<p>{{'jukebox.timeout' | i18n:timeout}}</p>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card class="warn" *ngIf="unavailable">
|
@if (unavailable) {
|
||||||
|
<mat-card class="warn">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
||||||
<mat-card-subtitle>{{'jukebox.unavailable' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'jukebox.unavailable' | i18n}}</mat-card-subtitle>
|
||||||
@@ -103,8 +134,10 @@
|
|||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card *ngIf="forbidden">
|
@if (forbidden) {
|
||||||
|
<mat-card>
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
<mat-card-title>{{'jukebox' | i18n}}</mat-card-title>
|
||||||
<mat-card-subtitle>{{'jukebox.forbidden' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'jukebox.forbidden' | i18n}}</mat-card-subtitle>
|
||||||
@@ -115,3 +148,4 @@
|
|||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'security.2fa.totp' | i18n}}</h2>
|
<h2>{{'security.2fa.totp' | i18n}}</h2>
|
||||||
<mat-error *ngIf="loginInvalid">
|
@if (loginInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'security.2fa.totp.invalid' | i18n}}
|
{{'security.2fa.totp.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'security.2fa.totp.code' | i18n}}</mat-label>
|
<mat-label>{{'security.2fa.totp.code' | i18n}}</mat-label>
|
||||||
<input id="code" name="code" matInput formControlName="code"
|
<input id="code" name="code" matInput formControlName="code"
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'login' | i18n}}</h2>
|
<h2>{{'login' | i18n}}</h2>
|
||||||
<mat-error *ngIf="loginInvalid">
|
@if (loginInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'login.invalid' | i18n}}
|
{{'login.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'username' | i18n}}</mat-label>
|
<mat-label>{{'username' | i18n}}</mat-label>
|
||||||
<input id="username" name="username" matInput
|
<input id="username" name="username" matInput
|
||||||
|
|||||||
@@ -29,8 +29,11 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'minetest.accounts.info' | i18n}}</p>
|
<p>{{'minetest.accounts.info' | i18n}}</p>
|
||||||
<p *ngIf="!minetestAccountsQuota">{{'minetest.accounts.noQuota' | i18n}}</p>
|
@if (!minetestAccountsQuota) {
|
||||||
<div *ngIf="minetestAccountsQuota">
|
<p>{{'minetest.accounts.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (minetestAccountsQuota) {
|
||||||
|
<div>
|
||||||
<p>{{'minetest.accounts.left' | i18n:minetestAccountsQuota}}</p>
|
<p>{{'minetest.accounts.left' | i18n:minetestAccountsQuota}}</p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'minetest.accounts.name' | i18n}}</mat-label>
|
<mat-label>{{'minetest.accounts.name' | i18n}}</mat-label>
|
||||||
@@ -41,11 +44,14 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="minetestAccountsQuota && !working" mat-raised-button color="primary" [disabled]="form.invalid">
|
@if (minetestAccountsQuota && !working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="form.invalid">
|
||||||
{{'minetest.accounts.create' | i18n}}
|
{{'minetest.accounts.create' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/minetest" class="help-button"
|
<a href="https://wiki.bstly.de/services/minetest" class="help-button"
|
||||||
|
|||||||
@@ -1,17 +1,25 @@
|
|||||||
<h3>{{'partey.tags' | i18n}}</h3>
|
<h3>{{'partey.tags' | i18n}}</h3>
|
||||||
|
|
||||||
<p *ngIf="!tags || tags.length == 0">{{'partey.tags.none' | i18n}}</p>
|
@if (!tags || tags.length == 0) {
|
||||||
|
<p>{{'partey.tags.none' | i18n}}</p>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-chip-listbox>
|
<mat-chip-listbox>
|
||||||
<ng-container *ngFor="let tag of tags">
|
@for (tag of tags; track tag) {
|
||||||
<mat-chip *ngIf="activeTag(tag)" color="accent" selected matTooltip="{{ 'partey.tag.' + tag.tag + '.hint' | i18nEmpty}}">
|
@if (activeTag(tag)) {
|
||||||
|
<mat-chip color="accent" selected matTooltip="{{ 'partey.tag.' + tag.tag + '.hint' | i18nEmpty}}">
|
||||||
{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
||||||
<mat-chip *ngIf="upcomingTag(tag)" disabled matTooltip="{{'partey.tags.upcoming' | i18n:(tag.starts | datef)}}"
|
}
|
||||||
|
@if (upcomingTag(tag)) {
|
||||||
|
<mat-chip disabled matTooltip="{{'partey.tags.upcoming' | i18n:(tag.starts | datef)}}"
|
||||||
selected>{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
selected>{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
||||||
<mat-chip *ngIf="expiringTag(tag)" color="primary"
|
}
|
||||||
|
@if (expiringTag(tag)) {
|
||||||
|
<mat-chip color="primary"
|
||||||
matTooltip="{{'partey.tags.expires' | i18n:(tag.expires | datef)}}" selected>
|
matTooltip="{{'partey.tags.expires' | i18n:(tag.expires | datef)}}" selected>
|
||||||
{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
{{ 'partey.tag.' + tag.tag | i18nEmpty}}</mat-chip>
|
||||||
</ng-container>
|
}
|
||||||
|
}
|
||||||
</mat-chip-listbox>
|
</mat-chip-listbox>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,28 @@
|
|||||||
timeslot.type) | i18n}}
|
timeslot.type) | i18n}}
|
||||||
</h1>
|
</h1>
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
<h3 *ngIf="timeslot.id">{{'partey.timeslots.type.' + timeslot.type | i18n}}</h3>
|
@if (timeslot.id) {
|
||||||
|
<h3>{{'partey.timeslots.type.' + timeslot.type | i18n}}</h3>
|
||||||
|
}
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<mat-form-field *ngIf="timeslot.type == 'VIDEO' || timeslot.type == 'AUDIO'">
|
@if (timeslot.type == 'VIDEO' || timeslot.type == 'AUDIO') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'partey.timeslots.share.placeholder' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.share.placeholder' | i18n}}</mat-label>
|
||||||
<input matInput [(ngModel)]="timeslot.share" formControlName="share">
|
<input matInput [(ngModel)]="timeslot.share" formControlName="share">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngIf="timeslot.type == 'VIDEO_STREAM'">
|
}
|
||||||
|
@if (timeslot.type == 'VIDEO_STREAM') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'partey.timeslots.stream' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.stream' | i18n}}</mat-label>
|
||||||
<input matInput [(ngModel)]="timeslot.stream" formControlName="stream">
|
<input matInput [(ngModel)]="timeslot.stream" formControlName="stream">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngIf="timeslot.type == 'AUDIO_STREAM' && timeslot.secret">
|
}
|
||||||
|
@if (timeslot.type == 'AUDIO_STREAM' && timeslot.secret) {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'partey.timeslots.secret' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.secret' | i18n}}</mat-label>
|
||||||
<textarea [mat-autosize] matInput [value]="timeslot.secret" readonly></textarea>
|
<textarea [mat-autosize] matInput [value]="timeslot.secret" readonly></textarea>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'partey.timeslots.starts' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.starts' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="timeslot.starts" formControlName="starts">
|
<input matInput type="datetime-local" [(ngModel)]="timeslot.starts" formControlName="starts">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<h3>{{'partey.timeslots' | i18n}}</h3>
|
<h3>{{'partey.timeslots' | i18n}}</h3>
|
||||||
|
|
||||||
<div *ngIf="timeslots">
|
@if (timeslots) {
|
||||||
|
<div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'partey.timeslots.filter.search' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.filter.search' | i18n}}</mat-label>
|
||||||
@@ -18,13 +19,17 @@
|
|||||||
<mat-label>{{'partey.timeslots.filter.type' | i18n}}</mat-label>
|
<mat-label>{{'partey.timeslots.filter.type' | i18n}}</mat-label>
|
||||||
<mat-select [formControl]="typeFormControl">
|
<mat-select [formControl]="typeFormControl">
|
||||||
<mat-option value="">{{'partey.timeslots.filter.type.all' | i18n}}</mat-option>
|
<mat-option value="">{{'partey.timeslots.filter.type.all' | i18n}}</mat-option>
|
||||||
<mat-option *ngFor="let type of types" [value]="type">
|
@for (type of types; track type) {
|
||||||
|
<mat-option [value]="type">
|
||||||
<mat-icon inline="true">{{'partey.timeslots.type.' + type + '.icon' | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'partey.timeslots.type.' + type + '.icon' | i18n}}</mat-icon>
|
||||||
{{'partey.timeslots.filter.type.' + type | i18n}}
|
{{'partey.timeslots.filter.type.' + type | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
<mat-select-trigger>
|
<mat-select-trigger>
|
||||||
<mat-icon inline="true" *ngIf="typeFormControl.value ">{{'partey.timeslots.type.' + typeFormControl.value +
|
@if (typeFormControl.value ) {
|
||||||
'.icon' | i18n}}</mat-icon> {{'partey.timeslots.filter.type.' + (typeFormControl.value ?
|
<mat-icon inline="true">{{'partey.timeslots.type.' + typeFormControl.value +
|
||||||
|
'.icon' | i18n}}</mat-icon>
|
||||||
|
} {{'partey.timeslots.filter.type.' + (typeFormControl.value ?
|
||||||
typeFormControl.value
|
typeFormControl.value
|
||||||
: 'all') | i18n}}
|
: 'all') | i18n}}
|
||||||
</mat-select-trigger>
|
</mat-select-trigger>
|
||||||
@@ -40,23 +45,19 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="starts"> {{'partey.timeslots.starts' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="starts"> {{'partey.timeslots.starts' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot">{{ timeslot.starts | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let timeslot">{{ timeslot.starts | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="ends">
|
<ng-container matColumnDef="ends">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="ends"> {{'partey.timeslots.ends' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="ends"> {{'partey.timeslots.ends' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.ends | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.ends | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="title">
|
<ng-container matColumnDef="title">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="title"> {{'partey.timeslots.title' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="title"> {{'partey.timeslots.title' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.title }} </td>
|
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.title }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="description">
|
<ng-container matColumnDef="description">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="description"> {{'partey.timeslots.description' | i18n}}
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="description"> {{'partey.timeslots.description' | i18n}}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.description }} </td>
|
<td mat-cell *matCellDef="let timeslot"> {{ timeslot.description }} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="type">
|
<ng-container matColumnDef="type">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="type"> {{'partey.timeslots.type' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="type"> {{'partey.timeslots.type' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot">
|
<td mat-cell *matCellDef="let timeslot">
|
||||||
@@ -64,65 +65,78 @@
|
|||||||
{{'partey.timeslots.type.' + timeslot.type + '.icon' | i18n}}</mat-icon>
|
{{'partey.timeslots.type.' + timeslot.type + '.icon' | i18n}}</mat-icon>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="share">
|
<ng-container matColumnDef="share">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="share"> {{'partey.timeslots.share' | i18n}}
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="share"> {{'partey.timeslots.share' | i18n}}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let timeslot">
|
<td mat-cell *matCellDef="let timeslot">
|
||||||
<div *ngIf="timeslot.owner == userId">
|
@if (timeslot.owner == userId) {
|
||||||
|
<div>
|
||||||
<span> {{ timeslot.share }} </span>
|
<span> {{ timeslot.share }} </span>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="stream">
|
<ng-container matColumnDef="stream">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="stream"> {{'partey.timeslots.stream' | i18n}}
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="stream"> {{'partey.timeslots.stream' | i18n}}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let timeslot">
|
<td mat-cell *matCellDef="let timeslot">
|
||||||
<div *ngIf="timeslot.owner == userId">
|
@if (timeslot.owner == userId) {
|
||||||
<a *ngIf="timeslot.type == 'AUDIO_STREAM'" mat-raised-button
|
<div>
|
||||||
|
@if (timeslot.type == 'AUDIO_STREAM') {
|
||||||
|
<a mat-raised-button
|
||||||
(click)="copySecretToClipboard(timeslot.secret)">{{'partey.timeslots.secret.copy' | i18n}}</a>
|
(click)="copySecretToClipboard(timeslot.secret)">{{'partey.timeslots.secret.copy' | i18n}}</a>
|
||||||
<span *ngIf="timeslot.type == 'VIDEO_STREAM'"> {{ timeslot.stream }} </span>
|
}
|
||||||
|
@if (timeslot.type == 'VIDEO_STREAM') {
|
||||||
|
<span> {{ timeslot.stream }} </span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="edit">
|
<ng-container matColumnDef="edit">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'partey.timeslots.edit' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'partey.timeslots.edit' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot" class="text-right">
|
<td mat-cell *matCellDef="let timeslot" class="text-right">
|
||||||
<a *ngIf="timeslot.owner == userId" mat-icon-button (click)="openEdit(timeslot)">
|
@if (timeslot.owner == userId) {
|
||||||
|
<a mat-icon-button (click)="openEdit(timeslot)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="delete">
|
<ng-container matColumnDef="delete">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'partey.timeslots.delete' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'partey.timeslots.delete' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let timeslot" class="text-right">
|
<td mat-cell *matCellDef="let timeslot" class="text-right">
|
||||||
<a *ngIf="timeslot.owner == userId" mat-icon-button (click)="confirmDelete(timeslot)">
|
@if (timeslot.owner == userId) {
|
||||||
|
<a mat-icon-button (click)="confirmDelete(timeslot)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="timeslotsColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="timeslotsColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: timeslotsColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: timeslotsColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="timeslots.totalElements" [pageSize]="timeslots.size"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="timeslots.totalElements" [pageSize]="timeslots.size"
|
||||||
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
(page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'partey.timeslots.info' | i18n}}</p>
|
<p>{{'partey.timeslots.info' | i18n}}</p>
|
||||||
<p *ngIf="!timeslotsQuota">{{'partey.timeslots.noQuota' | i18n}}</p>
|
@if (!timeslotsQuota) {
|
||||||
<div *ngIf="timeslotsQuota">
|
<p>{{'partey.timeslots.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (timeslotsQuota) {
|
||||||
|
<div>
|
||||||
<p>{{'partey.timeslots.left' | i18n:timeslotsQuota}}</p>
|
<p>{{'partey.timeslots.left' | i18n:timeslotsQuota}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions *ngIf="timeslotsQuota" class="flex wrap">
|
@if (timeslotsQuota) {
|
||||||
<div *ngFor="let type of types">
|
<mat-card-actions class="flex wrap">
|
||||||
|
@for (type of types; track type) {
|
||||||
|
<div>
|
||||||
<a mat-raised-button (click)="openCreate(type)">
|
<a mat-raised-button (click)="openCreate(type)">
|
||||||
<mat-icon inline="true">{{'partey.timeslots.type.' + type + '.icon' | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'partey.timeslots.type.' + type + '.icon' | i18n}}</mat-icon>
|
||||||
{{'partey.timeslots.create.' + type | i18n}}
|
{{'partey.timeslots.create.' + type | i18n}}
|
||||||
@@ -130,7 +144,9 @@
|
|||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
}
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/partey/stream" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/partey/stream" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
matTooltipPosition="above" target="_blank" mat-fab color="accent">
|
matTooltipPosition="above" target="_blank" mat-fab color="accent">
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
<form [formGroup]="form" (ngSubmit)="passwordReset()" *ngIf="!success">
|
@if (!success) {
|
||||||
|
<form [formGroup]="form" (ngSubmit)="passwordReset()">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'password.reset' | i18n}}</h2>
|
<h2>{{'password.reset' | i18n}}</h2>
|
||||||
<mat-error *ngIf="tokenInvalid">
|
@if (tokenInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'password.reset.tokenInvalid' | i18n}}
|
{{'password.reset.tokenInvalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password"
|
<input matInput type="password" formControlName="password"
|
||||||
[(ngModel)]="model.password">
|
[(ngModel)]="model.password">
|
||||||
<mat-error *ngFor="let error of form.get('password').errors | keyvalue">
|
@for (error of form.get('password').errors | keyvalue; track error) {
|
||||||
|
<mat-error>
|
||||||
{{error.key}}
|
{{error.key}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
||||||
@@ -23,16 +28,21 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid">
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="form.invalid">
|
||||||
{{'password.reset' | i18n}}
|
{{'password.reset' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card *ngIf="success">
|
@if (success) {
|
||||||
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'password.reset.success.title' | i18n}}</h2>
|
<h2>{{'password.reset.success.title' | i18n}}</h2>
|
||||||
<p>{{'password.reset.success.text' | i18n}}</p>
|
<p>{{'password.reset.success.text' | i18n}}</p>
|
||||||
@@ -43,3 +53,4 @@
|
|||||||
</a>
|
</a>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
@@ -18,11 +18,15 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid">
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="form.invalid">
|
||||||
{{'password.request' | i18n}}
|
{{'password.request' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</form>
|
</form>
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
<form [formGroup]="form" (ngSubmit)="register()" *ngIf="!success">
|
@if (!success) {
|
||||||
|
<form [formGroup]="form" (ngSubmit)="register()">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{'register' | i18n}}</mat-card-title>
|
<mat-card-title>{{'register' | i18n}}</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-error *ngIf="missingToken">
|
@if (missingToken) {
|
||||||
|
<mat-error>
|
||||||
{{'register.token.missing' | i18n}}
|
{{'register.token.missing' | i18n}}
|
||||||
|
|
||||||
<a routerLink="/tokens" mat-raised-button color="warn">{{'register.token.missing.action' |
|
<a routerLink="/tokens" mat-raised-button color="warn">{{'register.token.missing.action' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
|
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="lockedToken">
|
}
|
||||||
|
@if (lockedToken) {
|
||||||
|
<mat-error>
|
||||||
{{'register.token.locked' | i18n}}
|
{{'register.token.locked' | i18n}}
|
||||||
|
|
||||||
<a routerLink="/login" [queryParams]="{ target:'/tokens' }" mat-raised-button
|
<a routerLink="/login" [queryParams]="{ target:'/tokens' }" mat-raised-button
|
||||||
color="warn">{{'register.token.locked.action' | i18n}}</a>
|
color="warn">{{'register.token.locked.action' | i18n}}</a>
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'username' | i18n}}</mat-label>
|
<mat-label>{{'username' | i18n}}</mat-label>
|
||||||
<input matInput formControlName="username"
|
<input matInput formControlName="username"
|
||||||
@@ -33,9 +35,11 @@
|
|||||||
<input matInput type="password" formControlName="password"
|
<input matInput type="password" formControlName="password"
|
||||||
[(ngModel)]="model.password" required tabindex="2">
|
[(ngModel)]="model.password" required tabindex="2">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
<div *ngFor="let error of form.get('password').errors | keyvalue">
|
@for (error of form.get('password').errors | keyvalue; track error) {
|
||||||
|
<div>
|
||||||
{{'password.error.' + error.key | i18n}}<br>
|
{{'password.error.' + error.key | i18n}}<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
@@ -46,15 +50,14 @@
|
|||||||
{{'password.not-match' | i18n}}
|
{{'password.not-match' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-slide-toggle formControlName="primaryEmail" [(ngModel)]="model.primaryEmail"
|
<mat-slide-toggle formControlName="primaryEmail" [(ngModel)]="model.primaryEmail"
|
||||||
(change)="onPrimaryChange()" tabindex="4">
|
(change)="onPrimaryChange()" tabindex="4">
|
||||||
{{'email.primary' | i18n}}
|
{{'email.primary' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
<mat-icon #primaryHint="matTooltip" (click)="primaryHint.toggle()" inline="true"
|
<mat-icon #primaryHint="matTooltip" (click)="primaryHint.toggle()" inline="true"
|
||||||
matTooltip="{{'email.primary.hint' | i18n:model.username}}">info</mat-icon>
|
matTooltip="{{'email.primary.hint' | i18n:model.username}}">info</mat-icon>
|
||||||
|
@if (model.primaryEmail) {
|
||||||
<mat-form-field *ngIf="model.primaryEmail">
|
<mat-form-field>
|
||||||
<mat-label>{{'email' | i18n}}</mat-label>
|
<mat-label>{{'email' | i18n}}</mat-label>
|
||||||
<input matInput type="email" formControlName="email"
|
<input matInput type="email" formControlName="email"
|
||||||
[(ngModel)]="model.email" required tabindex="5">
|
[(ngModel)]="model.email" required tabindex="5">
|
||||||
@@ -62,22 +65,28 @@
|
|||||||
{{'email.invalid' | i18n}}
|
{{'email.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
<mat-list *ngIf="items && items[0]">
|
@if (items && items[0]) {
|
||||||
<mat-list-item *ngFor="let item of items">
|
<mat-list>
|
||||||
|
@for (item of items; track item) {
|
||||||
|
<mat-list-item>
|
||||||
<mat-icon mat-list-icon>plus_one</mat-icon>
|
<mat-icon mat-list-icon>plus_one</mat-icon>
|
||||||
{{ item.name[currentLocale] || 'missing' }}
|
{{ item.name[currentLocale] || 'missing' }}
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
}
|
||||||
</mat-list>
|
</mat-list>
|
||||||
|
}
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid" tabindex="6">
|
@if (!working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary" [disabled]="form.invalid" tabindex="6">
|
||||||
{{'register' | i18n}}
|
{{'register' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
<mat-progress-bar *ngIf="working" mode="indeterminate"></mat-progress-bar>
|
@if (working) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#registration" class="help-button"
|
<a href="https://wiki.bstly.de/services/webstly#registration" class="help-button"
|
||||||
@@ -88,18 +97,24 @@
|
|||||||
</mat-card-footer>
|
</mat-card-footer>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
<div *ngIf="!success && permissions && permissions[0]">
|
@if (!success && permissions && permissions[0]) {
|
||||||
|
<div>
|
||||||
<h3>{{'permissions' | i18n}}</h3>
|
<h3>{{'permissions' | i18n}}</h3>
|
||||||
<app-permissions [permissions]="permissions"></app-permissions>
|
<app-permissions [permissions]="permissions"></app-permissions>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!success && quotas && quotas[0]">
|
}
|
||||||
|
@if (!success && quotas && quotas[0]) {
|
||||||
|
<div>
|
||||||
<h3>{{'quotas' | i18n}}</h3>
|
<h3>{{'quotas' | i18n}}</h3>
|
||||||
<app-quotas [quotas]="quotas"></app-quotas>
|
<app-quotas [quotas]="quotas"></app-quotas>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card *ngIf="success">
|
@if (success) {
|
||||||
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<h2>{{'register.success.title' | i18n}}</h2>
|
<h2>{{'register.success.title' | i18n}}</h2>
|
||||||
<p>{{'register.success.text' | i18n}}</p>
|
<p>{{'register.success.text' | i18n}}</p>
|
||||||
@@ -110,3 +125,4 @@
|
|||||||
</a>
|
</a>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
@@ -5,9 +5,11 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-chip-listbox #chipList [multiple]="true" [selectable]="true" cdkDropList cdkDropListOrientation="horizontal"
|
<mat-chip-listbox #chipList [multiple]="true" [selectable]="true" cdkDropList cdkDropListOrientation="horizontal"
|
||||||
(cdkDropListDropped)="drop($event)">
|
(cdkDropListDropped)="drop($event)">
|
||||||
<mat-chip *ngFor="let dict of dicts" cdkDrag [selected]="dict.selected" (click)="toggle(dict)">
|
@for (dict of dicts; track dict) {
|
||||||
|
<mat-chip cdkDrag [selected]="dict.selected" (click)="toggle(dict)">
|
||||||
{{dict.name}}
|
{{dict.name}}
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
|
}
|
||||||
</mat-chip-listbox>
|
</mat-chip-listbox>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
|||||||
@@ -12,28 +12,42 @@
|
|||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<mat-progress-bar *ngIf="!baseServices" mode="indeterminate"></mat-progress-bar>
|
@if (!baseServices) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
|
|
||||||
<p *ngIf="baseServices && baseServices.length == 0">{{'services.empty' | i18n}}</p>
|
@if (baseServices && baseServices.length == 0) {
|
||||||
|
<p>{{'services.empty' | i18n}}</p>
|
||||||
|
}
|
||||||
|
|
||||||
<div *ngIf="view=='grid'">
|
@if (view=='grid') {
|
||||||
<app-services-grid *ngIf="baseServices" [services]="baseServices"></app-services-grid>
|
<div>
|
||||||
|
@if (baseServices) {
|
||||||
|
<app-services-grid [services]="baseServices"></app-services-grid>
|
||||||
|
}
|
||||||
<br>
|
<br>
|
||||||
<div *ngFor="let item of serviceCategory | keyvalue">
|
@for (item of serviceCategory | keyvalue; track item) {
|
||||||
|
<div>
|
||||||
<h4>{{'services.category.' + item.key | i18n}}</h4>
|
<h4>{{'services.category.' + item.key | i18n}}</h4>
|
||||||
|
|
||||||
<app-services-grid [services]="item.value"></app-services-grid>
|
<app-services-grid [services]="item.value"></app-services-grid>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div *ngIf="view=='table'">
|
@if (view=='table') {
|
||||||
<app-services-table *ngIf="baseServices" [services]="baseServices"></app-services-table>
|
<div>
|
||||||
|
@if (baseServices) {
|
||||||
|
<app-services-table [services]="baseServices"></app-services-table>
|
||||||
|
}
|
||||||
<br>
|
<br>
|
||||||
<div *ngFor="let item of serviceCategory | keyvalue">
|
@for (item of serviceCategory | keyvalue; track item) {
|
||||||
|
<div>
|
||||||
<h4>{{'services.category.' + item.key | i18n}}</h4>
|
<h4>{{'services.category.' + item.key | i18n}}</h4>
|
||||||
|
|
||||||
<app-services-table [services]="item.value"></app-services-table>
|
<app-services-table [services]="item.value"></app-services-table>
|
||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -1,40 +1,48 @@
|
|||||||
<div *ngIf="items && items[0]">
|
@if (items && items[0]) {
|
||||||
|
<div>
|
||||||
<h2>{{'tokens.active' | i18n}}</h2>
|
<h2>{{'tokens.active' | i18n}}</h2>
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<mat-list-item *ngFor="let item of items">
|
@for (item of items; track item) {
|
||||||
|
<mat-list-item>
|
||||||
<mat-icon mat-list-icon>plus_one</mat-icon>
|
<mat-icon mat-list-icon>plus_one</mat-icon>
|
||||||
{{ item.name[currentLocale] || 'missing' }}
|
{{ item.name[currentLocale] || 'missing' }}
|
||||||
<a mat-icon-button (click)="removeSecret(item.secret)">
|
<a mat-icon-button (click)="removeSecret(item.secret)">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
|
}
|
||||||
</mat-list>
|
</mat-list>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a *ngIf="auth.authenticated" mat-raised-button color="accent" (click)="redeem()">
|
@if (auth.authenticated) {
|
||||||
|
<a mat-raised-button color="accent" (click)="redeem()">
|
||||||
<mat-icon>redeem</mat-icon> {{'tokens.redeem' | i18n}}
|
<mat-icon>redeem</mat-icon> {{'tokens.redeem' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<div class="flex column" *ngIf="!auth.authenticated">
|
@if (!auth.authenticated) {
|
||||||
<p *ngIf="canRegister()">{{'tokens.register' | i18n}}</p>
|
<div class="flex column">
|
||||||
|
@if (canRegister()) {
|
||||||
<a routerLink="/register" mat-raised-button color="accent" *ngIf="canRegister()">
|
<p>{{'tokens.register' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (canRegister()) {
|
||||||
|
<a routerLink="/register" mat-raised-button color="accent">
|
||||||
<mat-icon>how_to_reg</mat-icon> {{'register' | i18n}}
|
<mat-icon>how_to_reg</mat-icon> {{'register' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<p *ngIf="canRegister()">{{'tokens.login' | i18n}}</p>
|
@if (canRegister()) {
|
||||||
|
<p>{{'tokens.login' | i18n}}</p>
|
||||||
<p *ngIf="!canRegister()">{{'tokens.loginRequired' | i18n}}</p>
|
}
|
||||||
|
@if (!canRegister()) {
|
||||||
|
<p>{{'tokens.loginRequired' | i18n}}</p>
|
||||||
|
}
|
||||||
<a routerLink="/login" [queryParams]="{ target:'/tokens' }" mat-raised-button color="primary">
|
<a routerLink="/login" [queryParams]="{ target:'/tokens' }" mat-raised-button color="primary">
|
||||||
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/webstly#registration" class="help-button"
|
<a href="https://wiki.bstly.de/services/webstly#registration" class="help-button"
|
||||||
@@ -43,16 +51,20 @@
|
|||||||
</a>
|
</a>
|
||||||
</mat-card-footer>
|
</mat-card-footer>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
@if (permissions && permissions[0]) {
|
||||||
<div *ngIf="permissions && permissions[0]">
|
<div>
|
||||||
<h3>{{'permissions' | i18n}}</h3>
|
<h3>{{'permissions' | i18n}}</h3>
|
||||||
<app-permissions [permissions]="permissions" [startsVisible]="canRegister() || auth.authenticated" [expiresVisible]="canRegister() || auth.authenticated"></app-permissions>
|
<app-permissions [permissions]="permissions" [startsVisible]="canRegister() || auth.authenticated" [expiresVisible]="canRegister() || auth.authenticated"></app-permissions>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="quotas && quotas[0]">
|
}
|
||||||
|
@if (quotas && quotas[0]) {
|
||||||
|
<div>
|
||||||
<h3>{{'quotas' | i18n}}</h3>
|
<h3>{{'quotas' | i18n}}</h3>
|
||||||
<app-quotas [quotas]="quotas"></app-quotas>
|
<app-quotas [quotas]="quotas"></app-quotas>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<form [formGroup]="form" (ngSubmit)="redeemSecret()" #formDirective="ngForm">
|
<form [formGroup]="form" (ngSubmit)="redeemSecret()" #formDirective="ngForm">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
@@ -60,12 +72,16 @@
|
|||||||
<mat-card-title>{{'tokens.enter' | i18n}}</mat-card-title>
|
<mat-card-title>{{'tokens.enter' | i18n}}</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-error *ngIf="tokenInvalid">
|
@if (tokenInvalid) {
|
||||||
|
<mat-error>
|
||||||
{{'tokens.invalid' | i18n}}
|
{{'tokens.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
<mat-error *ngIf="tokenRedeemed">
|
}
|
||||||
|
@if (tokenRedeemed) {
|
||||||
|
<mat-error>
|
||||||
{{'tokens.redeemed' | i18n}}
|
{{'tokens.redeemed' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'token' | i18n}}</mat-label>
|
<mat-label>{{'token' | i18n}}</mat-label>
|
||||||
<input matInput formControlName="token" matAutofocus>
|
<input matInput formControlName="token" matAutofocus>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<h3>{{'urlshortener' | i18n}}</h3>
|
<h3>{{'urlshortener' | i18n}}</h3>
|
||||||
|
|
||||||
<div *ngIf="shortenedUrls">
|
@if (shortenedUrls) {
|
||||||
|
<div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.search' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.search' | i18n}}</mat-label>
|
||||||
@@ -8,7 +9,6 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<table mat-table matSort [dataSource]="shortenedUrls.content" (matSortChange)="updateSort($event)">
|
<table mat-table matSort [dataSource]="shortenedUrls.content" (matSortChange)="updateSort($event)">
|
||||||
|
|
||||||
<ng-container matColumnDef="share">
|
<ng-container matColumnDef="share">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.share' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.share' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl">
|
<td mat-cell *matCellDef="let shortenedUrl">
|
||||||
@@ -17,25 +17,24 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="link">
|
<ng-container matColumnDef="link">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="link"> {{'urlshortener.link' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="link"> {{'urlshortener.link' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl">
|
<td mat-cell *matCellDef="let shortenedUrl">
|
||||||
<a mat-button color="accent" href="{{ shortenedUrl.link }}" target="_blank">
|
<a mat-button color="accent" href="{{ shortenedUrl.link }}" target="_blank">
|
||||||
<mat-icon *ngIf="shortenedUrl.password">vpn_key</mat-icon> {{ shortenedUrl.link }}
|
@if (shortenedUrl.password) {
|
||||||
|
<mat-icon>vpn_key</mat-icon>
|
||||||
|
} {{ shortenedUrl.link }}
|
||||||
<mat-icon style="font-size: 1em;">open_in_new
|
<mat-icon style="font-size: 1em;">open_in_new
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="note">
|
<ng-container matColumnDef="note">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.note' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.note' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl">
|
<td mat-cell *matCellDef="let shortenedUrl">
|
||||||
{{shortenedUrl.note}}
|
{{shortenedUrl.note}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="url">
|
<ng-container matColumnDef="url">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="url"> {{'urlshortener.url' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="url"> {{'urlshortener.url' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl">
|
<td mat-cell *matCellDef="let shortenedUrl">
|
||||||
@@ -46,12 +45,10 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="expires">
|
<ng-container matColumnDef="expires">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="expires"> {{'urlshortener.expires' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="expires"> {{'urlshortener.expires' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl"> {{ shortenedUrl.expires | datef:datetimeformat}} </td>
|
<td mat-cell *matCellDef="let shortenedUrl"> {{ shortenedUrl.expires | datef:datetimeformat}} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="edit">
|
<ng-container matColumnDef="edit">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.edit' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'urlshortener.edit' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl" class="text-right">
|
<td mat-cell *matCellDef="let shortenedUrl" class="text-right">
|
||||||
@@ -60,7 +57,6 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="delete">
|
<ng-container matColumnDef="delete">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'urlshortener.delete' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'urlshortener.delete' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let shortenedUrl" class="text-right">
|
<td mat-cell *matCellDef="let shortenedUrl" class="text-right">
|
||||||
@@ -69,23 +65,24 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="shortenedUrlColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="shortenedUrlColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: shortenedUrlColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: shortenedUrlColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="shortenedUrls.totalElements"
|
<mat-paginator [pageSizeOptions]="pageSizeOptions" [length]="shortenedUrls.totalElements"
|
||||||
[pageSize]="shortenedUrls.size" (page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
[pageSize]="shortenedUrls.size" (page)="updatePages($event)" showFirstLastButtons></mat-paginator>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<form [formGroup]="form" (ngSubmit)="create()" #formDirective="ngForm">
|
<form [formGroup]="form" (ngSubmit)="create()" #formDirective="ngForm">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>{{'urlshortener.info' | i18n}}</p>
|
<p>{{'urlshortener.info' | i18n}}</p>
|
||||||
<p *ngIf="!shortenedUrlQuota">{{'urlshortener.noQuota' | i18n}}</p>
|
@if (!shortenedUrlQuota) {
|
||||||
<div *ngIf="shortenedUrlQuota">
|
<p>{{'urlshortener.noQuota' | i18n}}</p>
|
||||||
|
}
|
||||||
|
@if (shortenedUrlQuota) {
|
||||||
|
<div>
|
||||||
<p>{{'urlshortener.left' | i18n:shortenedUrlQuota}}</p>
|
<p>{{'urlshortener.left' | i18n:shortenedUrlQuota}}</p>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.url' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.url' | i18n}}</mat-label>
|
||||||
<input matInput formControlName="url" [(ngModel)]="shortenedUrl.url" type="url">
|
<input matInput formControlName="url" [(ngModel)]="shortenedUrl.url" type="url">
|
||||||
@@ -93,7 +90,6 @@
|
|||||||
{{'urlshortener.error.url' | i18n}}
|
{{'urlshortener.error.url' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.note' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.note' | i18n}}</mat-label>
|
||||||
<textarea matInput type="note" formControlName="note" [(ngModel)]="shortenedUrl.note"></textarea>
|
<textarea matInput type="note" formControlName="note" [(ngModel)]="shortenedUrl.note"></textarea>
|
||||||
@@ -101,7 +97,6 @@
|
|||||||
{{'urlshortener.error.note' | i18n}}
|
{{'urlshortener.error.note' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-expansion-panel>
|
<mat-expansion-panel>
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title>
|
<mat-panel-title>
|
||||||
@@ -112,12 +107,13 @@
|
|||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password" [(ngModel)]="shortenedUrl.password">
|
<input matInput type="password" formControlName="password" [(ngModel)]="shortenedUrl.password">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
<div *ngFor="let error of form.get('password').errors | keyvalue">
|
@for (error of form.get('password').errors | keyvalue; track error) {
|
||||||
|
<div>
|
||||||
{{'password.error.' + error.key | i18n}}<br>
|
{{'password.error.' + error.key | i18n}}<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password2" [(ngModel)]="shortenedUrl.password2">
|
<input matInput type="password" formControlName="password2" [(ngModel)]="shortenedUrl.password2">
|
||||||
@@ -125,7 +121,6 @@
|
|||||||
{{'password.not-match' | i18n}}
|
{{'password.not-match' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.expires' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.expires' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="shortenedUrl.expires" formControlName="expires">
|
<input matInput type="datetime-local" [(ngModel)]="shortenedUrl.expires" formControlName="expires">
|
||||||
@@ -133,12 +128,10 @@
|
|||||||
{{'urlshortener.error.expires' | i18n}}
|
{{'urlshortener.error.expires' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-slide-toggle [(ngModel)]="shortenedUrl.queryParameters" formControlName="queryParameters">
|
<mat-slide-toggle [(ngModel)]="shortenedUrl.queryParameters" formControlName="queryParameters">
|
||||||
{{'urlshortener.queryParameters' | i18n}}
|
{{'urlshortener.queryParameters' | i18n}}
|
||||||
<mat-icon inline="true" matTooltip="{{'urlshortener.queryParameters.info' | i18n}}">info</mat-icon>
|
<mat-icon inline="true" matTooltip="{{'urlshortener.queryParameters.info' | i18n}}">info</mat-icon>
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.code' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.code' | i18n}}</mat-label>
|
||||||
<input matInput formControlName="code" [(ngModel)]="shortenedUrl.code">
|
<input matInput formControlName="code" [(ngModel)]="shortenedUrl.code">
|
||||||
@@ -148,12 +141,15 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<button type="submit" *ngIf="shortenedUrlQuota && !working" mat-raised-button color="primary"
|
@if (shortenedUrlQuota && !working) {
|
||||||
|
<button type="submit" mat-raised-button color="primary"
|
||||||
[disabled]="form.invalid">
|
[disabled]="form.invalid">
|
||||||
{{'urlshortener.create' | i18n}}
|
{{'urlshortener.create' | i18n}}
|
||||||
</button>
|
</button>
|
||||||
|
}
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
<mat-card-footer>
|
<mat-card-footer>
|
||||||
<a href="https://wiki.bstly.de/services/urlshortener" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
<a href="https://wiki.bstly.de/services/urlshortener" class="help-button" matTooltip="{{'help-button' | i18n}}"
|
||||||
|
|||||||
@@ -30,23 +30,29 @@
|
|||||||
{{'urlshortener.newPassword' | i18n}}
|
{{'urlshortener.newPassword' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
|
||||||
<mat-form-field *ngIf="shortenedUrlModel.newPassword">
|
@if (shortenedUrlModel.newPassword) {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password" [(ngModel)]="shortenedUrlModel.password">
|
<input matInput type="password" formControlName="password" [(ngModel)]="shortenedUrlModel.password">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
<div *ngFor="let error of form.get('password').errors | keyvalue">
|
@for (error of form.get('password').errors | keyvalue; track error) {
|
||||||
|
<div>
|
||||||
{{'password.error.' + error.key | i18n}}<br>
|
{{'password.error.' + error.key | i18n}}<br>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-form-field *ngIf="shortenedUrlModel.newPassword">
|
@if (shortenedUrlModel.newPassword) {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
<mat-label>{{'password.confirm' | i18n}}</mat-label>
|
||||||
<input matInput type="password" formControlName="password2" [(ngModel)]="shortenedUrlModel.password2">
|
<input matInput type="password" formControlName="password2" [(ngModel)]="shortenedUrlModel.password2">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'password.not-match' | i18n}}
|
{{'password.not-match' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'urlshortener.expires' | i18n}}</mat-label>
|
<mat-label>{{'urlshortener.expires' | i18n}}</mat-label>
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
<mat-label>{{'password' | i18n}}</mat-label>
|
<mat-label>{{'password' | i18n}}</mat-label>
|
||||||
<input id="password" name="password" matInput type="password" required matAutofocus>
|
<input id="password" name="password" matInput type="password" required matAutofocus>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-error *ngIf="invalidPassword">
|
@if (invalidPassword) {
|
||||||
|
<mat-error>
|
||||||
{{'urlshortener.password.invalid' | i18n}}
|
{{'urlshortener.password.invalid' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
}
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<a type="submit" (click)="loginForm.submit()" mat-raised-button color="primary"
|
<a type="submit" (click)="loginForm.submit()" mat-raised-button color="primary"
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
<br>
|
<br>
|
||||||
<mat-progress-bar *ngIf="!success && !error" mode="indeterminate"></mat-progress-bar>
|
@if (!success && !error) {
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
}
|
||||||
|
|
||||||
<div *ngIf="success">
|
@if (success) {
|
||||||
|
<div>
|
||||||
<h3>{{model.username}}
|
<h3>{{model.username}}
|
||||||
<a *ngIf="isMe" mat-icon-button color="accent">
|
@if (isMe) {
|
||||||
|
<a mat-icon-button color="accent">
|
||||||
<mat-icon>star</mat-icon>
|
<mat-icon>star</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</h3>
|
</h3>
|
||||||
<app-profilefields [username]="model.username"></app-profilefields>
|
<app-profilefields [username]="model.username"></app-profilefields>
|
||||||
<div *ngIf="model.aliases && model.aliases.length > 0">
|
@if (model.aliases && model.aliases.length > 0) {
|
||||||
|
<div>
|
||||||
<h4>{{'user.aliases' | i18n}}</h4>
|
<h4>{{'user.aliases' | i18n}}</h4>
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<mat-list-item *ngFor="let alias of model.aliases">{{alias}}</mat-list-item>
|
@for (alias of model.aliases; track alias) {
|
||||||
|
<mat-list-item>{{alias}}</mat-list-item>
|
||||||
|
}
|
||||||
</mat-list>
|
</mat-list>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-card class="warn" *ngIf="error">
|
@if (error) {
|
||||||
|
<mat-card class="warn">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<mat-card-title>{{error.status}}</mat-card-title>
|
<mat-card-title>{{error.status}}</mat-card-title>
|
||||||
<mat-card-subtitle>{{'user.unavailable' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'user.unavailable' | i18n}}</mat-card-subtitle>
|
||||||
@@ -27,3 +38,4 @@
|
|||||||
</p>
|
</p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
}
|
||||||
@@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
|
|
||||||
<mat-select [(ngModel)]="unit">
|
<mat-select [(ngModel)]="unit">
|
||||||
<mat-option *ngFor="let item of dividerModel.units" [value]="item">{{item.name}}</mat-option>
|
@for (item of dividerModel.units; track item) {
|
||||||
|
<mat-option [value]="item">{{item.name}}</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
|
|
||||||
<div *ngFor="let item of dividerModel.items">
|
@for (item of dividerModel.items; track item) {
|
||||||
|
<div>
|
||||||
<label>{{item.name}}: {{toCurrentUnit(item.value)}}{{unit.name}}</label>
|
<label>{{item.name}}: {{toCurrentUnit(item.value)}}{{unit.name}}</label>
|
||||||
<mat-slider [max]="toCurrentUnit(dividerModel.free + item.value)" min=0 [step]="unit.steps" [value]="toCurrentUnit(item.value)" thumbLabel
|
<mat-slider [max]="toCurrentUnit(dividerModel.free + item.value)" min=0 [step]="unit.steps" [value]="toCurrentUnit(item.value)" thumbLabel
|
||||||
tickInterval="5" (change)="updateValue($event, item)">
|
tickInterval="5" (change)="updateValue($event, item)">
|
||||||
</mat-slider>
|
</mat-slider>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -14,21 +14,33 @@
|
|||||||
<mat-icon>arrow_drop_down</mat-icon>
|
<mat-icon>arrow_drop_down</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<mat-menu #menu="matMenu">
|
<mat-menu #menu="matMenu">
|
||||||
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-menu-item>
|
@if (!auth || auth && !auth.authenticated) {
|
||||||
|
<a routerLink="/login" routerLinkActive="active" mat-menu-item>
|
||||||
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
<mat-divider *ngIf="!auth || auth && !auth.authenticated"></mat-divider>
|
}
|
||||||
<a *ngFor="let locale of locales" mat-menu-item (click)="setLocale(locale)">{{'locale.' + locale + '.long' |
|
@if (!auth || auth && !auth.authenticated) {
|
||||||
i18n}} <mat-icon *ngIf="locale == currentLocale">done</mat-icon></a>
|
<mat-divider></mat-divider>
|
||||||
|
}
|
||||||
|
@for (locale of locales; track locale) {
|
||||||
|
<a mat-menu-item (click)="setLocale(locale)">{{'locale.' + locale + '.long' |
|
||||||
|
i18n}} @if (locale == currentLocale) {
|
||||||
|
<mat-icon>done</mat-icon>
|
||||||
|
}</a>
|
||||||
|
}
|
||||||
<a mat-menu-item>
|
<a mat-menu-item>
|
||||||
<mat-slide-toggle (change)="darkThemeChange($event)" [checked]="darkTheme == 'true'">
|
<mat-slide-toggle (change)="darkThemeChange($event)" [checked]="darkTheme == 'true'">
|
||||||
{{'profileField.name.darkTheme' | i18n}}
|
{{'profileField.name.darkTheme' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
</a>
|
</a>
|
||||||
<mat-divider *ngIf="auth && auth.authenticated"></mat-divider>
|
@if (auth && auth.authenticated) {
|
||||||
<a *ngIf="auth && auth.authenticated" (click)="logout()" mat-menu-item>
|
<mat-divider></mat-divider>
|
||||||
|
}
|
||||||
|
@if (auth && auth.authenticated) {
|
||||||
|
<a (click)="logout()" mat-menu-item>
|
||||||
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
@@ -37,15 +49,21 @@
|
|||||||
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened"
|
<mat-sidenav #sidenav [mode]="isBiggerScreen() ? 'side' : 'over'" [(opened)]="opened"
|
||||||
(click)="!isBiggerScreen() && opened=false">
|
(click)="!isBiggerScreen() && opened=false">
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
<a *ngIf="!auth || auth && !auth.authenticated" routerLink="/login" routerLinkActive="active" mat-list-item>
|
@if (!auth || auth && !auth.authenticated) {
|
||||||
|
<a routerLink="/login" routerLinkActive="active" mat-list-item>
|
||||||
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
<mat-icon>login</mat-icon> {{'login' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="auth && auth.authenticated" routerLink="/account/info" routerLinkActive="active" mat-list-item>
|
}
|
||||||
|
@if (auth && auth.authenticated) {
|
||||||
|
<a routerLink="/account/info" routerLinkActive="active" mat-list-item>
|
||||||
<mat-icon>account_circle</mat-icon> {{'account' | i18n}}
|
<mat-icon>account_circle</mat-icon> {{'account' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="auth && auth.authenticated" routerLink="/services" routerLinkActive="active" mat-list-item>
|
}
|
||||||
|
@if (auth && auth.authenticated) {
|
||||||
|
<a routerLink="/services" routerLinkActive="active" mat-list-item>
|
||||||
<mat-icon>widgets</mat-icon> {{'services' | i18n}}
|
<mat-icon>widgets</mat-icon> {{'services' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<a routerLink="/tokens" mat-list-item>
|
<a routerLink="/tokens" mat-list-item>
|
||||||
<mat-icon>card_giftcard</mat-icon> {{'tokens.redeem' | i18n}}
|
<mat-icon>card_giftcard</mat-icon> {{'tokens.redeem' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
@@ -57,9 +75,11 @@
|
|||||||
<mat-icon>shopping_cart</mat-icon> {{'tokens.get' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
<mat-icon>shopping_cart</mat-icon> {{'tokens.get' | i18n}}<mat-icon style="font-size: 1em;">open_in_new
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="auth && auth.authenticated" (click)="logout()" mat-list-item>
|
@if (auth && auth.authenticated) {
|
||||||
|
<a (click)="logout()" mat-list-item>
|
||||||
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
<mat-icon>exit_to_app</mat-icon> {{'logout' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
<td mat-cell *matCellDef="let permission">
|
<td mat-cell *matCellDef="let permission">
|
||||||
<mat-icon inline="true">{{'services.' + permission.name + '.icon' | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'services.' + permission.name + '.icon' | i18n}}</mat-icon>
|
||||||
{{'services.' + permission.name + '.title' | i18n}}
|
{{'services.' + permission.name + '.title' | i18n}}
|
||||||
<mat-icon inline="true" *ngIf="permission.addon">add_circle</mat-icon>
|
@if (permission.addon) {
|
||||||
|
<mat-icon inline="true">add_circle</mat-icon>
|
||||||
|
}
|
||||||
<br>
|
<br>
|
||||||
<small>{{'services.' + permission.name + '.subtitle' | i18n}}</small>
|
<small>{{'services.' + permission.name + '.subtitle' | i18n}}</small>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -12,24 +12,30 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.type' | i18n}}</mat-label>
|
<mat-label>{{'profileField.type' | i18n}}</mat-label>
|
||||||
<mat-select [(ngModel)]="profileField.type" formControlName="type">
|
<mat-select [(ngModel)]="profileField.type" formControlName="type">
|
||||||
<mat-option *ngFor="let type of types" [value]="type">
|
@for (type of types; track type) {
|
||||||
|
<mat-option [value]="type">
|
||||||
{{'profileField.type.' + type | i18n}}
|
{{'profileField.type.' + type | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.type' | i18n}}
|
{{'profileField.error.type' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div [ngSwitch]="profileField.type">
|
<div>
|
||||||
<mat-form-field *ngSwitchCase="'TEXT'">
|
@switch (profileField.type) {
|
||||||
|
@case ('TEXT') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput type="text" max="255" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput type="text" max="255" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.TEXT' | i18n}}
|
{{'profileField.error.TEXT' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngSwitchCase="'DATE'">
|
}
|
||||||
|
@case ('DATE') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput [matDatepicker]="datePicker" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput [matDatepicker]="datePicker" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-datepicker-toggle matSuffix [for]="datePicker"></mat-datepicker-toggle>
|
<mat-datepicker-toggle matSuffix [for]="datePicker"></mat-datepicker-toggle>
|
||||||
@@ -38,39 +44,51 @@
|
|||||||
{{'profileField.error.DATE' | i18n}}
|
{{'profileField.error.DATE' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngSwitchCase="'DATETIME'">
|
}
|
||||||
|
@case ('DATETIME') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput type="datetime-local" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput type="datetime-local" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.DATETIME' | i18n}}
|
{{'profileField.error.DATETIME' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngSwitchCase="'URL'">
|
}
|
||||||
|
@case ('URL') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput type="url" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput type="url" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.URL' | i18n}}
|
{{'profileField.error.URL' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-form-field *ngSwitchCase="'EMAIL'">
|
}
|
||||||
|
@case ('EMAIL') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput type="email" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput type="email" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.EMAIL' | i18n}}
|
{{'profileField.error.EMAIL' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-slide-toggle *ngSwitchCase="'BOOL'" (change)="booleanChange(profileField)"
|
}
|
||||||
|
@case ('BOOL') {
|
||||||
|
<mat-slide-toggle (change)="booleanChange(profileField)"
|
||||||
[checked]="profileField.value == 'true'">
|
[checked]="profileField.value == 'true'">
|
||||||
{{'profileField.value' | i18n}}
|
{{'profileField.value' | i18n}}
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
<mat-form-field *ngSwitchCase="'NUMBER'">
|
}
|
||||||
|
@case ('NUMBER') {
|
||||||
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<input matInput type="number" [(ngModel)]="profileField.value" formControlName="value">
|
<input matInput type="number" [(ngModel)]="profileField.value" formControlName="value">
|
||||||
<mat-error>
|
<mat-error>
|
||||||
{{'profileField.error.NUMBER' | i18n}}
|
{{'profileField.error.NUMBER' | i18n}}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div *ngSwitchCase="'BLOB'">
|
}
|
||||||
|
@case ('BLOB') {
|
||||||
|
<div>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
<mat-label>{{'profileField.value' | i18n}}</mat-label>
|
||||||
<textarea matInput [(ngModel)]="profileField.blob" formControlName="blob"></textarea>
|
<textarea matInput [(ngModel)]="profileField.blob" formControlName="blob"></textarea>
|
||||||
@@ -80,16 +98,20 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<a mat-button (click)="pgpBlob(profileField)">{{'profileField.blob.pgp' | i18n}}</a>
|
<a mat-button (click)="pgpBlob(profileField)">{{'profileField.blob.pgp' | i18n}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{'visibility' | i18n}}</mat-label>
|
<mat-label>{{'visibility' | i18n}}</mat-label>
|
||||||
<mat-select [(ngModel)]="profileField.visibility" formControlName="visibility">
|
<mat-select [(ngModel)]="profileField.visibility" formControlName="visibility">
|
||||||
<mat-option *ngFor="let visibility of visibilities" [value]="visibility">
|
@for (visibility of visibilities; track visibility) {
|
||||||
|
<mat-option [value]="visibility">
|
||||||
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
<mat-icon inline="true">{{'visibility.' + visibility + '.icon' | i18n}}</mat-icon> {{'visibility.' +
|
||||||
visibility | i18n}}
|
visibility | i18n}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
}
|
||||||
|
|
||||||
<mat-select-trigger>
|
<mat-select-trigger>
|
||||||
<mat-icon inline="true">{{'visibility.' + profileField.visibility + '.icon' | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'visibility.' + profileField.visibility + '.icon' | i18n}}</mat-icon>
|
||||||
|
|||||||
@@ -8,30 +8,53 @@
|
|||||||
<ng-container matColumnDef="value">
|
<ng-container matColumnDef="value">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="value"> {{'profileField.value' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="value"> {{'profileField.value' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let profileField">
|
<td mat-cell *matCellDef="let profileField">
|
||||||
<div [ngSwitch]="profileField.type">
|
<div>
|
||||||
<span *ngSwitchCase="'TEXT'">{{profileField.value}}</span>
|
@switch (profileField.type) {
|
||||||
<span *ngSwitchCase="'DATE'">{{profileField.value | datef:dateformat}}</span>
|
@case ('TEXT') {
|
||||||
<span *ngSwitchCase="'DATETIME'">{{profileField.value | datef:datetimeformat}}</span>
|
<span>{{profileField.value}}</span>
|
||||||
<span *ngSwitchCase="'TIME'">{{profileField.value | datef:timeformat}}</span>
|
}
|
||||||
<a *ngSwitchCase="'URL'" class="accent" href="{{profileField.value}}">{{profileField.value}}</a>
|
@case ('DATE') {
|
||||||
<a *ngSwitchCase="'EMAIL'" class="accent" href="mailto:{{profileField.value}}">{{profileField.value}}</a>
|
<span>{{profileField.value | datef:dateformat}}</span>
|
||||||
<span *ngSwitchCase="'NUMBER'">{{profileField.value}}</span>
|
}
|
||||||
<a *ngSwitchCase="'BLOB'" mat-raised-button (click)="openBlob(profileField)">{{'profileField.openBlob' | i18n}}</a>
|
@case ('DATETIME') {
|
||||||
<mat-slide-toggle *ngSwitchCase="'BOOL'" [checked]="profileField.value == 'true'" disabled>
|
<span>{{profileField.value | datef:datetimeformat}}</span>
|
||||||
|
}
|
||||||
|
@case ('TIME') {
|
||||||
|
<span>{{profileField.value | datef:timeformat}}</span>
|
||||||
|
}
|
||||||
|
@case ('URL') {
|
||||||
|
<a class="accent" href="{{profileField.value}}">{{profileField.value}}</a>
|
||||||
|
}
|
||||||
|
@case ('EMAIL') {
|
||||||
|
<a class="accent" href="mailto:{{profileField.value}}">{{profileField.value}}</a>
|
||||||
|
}
|
||||||
|
@case ('NUMBER') {
|
||||||
|
<span>{{profileField.value}}</span>
|
||||||
|
}
|
||||||
|
@case ('BLOB') {
|
||||||
|
<a mat-raised-button (click)="openBlob(profileField)">{{'profileField.openBlob' | i18n}}</a>
|
||||||
|
}
|
||||||
|
@case ('BOOL') {
|
||||||
|
<mat-slide-toggle [checked]="profileField.value == 'true'" disabled>
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="visibility" *ngIf="edit">
|
@if (edit) {
|
||||||
|
<ng-container matColumnDef="visibility">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="visibility"> {{'visibility' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="visibility"> {{'visibility' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let profileField">
|
<td mat-cell *matCellDef="let profileField">
|
||||||
<mat-icon inline="true">{{'visibility.' + profileField.visibility + '.icon' | i18n}}</mat-icon>
|
<mat-icon inline="true">{{'visibility.' + profileField.visibility + '.icon' | i18n}}</mat-icon>
|
||||||
{{'visibility.' + profileField.visibility | i18n}}
|
{{'visibility.' + profileField.visibility | i18n}}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
<ng-container matColumnDef="edit" *ngIf="edit">
|
@if (edit) {
|
||||||
|
<ng-container matColumnDef="edit">
|
||||||
<th mat-header-cell *matHeaderCellDef class="text-right"> {{'profileField.edit' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="text-right"> {{'profileField.edit' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let profileField" class="text-right">
|
<td mat-cell *matCellDef="let profileField" class="text-right">
|
||||||
<a mat-icon-button (click)="openEdit(profileField)">
|
<a mat-icon-button (click)="openEdit(profileField)">
|
||||||
@@ -39,8 +62,10 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
<ng-container matColumnDef="delete" *ngIf="edit">
|
@if (edit) {
|
||||||
|
<ng-container matColumnDef="delete">
|
||||||
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'profileField.delete' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'profileField.delete' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let profileField" class="text-right">
|
<td mat-cell *matCellDef="let profileField" class="text-right">
|
||||||
<a mat-icon-button (click)="confirmDelete(profileField)">
|
<a mat-icon-button (click)="confirmDelete(profileField)">
|
||||||
@@ -48,12 +73,15 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
}
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="profileFieldColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="profileFieldColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: profileFieldColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: profileFieldColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
<br>
|
<br>
|
||||||
<div *ngIf="edit" class="text-center">
|
@if (edit) {
|
||||||
|
<div class="text-center">
|
||||||
<a mat-raised-button color="primary" (click)="openCreate()">{{'profileField.create' |
|
<a mat-raised-button color="primary" (click)="openCreate()">{{'profileField.create' |
|
||||||
i18n}}</a>
|
i18n}}</a>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
@@ -10,21 +10,29 @@
|
|||||||
|
|
||||||
<ng-container matColumnDef="value">
|
<ng-container matColumnDef="value">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="value"> {{'quotas.value' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="value"> {{'quotas.value' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let quota"><span *ngIf="quota.disposable">{{quota.value}}</span> </td>
|
<td mat-cell *matCellDef="let quota">@if (quota.disposable) {
|
||||||
|
<span>{{quota.value}}</span>
|
||||||
|
} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="fixed_value">
|
<ng-container matColumnDef="fixed_value">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'quotas.fixed_value' | i18n}} <mat-icon #primaryHint="matTooltip" inline
|
<th mat-header-cell *matHeaderCellDef> {{'quotas.fixed_value' | i18n}} <mat-icon #primaryHint="matTooltip" inline
|
||||||
matTooltip="{{'quotas.fixed_value.hint' | i18n}}">info</mat-icon>
|
matTooltip="{{'quotas.fixed_value.hint' | i18n}}">info</mat-icon>
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let quota"><span *ngIf="!quota.disposable">{{quota.value}}</span> </td>
|
<td mat-cell *matCellDef="let quota">@if (!quota.disposable) {
|
||||||
|
<span>{{quota.value}}</span>
|
||||||
|
} </td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="quotaUnit">
|
<ng-container matColumnDef="quotaUnit">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'quotas.unit' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'quotas.unit' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let quota">
|
<td mat-cell *matCellDef="let quota">
|
||||||
<span *ngIf="quota.unit">{{'quotas.unit.' + quota.unit | i18n}}</span>
|
@if (quota.unit) {
|
||||||
<span *ngIf="!quota.unit">#</span>
|
<span>{{'quotas.unit.' + quota.unit | i18n}}</span>
|
||||||
|
}
|
||||||
|
@if (!quota.unit) {
|
||||||
|
<span>#</span>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
<div class="service-grid" fxLayoutGap="24px grid">
|
<div class="service-grid" fxLayoutGap="24px grid">
|
||||||
<div *ngFor="let service of services">
|
@for (service of services; track service) {
|
||||||
|
<div>
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<a *ngIf="service.url" href="{{service.url}}" [target]="service.sameSite ? '_self' : '_blank'"
|
@if (service.url) {
|
||||||
|
<a href="{{service.url}}" [target]="service.sameSite ? '_self' : '_blank'"
|
||||||
color="accent">
|
color="accent">
|
||||||
<mat-card-header>
|
<mat-card-header>
|
||||||
<div class="icon" mat-card-avatar>
|
<div class="icon" mat-card-avatar>
|
||||||
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
<mat-card-title> <strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
<mat-card-title> <strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
||||||
<mat-icon *ngIf="!service.sameSite" inline="true">
|
@if (!service.sameSite) {
|
||||||
|
<mat-icon inline="true">
|
||||||
open_in_new</mat-icon>
|
open_in_new</mat-icon>
|
||||||
|
}
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
<mat-card-subtitle>{{'services.' + service.name + '.subtitle' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'services.' + service.name + '.subtitle' | i18n}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<mat-card-header *ngIf="!service.url">
|
@if (!service.url) {
|
||||||
|
<mat-card-header>
|
||||||
<div class="icon" mat-card-avatar>
|
<div class="icon" mat-card-avatar>
|
||||||
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,6 +28,7 @@
|
|||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
<mat-card-subtitle>{{'services.' + service.name + '.subtitle' | i18n}}</mat-card-subtitle>
|
<mat-card-subtitle>{{'services.' + service.name + '.subtitle' | i18n}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
|
}
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<p>
|
<p>
|
||||||
{{ 'services.' + service.name + '.text' | i18n}}
|
{{ 'services.' + service.name + '.text' | i18n}}
|
||||||
@@ -32,4 +38,5 @@
|
|||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '../../../variables.scss';
|
@use '../../../variables.scss' as vars;
|
||||||
|
|
||||||
.service-grid {
|
.service-grid {
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
|
|
||||||
mat-card-title {
|
mat-card-title {
|
||||||
color: $accent;
|
color: vars.$accent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,38 @@
|
|||||||
<table *ngIf="services && services.length > 0" mat-table matSort [dataSource]="services"
|
@if (services && services.length > 0) {
|
||||||
|
<table mat-table matSort [dataSource]="services"
|
||||||
(matSortChange)="sortData($event)" matSortActive="name" matSortDirection="asc">
|
(matSortChange)="sortData($event)" matSortActive="name" matSortDirection="asc">
|
||||||
|
|
||||||
<ng-container matColumnDef="icon">
|
<ng-container matColumnDef="icon">
|
||||||
<th mat-header-cell *matHeaderCellDef> </th>
|
<th mat-header-cell *matHeaderCellDef> </th>
|
||||||
<td mat-cell *matCellDef="let service">
|
<td mat-cell *matCellDef="let service">
|
||||||
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
<mat-icon>{{'services.' + service.name + '.icon' | i18n}}</mat-icon>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'service.name' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header="name"> {{'service.name' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let service" class="text-center">
|
<td mat-cell *matCellDef="let service" class="text-center">
|
||||||
<a *ngIf="service.url" href="{{service.url}}" [target]="service.sameSite ? '_self' : '_blank'" mat-button
|
@if (service.url) {
|
||||||
|
<a href="{{service.url}}" [target]="service.sameSite ? '_self' : '_blank'" mat-button
|
||||||
color="accent">
|
color="accent">
|
||||||
<strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
<strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
||||||
<mat-icon *ngIf="!service.sameSite" inline="true">
|
@if (!service.sameSite) {
|
||||||
|
<mat-icon inline="true">
|
||||||
open_in_new</mat-icon>
|
open_in_new</mat-icon>
|
||||||
|
}
|
||||||
</a>
|
</a>
|
||||||
<a *ngIf="!service.url" mat-button disabled>
|
}
|
||||||
|
@if (!service.url) {
|
||||||
|
<a mat-button disabled>
|
||||||
<strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
<strong>{{'services.' + service.name + '.title' | i18n}}</strong>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
<div><small>{{'services.' + service.name + '.subtitle' | i18n}}</small></div>
|
<div><small>{{'services.' + service.name + '.subtitle' | i18n}}</small></div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="text">
|
<ng-container matColumnDef="text">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'service.text' | i18n}} </th>
|
<th mat-header-cell *matHeaderCellDef> {{'service.text' | i18n}} </th>
|
||||||
<td mat-cell *matCellDef="let service">{{ 'services.' + service.name + '.text' | i18n}}</td>
|
<td mat-cell *matCellDef="let service">{{ 'services.' + service.name + '.text' | i18n}}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="serviceColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="serviceColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: serviceColumns"></tr>
|
<tr mat-row *matRowDef="let myRowData; columns: serviceColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
|
}
|
||||||
+7
-8
@@ -2,21 +2,20 @@
|
|||||||
@use '@angular/material' as mat;
|
@use '@angular/material' as mat;
|
||||||
// For more information: https://material.angular.io/guide/theming
|
// For more information: https://material.angular.io/guide/theming
|
||||||
// Plus imports for other components in your app.
|
// Plus imports for other components in your app.
|
||||||
|
@use './variables.scss' as vars;
|
||||||
|
|
||||||
// Include the common styles for Angular Material. We include this here so that you only
|
// Include the common styles for Angular Material. We include this here so that you only
|
||||||
// have to load a single css file for Angular Material in your app.
|
// have to load a single css file for Angular Material in your app.
|
||||||
// Be sure that you only ever include this mixin once!
|
// Be sure that you only ever include this mixin once!
|
||||||
@include mat.core();
|
@include mat.core();
|
||||||
|
|
||||||
@import './variables.scss';
|
|
||||||
|
|
||||||
// Include theme styles for core and each component used in your app.
|
// Include theme styles for core and each component used in your app.
|
||||||
// Alternatively, you can import and @include the theme mixins for each component
|
// Alternatively, you can import and @include the theme mixins for each component
|
||||||
// that you are using.
|
// that you are using.
|
||||||
@include mat.all-component-themes($light-theme);
|
@include mat.all-component-themes(vars.$light-theme);
|
||||||
|
|
||||||
.dark-theme {
|
.dark-theme {
|
||||||
@include mat.all-component-colors($dark-theme);
|
@include mat.all-component-colors(vars.$dark-theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
@@ -31,7 +30,7 @@
|
|||||||
|
|
||||||
|
|
||||||
a.accent {
|
a.accent {
|
||||||
color: $accent;
|
color: vars.$accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
@@ -232,7 +231,7 @@ mat-sidenav-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text-warning {
|
.text-warning {
|
||||||
color: $warn;
|
color: vars.$warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
.align-right {
|
.align-right {
|
||||||
@@ -268,11 +267,11 @@ mat-card.accent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mat-card.warn mat-card-header {
|
mat-card.warn mat-card-header {
|
||||||
background-color: $warn !important;
|
background-color: vars.$warn !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-card.accent mat-card-header {
|
mat-card.accent mat-card-header {
|
||||||
background-color: $accent !important;
|
background-color: vars.$accent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-mdc-list-item-unscoped-content {
|
.mat-mdc-list-item-unscoped-content {
|
||||||
|
|||||||
Reference in New Issue
Block a user