mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-01 15:03:32 +00:00
* features, page, table, create dialog, i18n * trigger actions service, add action dialog * display flows, add flow dialog, duration pipe, i18n * optim flow layout, action presets * delete actions, flows, layout * drag drop list, fix update * lint * stylelint * fix template rest * actions, drag, fix hasrole * stylelint * toast, i18n * missing italian translations * it * fix ActionSearchQueries Co-authored-by: Livio Amstutz <livio.a@gmail.com>
291 lines
13 KiB
HTML
291 lines
13 KiB
HTML
<cnsl-detail-layout [backRouterLink]="[ serviceType === FeatureServiceType.ADMIN ? '/iam/policies' : '/org']"
|
|
[title]="('FEATURES.TITLE' | translate)" [description]="'FEATURES.DESCRIPTION' | translate">
|
|
|
|
<h2>{{'FEATURES.TIER.TITLE' | translate}}</h2>
|
|
<p *ngIf="serviceType === FeatureServiceType.MGMT" class="tier-desc">{{'FEATURES.TIER.DESCRIPTION' | translate}}
|
|
{{'FEATURES.TIER.QUESTIONS' | translate}} <a href="mailto:support@zitadel.ch">support@zitadel.ch</a>.</p>
|
|
|
|
<div class="detail">
|
|
<p class="title">{{'FEATURES.TIER.NAME' | translate}}</p>
|
|
<p class="center">{{features?.tier?.name}}
|
|
<a class="ext" href="https://zitadel.ch/pricing" target="_blank">
|
|
<i class="las la-external-link-alt"></i>
|
|
</a>
|
|
</p>
|
|
</div>
|
|
|
|
<ng-container *ngIf="serviceType === FeatureServiceType.MGMT">
|
|
<mat-spinner class="spinner" diameter="20" *ngIf="customerLoading || stripeLoading"></mat-spinner>
|
|
<div class="detail" *ngIf="stripeCustomer || stripeCustomer === null">
|
|
<p class="title">{{'FEATURES.TIER.DETAILS' | translate}}
|
|
<a (click)="setCustomer()">{{'ACTIONS.EDIT' | translate}}</a>
|
|
</p>
|
|
<p>{{stripeCustomer?.contact}}</p>
|
|
<p *ngIf="stripeCustomer?.company">{{stripeCustomer?.company}}</p>
|
|
<p>{{stripeCustomer?.address}}</p>
|
|
<p *ngIf="stripeCustomer?.postal_code || stripeCustomer?.city || stripeCustomer?.country">
|
|
{{stripeCustomer?.postal_code}} {{stripeCustomer?.city}} {{stripeCustomer?.country}}
|
|
<img *ngIf="customerCountry" height="20px" width="30px"
|
|
style="margin-right: 1rem; border-radius: 2px; vertical-align: middle;"
|
|
src="../../../assets/flags/{{customerCountry.isoCode.toLowerCase()}}.png" />
|
|
</p>
|
|
</div>
|
|
|
|
<p class="error" *ngIf="(stripeCustomer || stripeCustomer === null) && !customerValid">
|
|
{{'FEATURES.TIER.CUSTOMERINVALID' | translate}}</p>
|
|
|
|
<div class="current-tier">
|
|
<a color="primary" [disabled]="!org.id || !customerValid || !stripeURL" mat-raised-button [href]="stripeURL"
|
|
target="_blank" alt="change tier">{{'FEATURES.TIER.BTN' | translate}}</a>
|
|
</div>
|
|
</ng-container>
|
|
|
|
<ng-template cnslHasRole [hasRole]="['iam.features.delete']">
|
|
<button *ngIf="serviceType === FeatureServiceType.MGMT && !isDefault" matTooltip="{{'POLICY.RESET' | translate}}"
|
|
color="warn" (click)="resetFeatures()" mat-stroked-button>
|
|
{{'POLICY.RESET' | translate}}
|
|
</button>
|
|
</ng-template>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
|
|
<div class="content" *ngIf="features">
|
|
<div class="row">
|
|
<span class="left-desc">{{'FEATURES.DATA.AUDITLOGRETENTION' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<span>{{features.auditLogRetention | timestampToRetention }} {{'FEATURES.RETENTIONDAYS' |
|
|
translate}}</span>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.LOGINPOLICY' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYUSERNAMELOGIN' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyUsernameLogin}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyUsernameLogin" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYPASSWORDRESET' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyPasswordReset}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyPasswordReset" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYREGISTRATION' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyRegistration}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyRegistration" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYIDP' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyIdp}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyIdp" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYFACTORS' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyFactors}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyFactors" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar green">
|
|
<i class="icon las la-sign-in-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYPASSWORDLESS' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.loginPolicyPasswordless}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.loginPolicyPasswordless" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.PASSWORD' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar yellow">
|
|
<mat-icon class="icon smaller" svgIcon="mdi_textbox_password"></mat-icon>
|
|
</div>
|
|
|
|
<span class="left-desc">{{'FEATURES.DATA.LOGINPOLICYCOMPLEXITYPOLICY' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.passwordComplexityPolicy}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.passwordComplexityPolicy" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar yellow">
|
|
<mat-icon class="icon smaller" svgIcon="mdi_textbox_password"></mat-icon>
|
|
</div>
|
|
|
|
<span class="left-desc">{{'FEATURES.DATA.LOCKOUTPOLICY' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.lockoutPolicy}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.lockoutPolicy" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.LABELPOLICY' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar blue">
|
|
<i class="icon las la-swatchbook"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LABELPOLICYPRIVATELABEL' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.labelPolicyPrivateLabel}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.labelPolicyPrivateLabel" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar blue">
|
|
<i class="icon las la-swatchbook"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.LABELPOLICYWATERMARK' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.labelPolicyWatermark}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.labelPolicyWatermark" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.DOMAIN' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar purple">
|
|
<i class="icon las la-gem"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.CUSTOMDOMAIN' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{active: features.customDomain}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.customDomain" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.TEXTSANDLINKS' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar red">
|
|
<i class="icon las la-paragraph"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.CUSTOMTEXTMESSAGE' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.customTextMessage}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.customTextMessage" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar red">
|
|
<i class="icon las la-paragraph"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.CUSTOMTEXTLOGIN' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.customTextLogin}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.customTextLogin" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar black">
|
|
<i class="icon las la-file-contract"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.PRIVACYPOLICY' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef"
|
|
[ngTemplateOutletContext]="{active: features.privacyPolicy}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.privacyPolicy" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<p class="feature-section">{{'FEATURES.HEADERS.METADATA' | translate}}</p>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar blue">
|
|
<i class="icon las la-tags"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.METADATAUSER' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{active: features.metadataUser}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl
|
|
[(ngModel)]="features.metadataUser" *ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="featureavatar pink">
|
|
<i class="icon las la-exchange-alt"></i>
|
|
</div>
|
|
<span class="left-desc">{{'FEATURES.DATA.FLOWS' | translate}}</span>
|
|
<span class="fill-space"></span>
|
|
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{active: features.actions}"></template>
|
|
<mat-slide-toggle class="toggle" color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="features.actions"
|
|
*ngIf="(['iam.features.write'] | hasRole | async)">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="btn-container" *ngIf="(['iam.features.write'] | hasRole | async) === true">
|
|
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
|
|
}}</button>
|
|
</div>
|
|
</cnsl-detail-layout>
|
|
|
|
<ng-template #templateRef let-active="active">
|
|
<span class="state" [ngClass]="{'active': active, 'inactive': !active}">
|
|
{{active ? ('FEATURES.AVAILABLE' | translate) : ('FEATURES.UNAVAILABLE' | translate)}}
|
|
</span>
|
|
</ng-template> |