Skip to content

Commit

Permalink
feat(cnsl): docs link can be customized and custom button is available (
Browse files Browse the repository at this point in the history
#7840)

* feat: customize doc link and additional custom link

* feat: add e2e tests

* fix: update docs

* fix: add @peintnermax changes about cache

* fix: golangci-lint complains preparation.PrepareCommands

---------

Co-authored-by: Max Peintner <max@caos.ch>
  • Loading branch information
doncicuto and peintnermax committed May 13, 2024
1 parent 6942324 commit 15d5338
Show file tree
Hide file tree
Showing 61 changed files with 1,000 additions and 286 deletions.
15 changes: 9 additions & 6 deletions cmd/defaults.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ Tracing:
# for type 'otel' is used for standard [open telemetry](https://opentelemetry.io)
# Fraction: 1.0
# Endpoint: 'otel.collector.endpoint'
#
#
# type 'log' or '' disables tracing
#
#
# for type 'google'
# ProjectID: ''
# Fraction: 1.0
Type: none # ZITADEL_TRACING_TYPE
Fraction: 1.0 # ZITADEL_TRACING_FRACTION
# The endpoint of the otel collector endpoint
Endpoint: '' #ZITADEL_TRACING_ENDPOINT
Endpoint: "" #ZITADEL_TRACING_ENDPOINT

Telemetry:
# As long as Enabled is true, ZITADEL tries to send usage data to the configured Telemetry.Endpoints.
Expand Down Expand Up @@ -200,7 +200,7 @@ AssetStorage:

# The Projections section defines the behavior for the scheduled and synchronous events projections.
Projections:
# The maximum duration a transaction remains open
# The maximum duration a transaction remains open
# before it spots left folding additional events
# and updates the table.
TransactionDuration: 500ms # ZITADEL_PROJECTIONS_TRANSACTIONDURATION
Expand Down Expand Up @@ -264,7 +264,7 @@ Auth:
# See Projections.BulkLimit
SearchLimit: 1000 # ZITADEL_AUTH_SEARCHLIMIT
Spooler:
# See Projections.TransationDuration
# See Projections.TransationDuration
TransactionDuration: 10s #ZITADEL_AUTH_SPOOLER_TRANSACTIONDURATION
# See Projections.BulkLimit
BulkLimit: 100 #ZITADEL_AUTH_SPOOLER_BULKLIMIT
Expand Down Expand Up @@ -704,6 +704,9 @@ DefaultInstance:
PrivacyLink: https://zitadel.com/docs/legal/privacy-policy # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_PRIVACYLINK
HelpLink: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_HELPLINK
SupportEmail: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_SUPPORTEMAIL
DocsLink: https://zitadel.com/docs # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_DOCSLINK
CustomLink: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_CUSTOMLINK
CustomLinkText: "" # ZITADEL_DEFAULTINSTANCE_PRIVACYPOLICY_CUSTOMLINKTEXT
NotificationPolicy:
PasswordChange: true # ZITADEL_DEFAULTINSTANCE_NOTIFICATIONPOLICY_PASSWORDCHANGE
LabelPolicy:
Expand Down Expand Up @@ -1432,4 +1435,4 @@ InitProjections:
Enabled: true # ZITADEL_INITPROJECTIONS_ENABLED
RetryFailedAfter: 100ms # ZITADEL_INITPROJECTIONS_RETRYFAILEDAFTER
MaxFailureCount: 2 # ZITADEL_INITPROJECTIONS_MAXFAILURECOUNT
BulkLimit: 1000 # ZITADEL_INITPROJECTIONS_BULKLIMIT
BulkLimit: 1000 # ZITADEL_INITPROJECTIONS_BULKLIMIT
6 changes: 3 additions & 3 deletions console/src/app/modules/footer/footer.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div class="footer-wrapper">
<div class="footer-row">
<div class="footer-links">
<a target="_blank" *ngIf="policy?.tosLink" rel="noreferrer" [href]="policy?.tosLink" external>
<div class="footer-links" *ngIf="authService.privacypolicy | async as pP">
<a target="_blank" *ngIf="pP?.tosLink" rel="noreferrer" [href]="pP?.tosLink" external>
<span>{{ 'FOOTER.LINKS.TOS' | translate }}</span>
<i class="las la-external-link-alt"></i>
</a>
<a target="_blank" *ngIf="policy?.privacyLink" rel="noreferrer" [href]="policy?.privacyLink" external>
<a target="_blank" *ngIf="pP?.privacyLink" rel="noreferrer" [href]="pP?.privacyLink" external>
<span>{{ 'FOOTER.LINKS.PP' | translate }}</span>
<i class="las la-external-link-alt"></i>
</a>
Expand Down
11 changes: 1 addition & 10 deletions console/src/app/modules/footer/footer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,7 @@ import { faXTwitter } from '@fortawesome/free-brands-svg-icons';
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss'],
})
export class FooterComponent implements OnInit {
public policy?: PrivacyPolicy.AsObject;
export class FooterComponent {
public faXTwitter = faXTwitter;
constructor(public authService: GrpcAuthService) {}

ngOnInit(): void {
this.authService.getMyPrivacyPolicy().then((policyResp) => {
if (policyResp.policy) {
this.policy = policyResp.policy;
}
});
}
}
6 changes: 5 additions & 1 deletion console/src/app/modules/header/header.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,11 @@

<span class="fill-space"></span>

<a class="doc-link" href="https://zitadel.com/docs" mat-stroked-button target="_blank">
<a class="custom-link" *ngIf="customLink && customLinkText" href="{{ customLink }}" mat-stroked-button target="_blank">
{{ customLinkText }}
</a>

<a class="doc-link" *ngIf="docsLink" href="{{ docsLink }}" mat-stroked-button target="_blank">
{{ 'MENU.DOCUMENTATION' | translate }}
</a>

Expand Down
3 changes: 2 additions & 1 deletion console/src/app/modules/header/header.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@
flex: 1;
}

.doc-link {
.doc-link,
.custom-link {
margin-right: 1rem;

@media only screen and (max-width: 800px) {
Expand Down
27 changes: 24 additions & 3 deletions console/src/app/modules/header/header.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConnectedPosition, ConnectionPositionPair } from '@angular/cdk/overlay';
import { Component, ElementRef, EventEmitter, Input, OnDestroy, Output, ViewChild } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
import { Org } from 'src/app/proto/generated/zitadel/org_pb';
Expand All @@ -8,8 +8,8 @@ import { AuthenticationService } from 'src/app/services/authentication.service';
import { BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service';

import { ActionKeysType } from '../action-keys/action-keys.component';
import { GetPrivacyPolicyResponse } from 'src/app/proto/generated/zitadel/management_pb';

@Component({
selector: 'cnsl-header',
Expand All @@ -31,6 +31,9 @@ export class HeaderComponent implements OnDestroy {
private destroy$: Subject<void> = new Subject();
public BreadcrumbType: any = BreadcrumbType;
public ActionKeysType: any = ActionKeysType;
public docsLink = 'https://zitadel.com/docs';
public customLink = '';
public customLinkText = '';

public positions: ConnectedPosition[] = [
new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }, 0, 10),
Expand All @@ -47,7 +50,25 @@ export class HeaderComponent implements OnDestroy {
public mgmtService: ManagementService,
public breadcrumbService: BreadcrumbService,
public router: Router,
) {}
) {
this.loadData();
}

public async loadData(): Promise<any> {
const getData = (): Promise<GetPrivacyPolicyResponse.AsObject> => {
return this.mgmtService.getPrivacyPolicy();
};

getData()
.then((resp) => {
if (resp.policy) {
this.docsLink = resp.policy.docsLink;
this.customLink = resp.policy.customLink;
this.customLinkText = resp.policy.customLinkText;
}
})
.catch(() => {});
}

public ngOnDestroy() {
this.destroy$.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ <h2>{{ 'DESCRIPTIONS.SETTINGS.PRIVACY_POLICY.TITLE' | translate }}</h2>
color="warn"
(click)="resetDefault()"
mat-stroked-button
data-e2e="reset-button"
>
{{ 'POLICY.RESET' | translate }}
</button>
Expand Down Expand Up @@ -40,7 +41,23 @@ <h2>{{ 'DESCRIPTIONS.SETTINGS.PRIVACY_POLICY.TITLE' | translate }}</h2>
<cnsl-form-field class="privacy-policy-formfield">
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.SUPPORTEMAIL' | translate }}</cnsl-label>
<input cnslInput name="supportEmail" formControlName="supportEmail" />
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ key: 'supportEmail' }"></template>
</cnsl-form-field>

<cnsl-form-field class="privacy-policy-formfield">
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.CUSTOMLINK' | translate }}</cnsl-label>
<input cnslInput name="customLink" formControlName="customLink" />
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ key: 'customLink' }"></template>
</cnsl-form-field>

<cnsl-form-field class="privacy-policy-formfield">
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.CUSTOMLINKTEXT' | translate }}</cnsl-label>
<input cnslInput name="customLinkText" formControlName="customLinkText" />
</cnsl-form-field>

<cnsl-form-field class="privacy-policy-formfield">
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.DOCSLINK' | translate }}</cnsl-label>
<input cnslInput name="docsLink" formControlName="docsLink" />
<template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{ key: 'docsLink' }"></template>
</cnsl-form-field>
</form>
</div>
Expand All @@ -53,6 +70,7 @@ <h2>{{ 'DESCRIPTIONS.SETTINGS.PRIVACY_POLICY.TITLE' | translate }}</h2>
color="primary"
type="submit"
mat-raised-button
data-e2e="save-button"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
privacyLink: ['', []],
helpLink: ['', []],
supportEmail: ['', []],
docsLink: ['', []],
customLink: ['', []],
customLinkText: ['', []],
});

this.canWrite$.pipe(take(1)).subscribe((canWrite) => {
Expand Down Expand Up @@ -107,6 +110,9 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
privacyLink: '',
helpLink: '',
supportEmail: '',
docsLink: '',
customLink: '',
customLinkText: '',
});
}
})
Expand All @@ -117,6 +123,9 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
privacyLink: '',
helpLink: '',
supportEmail: '',
docsLink: '',
customLink: '',
customLinkText: '',
});
});
}
Expand All @@ -129,11 +138,16 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
req.setTosLink(this.form.get('tosLink')?.value);
req.setHelpLink(this.form.get('helpLink')?.value);
req.setSupportEmail(this.form.get('supportEmail')?.value);
req.setDocsLink(this.form.get('docsLink')?.value);
req.setCustomLink(this.form.get('customLink')?.value);
req.setCustomLinkText(this.form.get('customLinkText')?.value);
(this.service as ManagementService)
.addCustomPrivacyPolicy(req)
.then(() => {
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
this.loadData();
// Reload console as links may have changed
this.reloadConsole();
})
.catch((error) => this.toast.showError(error));
} else {
Expand All @@ -142,12 +156,17 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
req.setTosLink(this.form.get('tosLink')?.value);
req.setHelpLink(this.form.get('helpLink')?.value);
req.setSupportEmail(this.form.get('supportEmail')?.value);
req.setDocsLink(this.form.get('docsLink')?.value);
req.setCustomLink(this.form.get('customLink')?.value);
req.setCustomLinkText(this.form.get('customLinkText')?.value);

(this.service as ManagementService)
.updateCustomPrivacyPolicy(req)
.then(() => {
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
this.loadData();
// Reload console as links may have changed
this.reloadConsole();
})
.catch((error) => this.toast.showError(error));
}
Expand All @@ -157,12 +176,17 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
req.setTosLink(this.form.get('tosLink')?.value);
req.setHelpLink(this.form.get('helpLink')?.value);
req.setSupportEmail(this.form.get('supportEmail')?.value);
req.setDocsLink(this.form.get('docsLink')?.value);
req.setCustomLink(this.form.get('customLink')?.value);
req.setCustomLinkText(this.form.get('customLinkText')?.value);

(this.service as AdminService)
.updatePrivacyPolicy(req)
.then(() => {
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
this.loadData();
// Reload console as links may have changed
this.reloadConsole();
})
.catch((error) => this.toast.showError(error));
}
Expand All @@ -188,6 +212,7 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
.then(() => {
setTimeout(() => {
this.loadData();
window.location.reload();
}, 1000);
})
.catch((error) => {
Expand All @@ -209,4 +234,10 @@ export class PrivacyPolicyComponent implements OnInit, OnDestroy {
return false;
}
}

private reloadConsole(): void {
setTimeout(() => {
window.location.reload();
}, 1000);
}
}
2 changes: 1 addition & 1 deletion console/src/app/modules/settings-grid/settinglinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const APPEARANCE_GROUP: SettingLinks = {
};

export const PRIVACY_POLICY: SettingLinks = {
i18nTitle: 'SETTINGS.LIST.PRIVACYPOLICY',
i18nTitle: 'DESCRIPTIONS.SETTINGS.PRIVACY_POLICY.TITLE',
i18nDesc: 'POLICY.PRIVACY_POLICY.DESCRIPTION',
iamRouterLink: ['/settings'],
orgRouterLink: ['/org-settings'],
Expand Down
2 changes: 1 addition & 1 deletion console/src/app/modules/settings-list/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export const LOGINTEXTS: SidenavSetting = {

export const PRIVACYPOLICY: SidenavSetting = {
id: 'privacypolicy',
i18nKey: 'SETTINGS.LIST.PRIVACYPOLICY',
i18nKey: 'DESCRIPTIONS.SETTINGS.PRIVACY_POLICY.TITLE',
groupI18nKey: 'SETTINGS.GROUPS.OTHER',
requiredRoles: {
[PolicyComponentServiceType.MGMT]: ['policy.read'],
Expand Down
Loading

0 comments on commit 15d5338

Please sign in to comment.