mirror of
https://github.com/zitadel/zitadel.git
synced 2025-10-20 12:22:25 +00:00
feat(console): message and login texts, privacy policy (#2016)
* message texts wrapper components * message-text sub, i18n, grid * fix routing * pack * pack * update material * audit * fix mgmt service for labelplcy * map conv * edit text from map * request map * fetch data, mgmt admin service * warn box, i18n * resetbtn * login texts * login text requests * reset, default, i18n * disabled, features, message text setter, service * locale switcher * policy grid * password reset, domain claimed i18n * lint files * fix admin service, i18n, lang setter * fix scss duplicate * privacy policy, cleanup grid, fix message, login texts (#2031) * policy grid everywhere 🦒 * cleanup home * log login text request * patch all data * refresh toggle * fix: add dialog for unsaved changes (#2057) * logintexts dialog * check for dialog on pairwise operation * fix: patch value to local state after save * fix: i18n and custom login texts (#2060) * fix: i18n and custom login texts * fix: tos and privacy texts * fix frontend * fix: tos and privacy texts and tests * fix: i18n, tos and privacy texts and tests * fix frontend maps * i18n * add ResetCustomLoginTextToDefault in admin api and fix template remove in handlers * resetlogintexttodefault Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -219,6 +219,5 @@
|
||||
</app-card>
|
||||
</ng-template>
|
||||
|
||||
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
||||
|
||||
<app-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security"></app-policy-grid>
|
||||
</app-detail-layout>
|
||||
|
@@ -137,3 +137,8 @@
|
||||
background-color: rgba(var(--grey), .5);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: block;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
@@ -19,15 +19,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CnslLinks } from '../../links/links.component';
|
||||
import {
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
ORG_COMPLEXITY_LINK,
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
} from '../../policy-grid/policy-links';
|
||||
import { GridPolicy, LOGIN_POLICY } from '../../policy-grid/policies';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
|
||||
|
||||
@@ -51,7 +43,7 @@ export class LoginPolicyComponent implements OnDestroy {
|
||||
public disabled: boolean = true;
|
||||
|
||||
public IDPStylingType: any = IDPStylingType;
|
||||
public nextLinks: CnslLinks[] = [];
|
||||
public currentPolicy: GridPolicy = LOGIN_POLICY;
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
@@ -67,11 +59,6 @@ export class LoginPolicyComponent implements OnDestroy {
|
||||
PasswordlessType.PASSWORDLESS_TYPE_ALLOWED,
|
||||
PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED,
|
||||
];
|
||||
this.nextLinks = [
|
||||
ORG_COMPLEXITY_LINK,
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
];
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
@@ -79,11 +66,6 @@ export class LoginPolicyComponent implements OnDestroy {
|
||||
PasswordlessType.PASSWORDLESS_TYPE_ALLOWED,
|
||||
PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED,
|
||||
];
|
||||
this.nextLinks = [
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -19,36 +19,36 @@ import { HasFeaturePipeModule } from 'src/app/pipes/has-feature-pipe/has-feature
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { LinksModule } from '../../links/links.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { AddIdpDialogModule } from './add-idp-dialog/add-idp-dialog.module';
|
||||
import { LoginPolicyRoutingModule } from './login-policy-routing.module';
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
imports: [
|
||||
LoginPolicyRoutingModule,
|
||||
CommonModule,
|
||||
InfoSectionModule,
|
||||
FormsModule,
|
||||
CardModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
HasFeaturePipeModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
AddIdpDialogModule,
|
||||
IdpTableModule,
|
||||
MfaTableModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
MatRippleModule,
|
||||
LinksModule,
|
||||
],
|
||||
declarations: [LoginPolicyComponent],
|
||||
imports: [
|
||||
LoginPolicyRoutingModule,
|
||||
CommonModule,
|
||||
InfoSectionModule,
|
||||
FormsModule,
|
||||
CardModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
HasFeaturePipeModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
AddIdpDialogModule,
|
||||
IdpTableModule,
|
||||
MfaTableModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
MatRippleModule,
|
||||
PolicyGridModule,
|
||||
],
|
||||
})
|
||||
export class LoginPolicyModule { }
|
||||
|
317
console/src/app/modules/policies/login-texts/helper.ts
Normal file
317
console/src/app/modules/policies/login-texts/helper.ts
Normal file
@@ -0,0 +1,317 @@
|
||||
import { SetCustomLoginTextsRequest as AdminSetCustomLoginTextsRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { SetCustomLoginTextsRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import {
|
||||
EmailVerificationDoneScreenText,
|
||||
EmailVerificationScreenText,
|
||||
ExternalUserNotFoundScreenText,
|
||||
FooterText,
|
||||
InitializeUserDoneScreenText,
|
||||
InitializeUserScreenText,
|
||||
InitMFADoneScreenText,
|
||||
InitMFAOTPScreenText,
|
||||
InitMFAPromptScreenText,
|
||||
InitMFAU2FScreenText,
|
||||
InitPasswordDoneScreenText,
|
||||
InitPasswordScreenText,
|
||||
LinkingUserDoneScreenText,
|
||||
LoginScreenText,
|
||||
LogoutDoneScreenText,
|
||||
MFAProvidersText,
|
||||
PasswordChangeDoneScreenText,
|
||||
PasswordChangeScreenText,
|
||||
PasswordlessScreenText,
|
||||
PasswordResetDoneScreenText,
|
||||
PasswordScreenText,
|
||||
RegistrationOptionScreenText,
|
||||
RegistrationOrgScreenText,
|
||||
RegistrationUserScreenText,
|
||||
SelectAccountScreenText,
|
||||
SuccessLoginScreenText,
|
||||
UsernameChangeDoneScreenText,
|
||||
UsernameChangeScreenText,
|
||||
VerifyMFAOTPScreenText,
|
||||
VerifyMFAU2FScreenText,
|
||||
} from 'src/app/proto/generated/zitadel/text_pb';
|
||||
|
||||
type Req = AdminSetCustomLoginTextsRequest | SetCustomLoginTextsRequest;
|
||||
type Map = AdminSetCustomLoginTextsRequest.AsObject | SetCustomLoginTextsRequest.AsObject;
|
||||
|
||||
export function mapRequestValues(map: Partial<Map>, req: Req): Req {
|
||||
const r0 = new EmailVerificationDoneScreenText();
|
||||
r0.setCancelButtonText(map.emailVerificationDoneText?.cancelButtonText ?? '');
|
||||
r0.setDescription(map.emailVerificationDoneText?.description ?? '');
|
||||
r0.setLoginButtonText(map.emailVerificationDoneText?.loginButtonText ?? '');
|
||||
r0.setNextButtonText(map.emailVerificationDoneText?.nextButtonText ?? '');
|
||||
r0.setTitle(map.emailVerificationDoneText?.title ?? '');
|
||||
req.setEmailVerificationDoneText(r0);
|
||||
|
||||
const r1 = new EmailVerificationScreenText();
|
||||
r1.setCodeLabel(map.emailVerificationText?.codeLabel ?? '');
|
||||
r1.setDescription(map.emailVerificationText?.description ?? '');
|
||||
r1.setNextButtonText(map.emailVerificationText?.nextButtonText ?? '');
|
||||
r1.setResendButtonText(map.emailVerificationText?.resendButtonText ?? '');
|
||||
r1.setTitle(map.emailVerificationText?.title ?? '');
|
||||
req.setEmailVerificationText(r1);
|
||||
|
||||
const r2 = new ExternalUserNotFoundScreenText();
|
||||
r2.setAutoRegisterButtonText(map.externalUserNotFoundText?.autoRegisterButtonText ?? '');
|
||||
r2.setDescription(map.externalUserNotFoundText?.description ?? '');
|
||||
r2.setLinkButtonText(map.externalUserNotFoundText?.linkButtonText ?? '');
|
||||
r2.setTitle(map.externalUserNotFoundText?.title ?? '');
|
||||
req.setExternalUserNotFoundText(r2);
|
||||
|
||||
const r3 = new FooterText();
|
||||
r3.setHelp(map.footerText?.help ?? '');
|
||||
r3.setHelpLink(map.footerText?.helpLink ?? '');
|
||||
r3.setPrivacyPolicy(map.footerText?.privacyPolicy ?? '');
|
||||
r3.setTos(map.footerText?.tos ?? '');
|
||||
req.setFooterText(r3);
|
||||
|
||||
const r4 = new InitMFADoneScreenText();
|
||||
r4.setCancelButtonText(map.initMfaDoneText?.cancelButtonText ?? '');
|
||||
r4.setDescription(map.initMfaDoneText?.description ?? '');
|
||||
r4.setNextButtonText(map.initMfaDoneText?.nextButtonText ?? '');
|
||||
r4.setTitle(map.initMfaDoneText?.title ?? '');
|
||||
req.setInitMfaDoneText(r4);
|
||||
|
||||
const r5 = new InitMFAOTPScreenText();
|
||||
r5.setCancelButtonText(map.initMfaOtpText?.cancelButtonText ?? '');
|
||||
r5.setCodeLabel(map.initMfaOtpText?.codeLabel ?? '');
|
||||
r5.setDescription(map.initMfaOtpText?.description ?? '');
|
||||
r5.setDescriptionOtp(map.initMfaOtpText?.descriptionOtp ?? '');
|
||||
r5.setNextButtonText(map.initMfaOtpText?.nextButtonText ?? '');
|
||||
r5.setSecretLabel(map.initMfaOtpText?.secretLabel ?? '');
|
||||
r5.setTitle(map.initMfaOtpText?.title ?? '');
|
||||
req.setInitMfaOtpText(r5);
|
||||
|
||||
const r6 = new InitMFAPromptScreenText();
|
||||
r6.setDescription(map.initMfaPromptText?.description ?? '');
|
||||
r6.setNextButtonText(map.initMfaPromptText?.nextButtonText ?? '');
|
||||
r6.setOtpOption(map.initMfaPromptText?.otpOption ?? '');
|
||||
r6.setSkipButtonText(map.initMfaPromptText?.skipButtonText ?? '');
|
||||
r6.setTitle(map.initMfaPromptText?.title ?? '');
|
||||
r6.setU2fOption(map.initMfaPromptText?.otpOption ?? '');
|
||||
req.setInitMfaPromptText(r6);
|
||||
|
||||
|
||||
const r7 = new InitMFAU2FScreenText();
|
||||
r7.setDescription(map.initMfaU2fText?.description ?? '');
|
||||
r7.setErrorRetry(map.initMfaU2fText?.errorRetry ?? '');
|
||||
r7.setNotSupported(map.initMfaU2fText?.notSupported ?? '');
|
||||
r7.setRegisterTokenButtonText(map.initMfaU2fText?.registerTokenButtonText ?? '');
|
||||
r7.setTitle(map.initMfaU2fText?.title ?? '');
|
||||
r7.setTokenNameLabel(map.initMfaU2fText?.tokenNameLabel ?? '');
|
||||
req.setInitMfaU2fText(r7);
|
||||
|
||||
|
||||
const r8 = new InitPasswordDoneScreenText();
|
||||
r8.setCancelButtonText(map.initPasswordDoneText?.cancelButtonText ?? '');
|
||||
r8.setDescription(map.initPasswordDoneText?.description ?? '');
|
||||
r8.setNextButtonText(map.initPasswordDoneText?.nextButtonText ?? '');
|
||||
r8.setTitle(map.initPasswordDoneText?.title ?? '');
|
||||
req.setInitPasswordDoneText(r8);
|
||||
|
||||
const r9 = new InitPasswordScreenText();
|
||||
r9.setCodeLabel(map.initPasswordText?.description ?? '');
|
||||
r9.setDescription(map.initPasswordText?.description ?? '');
|
||||
r9.setNewPasswordConfirmLabel(map.initPasswordText?.newPasswordConfirmLabel ?? '');
|
||||
r9.setNewPasswordLabel(map.initPasswordText?.newPasswordLabel ?? '');
|
||||
r9.setNextButtonText(map.initPasswordText?.nextButtonText ?? '');
|
||||
r9.setResendButtonText(map.initPasswordText?.resendButtonText ?? '');
|
||||
r9.setTitle(map.initPasswordText?.title ?? '');
|
||||
req.setInitPasswordText(r9);
|
||||
|
||||
const r10 = new InitializeUserDoneScreenText();
|
||||
r10.setCancelButtonText(map.initializeDoneText?.cancelButtonText ?? '');
|
||||
r10.setDescription(map.initializeDoneText?.description ?? '');
|
||||
r10.setNextButtonText(map.initializeDoneText?.nextButtonText ?? '');
|
||||
r10.setTitle(map.initializeDoneText?.title ?? '');
|
||||
req.setInitializeDoneText(r10);
|
||||
|
||||
const r11 = new InitializeUserScreenText();
|
||||
r11.setCodeLabel(map.initializeUserText?.codeLabel ?? '');
|
||||
r11.setDescription(map.initializeUserText?.description ?? '');
|
||||
r11.setNewPasswordConfirmLabel(map.initializeUserText?.newPasswordConfirmLabel ?? '');
|
||||
r11.setNewPasswordLabel(map.initializeUserText?.newPasswordLabel ?? '');
|
||||
r11.setNextButtonText(map.initializeUserText?.nextButtonText ?? '');
|
||||
r11.setResendButtonText(map.initializeUserText?.resendButtonText ?? '');
|
||||
r11.setTitle(map.initializeUserText?.title ?? '');
|
||||
|
||||
req.setInitializeUserText(r11);
|
||||
|
||||
const r12 = new LinkingUserDoneScreenText();
|
||||
r12.setCancelButtonText(map.linkingUserDoneText?.cancelButtonText ?? '');
|
||||
r12.setDescription(map.linkingUserDoneText?.description ?? '');
|
||||
r12.setNextButtonText(map.linkingUserDoneText?.nextButtonText ?? '');
|
||||
r12.setTitle(map.linkingUserDoneText?.title ?? '');
|
||||
req.setLinkingUserDoneText(r12);
|
||||
|
||||
const r13 = new LoginScreenText();
|
||||
r13.setDescription(map.loginText?.description ?? '');
|
||||
r13.setDescriptionLinkingProcess(map.loginText?.descriptionLinkingProcess ?? '');
|
||||
r13.setExternalUserDescription(map.loginText?.externalUserDescription ?? '');
|
||||
r13.setLoginNameLabel(map.loginText?.loginNameLabel ?? '');
|
||||
r13.setLoginNamePlaceholder(map.loginText?.loginNamePlaceholder ?? '');
|
||||
r13.setNextButtonText(map.loginText?.nextButtonText ?? '');
|
||||
r13.setRegisterButtonText(map.loginText?.registerButtonText ?? '');
|
||||
r13.setTitle(map.loginText?.title ?? '');
|
||||
r13.setTitleLinkingProcess(map.loginText?.titleLinkingProcess ?? '');
|
||||
r13.setUserMustBeMemberOfOrg(map.loginText?.userMustBeMemberOfOrg ?? '');
|
||||
r13.setUserNamePlaceholder(map.loginText?.userNamePlaceholder ?? '');
|
||||
req.setLoginText(r13);
|
||||
|
||||
const r14 = new LogoutDoneScreenText();
|
||||
r14.setDescription(map.logoutText?.description ?? '');
|
||||
r14.setLoginButtonText(map.logoutText?.loginButtonText ?? '');
|
||||
r14.setTitle(map.logoutText?.title ?? '');
|
||||
req.setLogoutText(r14);
|
||||
|
||||
const r15 = new MFAProvidersText();
|
||||
r15.setChooseOther(map.mfaProvidersText?.chooseOther ?? '');
|
||||
r15.setOtp(map.mfaProvidersText?.otp ?? '');
|
||||
r15.setU2f(map.mfaProvidersText?.u2f ?? '');
|
||||
req.setMfaProvidersText(r15);
|
||||
|
||||
const r16 = new PasswordChangeDoneScreenText();
|
||||
r16.setDescription(map.passwordChangeDoneText?.description ?? '');
|
||||
r16.setNextButtonText(map.passwordChangeDoneText?.nextButtonText ?? '');
|
||||
r16.setTitle(map.passwordChangeDoneText?.title ?? '');
|
||||
req.setPasswordChangeDoneText(r16);
|
||||
|
||||
const r17 = new PasswordChangeScreenText();
|
||||
r17.setDescription(map.passwordChangeText?.description ?? '');
|
||||
r17.setNextButtonText(map.passwordChangeText?.nextButtonText ?? '');
|
||||
r17.setTitle(map.passwordChangeText?.title ?? '');
|
||||
r17.setNewPasswordLabel(map.passwordChangeText?.newPasswordLabel ?? '');
|
||||
r17.setNewPasswordConfirmLabel(map.passwordChangeText?.newPasswordConfirmLabel ?? '');
|
||||
r17.setCancelButtonText(map.passwordChangeText?.cancelButtonText ?? '');
|
||||
r17.setOldPasswordLabel(map.passwordChangeText?.oldPasswordLabel ?? '');
|
||||
req.setPasswordChangeText(r17);
|
||||
|
||||
const r18 = new PasswordResetDoneScreenText();
|
||||
r18.setDescription(map.passwordResetDoneText?.description ?? '');
|
||||
r18.setNextButtonText(map.passwordResetDoneText?.nextButtonText ?? '');
|
||||
r18.setTitle(map.passwordResetDoneText?.title ?? '');
|
||||
req.setPasswordResetDoneText(r18);
|
||||
|
||||
const r19 = new PasswordScreenText();
|
||||
r19.setBackButtonText(map.passwordText?.backButtonText ?? '');
|
||||
r19.setConfirmation(map.passwordText?.confirmation ?? '');
|
||||
r19.setDescription(map.passwordText?.description ?? '');
|
||||
r19.setHasLowercase(map.passwordText?.hasLowercase ?? '');
|
||||
r19.setHasNumber(map.passwordText?.hasNumber ?? '');
|
||||
r19.setHasSymbol(map.passwordText?.hasSymbol ?? '');
|
||||
r19.setHasUppercase(map.passwordText?.hasUppercase ?? '');
|
||||
r19.setMinLength(map.passwordText?.minLength ?? '');
|
||||
r19.setNextButtonText(map.passwordText?.nextButtonText ?? '');
|
||||
r19.setPasswordLabel(map.passwordText?.passwordLabel ?? '');
|
||||
r19.setResetLinkText(map.passwordText?.resetLinkText ?? '');
|
||||
r19.setTitle(map.passwordText?.title ?? '');
|
||||
req.setPasswordText(r19);
|
||||
|
||||
const r20 = new PasswordlessScreenText();
|
||||
r20.setDescription(map.passwordlessText?.description ?? '');
|
||||
r20.setErrorRetry(map.passwordlessText?.errorRetry ?? '');
|
||||
r20.setLoginWithPwButtonText(map.passwordlessText?.loginWithPwButtonText ?? '');
|
||||
r20.setNotSupported(map.passwordlessText?.notSupported ?? '');
|
||||
r20.setTitle(map.passwordlessText?.title ?? '');
|
||||
r20.setValidateTokenButtonText(map.passwordlessText?.validateTokenButtonText ?? '');
|
||||
req.setPasswordlessText(r20);
|
||||
|
||||
const r21 = new RegistrationOptionScreenText();
|
||||
r21.setDescription(map.registrationOptionText?.description ?? '');
|
||||
r21.setExternalLoginDescription(map.registrationOptionText?.externalLoginDescription ?? '');
|
||||
r21.setTitle(map.registrationOptionText?.title ?? '');
|
||||
r21.setUserNameButtonText(map.registrationOptionText?.userNameButtonText ?? '');
|
||||
req.setRegistrationOptionText(r21);
|
||||
|
||||
const r22 = new RegistrationOrgScreenText();
|
||||
r22.setDescription(map.registrationOrgText?.description ?? '');
|
||||
r22.setEmailLabel(map.registrationOrgText?.emailLabel ?? '');
|
||||
r22.setFirstnameLabel(map.registrationOrgText?.firstnameLabel ?? '');
|
||||
r22.setLastnameLabel(map.registrationOrgText?.lastnameLabel ?? '');
|
||||
r22.setOrgnameLabel(map.registrationOrgText?.orgnameLabel ?? '');
|
||||
r22.setPasswordConfirmLabel(map.registrationOrgText?.passwordConfirmLabel ?? '');
|
||||
r22.setPasswordLabel(map.registrationOrgText?.passwordLabel ?? '');
|
||||
r22.setTosConfirmAnd(map.registrationOrgText?.tosConfirm ?? '');
|
||||
r22.setPrivacyLinkText(map.registrationOrgText?.privacyLinkText ?? '');
|
||||
r22.setSaveButtonText(map.registrationOrgText?.saveButtonText ?? '');
|
||||
r22.setTitle(map.registrationOrgText?.title ?? '');
|
||||
r22.setTosAndPrivacyLabel(map.registrationOrgText?.tosAndPrivacyLabel ?? '');
|
||||
r22.setTosConfirm(map.registrationOrgText?.tosConfirm ?? '');
|
||||
r22.setTosConfirmAnd(map.registrationOrgText?.tosConfirmAnd ?? '');
|
||||
r22.setTosLinkText(map.registrationOrgText?.tosLinkText ?? '');
|
||||
r22.setUsernameLabel(map.registrationOrgText?.usernameLabel ?? '');
|
||||
req.setRegistrationOrgText(r22);
|
||||
|
||||
const r23 = new RegistrationUserScreenText();
|
||||
r23.setBackButtonText(map.registrationUserText?.backButtonText ?? '');
|
||||
r23.setDescription(map.registrationUserText?.description ?? '');
|
||||
r23.setDescriptionOrgRegister(map.registrationUserText?.descriptionOrgRegister ?? '');
|
||||
r23.setEmailLabel(map.registrationUserText?.emailLabel ?? '');
|
||||
r23.setFirstnameLabel(map.registrationUserText?.firstnameLabel ?? '');
|
||||
r23.setGenderLabel(map.registrationUserText?.genderLabel ?? '');
|
||||
r23.setLanguageLabel(map.registrationUserText?.languageLabel ?? '');
|
||||
r23.setLastnameLabel(map.registrationUserText?.lastnameLabel ?? '');
|
||||
r23.setNextButtonText(map.registrationUserText?.nextButtonText ?? '');
|
||||
r23.setPasswordConfirmLabel(map.registrationUserText?.passwordConfirmLabel ?? '');
|
||||
r23.setPasswordLabel(map.registrationUserText?.passwordLabel ?? '');
|
||||
r23.setTosConfirm(map.registrationUserText?.tosConfirm ?? '');
|
||||
r23.setTosConfirmAnd(map.registrationUserText?.tosConfirmAnd ?? '');
|
||||
r23.setTosLinkText(map.registrationUserText?.tosLinkText ?? '');
|
||||
r23.setPrivacyLinkText(map.registrationUserText?.privacyLinkText ?? '');
|
||||
r23.setTitle(map.registrationUserText?.title ?? '');
|
||||
r23.setTosAndPrivacyLabel(map.registrationUserText?.tosAndPrivacyLabel ?? '');
|
||||
r23.setTosConfirm(map.registrationUserText?.tosConfirm ?? '');
|
||||
r23.setUsernameLabel(map.registrationUserText?.usernameLabel ?? '');
|
||||
req.setRegistrationUserText(r23);
|
||||
|
||||
const r24 = new SelectAccountScreenText();
|
||||
r24.setDescription(map.selectAccountText?.description ?? '');
|
||||
r24.setDescriptionLinkingProcess(map.selectAccountText?.descriptionLinkingProcess ?? '');
|
||||
r24.setOtherUser(map.selectAccountText?.otherUser ?? '');
|
||||
r24.setSessionStateActive(map.selectAccountText?.sessionStateActive ?? '');
|
||||
r24.setSessionStateInactive(map.selectAccountText?.sessionStateInactive ?? '');
|
||||
r24.setTitle(map.selectAccountText?.title ?? '');
|
||||
r24.setTitleLinkingProcess(map.selectAccountText?.titleLinkingProcess ?? '');
|
||||
r24.setUserMustBeMemberOfOrg(map.selectAccountText?.userMustBeMemberOfOrg ?? '');
|
||||
req.setSelectAccountText(r24);
|
||||
|
||||
const r25 = new SuccessLoginScreenText();
|
||||
r25.setAutoRedirectDescription(map.successLoginText?.autoRedirectDescription ?? '');
|
||||
r25.setNextButtonText(map.successLoginText?.nextButtonText ?? '');
|
||||
r25.setRedirectedDescription(map.successLoginText?.redirectedDescription ?? '');
|
||||
r25.setTitle(map.successLoginText?.title ?? '');
|
||||
req.setSuccessLoginText(r25);
|
||||
|
||||
const r26 = new UsernameChangeDoneScreenText();
|
||||
r26.setDescription(map.usernameChangeDoneText?.description ?? '');
|
||||
r26.setNextButtonText(map.usernameChangeDoneText?.nextButtonText ?? '');
|
||||
r26.setTitle(map.usernameChangeDoneText?.title ?? '');
|
||||
req.setUsernameChangeDoneText(r26);
|
||||
|
||||
const r27 = new UsernameChangeScreenText();
|
||||
r27.setCancelButtonText(map.usernameChangeText?.cancelButtonText ?? '');
|
||||
r27.setDescription(map.usernameChangeText?.description ?? '');
|
||||
r27.setNextButtonText(map.usernameChangeText?.nextButtonText ?? '');
|
||||
r27.setTitle(map.usernameChangeText?.title ?? '');
|
||||
r27.setUsernameLabel(map.usernameChangeText?.usernameLabel ?? '');
|
||||
req.setUsernameChangeText(r27);
|
||||
|
||||
const r28 = new VerifyMFAOTPScreenText();
|
||||
r28.setCodeLabel(map.verifyMfaOtpText?.codeLabel ?? '');
|
||||
r28.setDescription(map.verifyMfaOtpText?.description ?? '');
|
||||
r28.setNextButtonText(map.verifyMfaOtpText?.nextButtonText ?? '');
|
||||
r28.setTitle(map.verifyMfaOtpText?.title ?? '');
|
||||
req.setVerifyMfaOtpText(r28);
|
||||
|
||||
const r29 = new VerifyMFAU2FScreenText();
|
||||
r29.setDescription(map.verifyMfaU2fText?.description ?? '');
|
||||
r29.setErrorRetry(map.verifyMfaU2fText?.errorRetry ?? '');
|
||||
r29.setNotSupported(map.verifyMfaU2fText?.notSupported ?? '');
|
||||
r29.setTitle(map.verifyMfaU2fText?.title ?? '');
|
||||
r29.setValidateTokenText(map.verifyMfaU2fText?.validateTokenText ?? '');
|
||||
req.setVerifyMfaU2fText(r29);
|
||||
|
||||
return req;
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { LoginTextsComponent } from './login-texts.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: LoginTextsComponent,
|
||||
data: {
|
||||
animation: 'DetailPage',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class LoginTextsRoutingModule { }
|
@@ -0,0 +1,60 @@
|
||||
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
|
||||
[title]="'POLICY.LOGIN_TEXTS.TITLE' | translate"
|
||||
[description]="'POLICY.LOGIN_TEXTS.DESCRIPTION' | translate">
|
||||
|
||||
|
||||
<div class="date">
|
||||
<div>
|
||||
<p class="newer-title" *ngIf="newerVersionExists">{{'POLICY.LOGIN_TEXTS.NEWERVERSIONEXISTS' | translate}}</p>
|
||||
<p *ngIf="newerPolicyChangeDate && newerVersionExists">{{'POLICY.LOGIN_TEXTS.CHANGEDATE' | translate}}: {{newerPolicyChangeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm:ss'}}</p>
|
||||
<p class="gray" *ngIf="currentPolicyChangeDate">{{'POLICY.LOGIN_TEXTS.CURRENTDATE' | translate}}: {{currentPolicyChangeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm:ss'}}</p>
|
||||
</div>
|
||||
<button [disabled]="!newerVersionExists" color="primary" mat-raised-button (click)="loadData()">
|
||||
<i class="las la-sync-alt"></i>
|
||||
{{'ACTIONS.REFRESH' | translate}}</button>
|
||||
</div>
|
||||
<form *ngIf="form" class="top-actions" [formGroup]="form">
|
||||
<cnsl-form-field class="keys" appearance="outline" >
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.KEYNAME' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="currentSubMap" name="currentSubMap">
|
||||
<mat-option *ngFor="let key of KeyNamesArray" [value]="key">
|
||||
{{'POLICY.LOGIN_TEXTS.KEYS.'+key | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="language">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
|
||||
<mat-select formControlName="locale" name="locale">
|
||||
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
|
||||
<div class="centerline">
|
||||
<span>{{loc}} <span class="lighter">| {{'POLICY.LOGIN_TEXTS.LOCALES.'+loc | translate }}</span></span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
|
||||
<cnsl-info-section class="warn"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false"
|
||||
type="WARN">
|
||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'custom_text'})}}
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="content" >
|
||||
<cnsl-edit-text label="one" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
$event)"></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
|
||||
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
|
||||
</app-detail-layout>
|
@@ -0,0 +1,108 @@
|
||||
.spinner-wr {
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.date {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
p {
|
||||
margin: .4rem 0;
|
||||
font-size: 14px;
|
||||
|
||||
&.gray {
|
||||
color: var(--grey);
|
||||
}
|
||||
}
|
||||
|
||||
.newer-title {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
align-self: center;
|
||||
|
||||
i {
|
||||
margin-bottom: 3px;
|
||||
margin-right: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-actions {
|
||||
display: flex;
|
||||
margin: 0 -.5rem;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.keys {
|
||||
flex: 1;
|
||||
margin: 0 .5rem;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.language {
|
||||
margin: 0 .5rem;
|
||||
min-width: 150px;
|
||||
|
||||
.lighter {
|
||||
font-size: 12px;
|
||||
color: var(--grey);
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.centerline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.chips {
|
||||
display: flex;
|
||||
margin: 0 -.25rem;
|
||||
|
||||
.chip {
|
||||
border-radius: 50vw;
|
||||
padding: 2px .5rem;
|
||||
font-size: 12px;
|
||||
background: #cbf4c9;
|
||||
color: #0e6245;
|
||||
margin: .25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: rgba(#81868a, .5);
|
||||
margin: 1.5rem 0 0 0;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.save-button,
|
||||
.reset-button {
|
||||
display: block;
|
||||
margin: 0 .25rem 3rem .25rem;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
|
||||
describe('LoginPolicyComponent', () => {
|
||||
let component: LoginPolicyComponent;
|
||||
let fixture: ComponentFixture<LoginPolicyComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginPolicyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,346 @@
|
||||
import { Component, Injector, OnDestroy, Type } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb';
|
||||
import { BehaviorSubject, from, interval, Observable, of, Subject, Subscription } from 'rxjs';
|
||||
import { map, pairwise, startWith, switchMap, takeUntil } from 'rxjs/operators';
|
||||
import {
|
||||
GetCustomLoginTextsRequest as AdminGetCustomLoginTextsRequest,
|
||||
GetDefaultLoginTextsRequest as AdminGetDefaultLoginTextsRequest,
|
||||
SetCustomLoginTextsRequest as AdminSetCustomLoginTextsRequest,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
GetCustomLoginTextsRequest,
|
||||
GetDefaultLoginTextsRequest,
|
||||
SetCustomLoginTextsRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { GridPolicy, LOGIN_TEXTS_POLICY } from '../../policy-grid/policies';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { mapRequestValues } from './helper';
|
||||
|
||||
// tslint:disable
|
||||
const KeyNamesArray = [
|
||||
'emailVerificationDoneText',
|
||||
'emailVerificationText',
|
||||
'externalUserNotFoundText',
|
||||
'footerText',
|
||||
'initMfaDoneText',
|
||||
'initMfaOtpText',
|
||||
'initMfaPromptText',
|
||||
'initMfaU2fText',
|
||||
'initPasswordDoneText',
|
||||
'initPasswordText',
|
||||
'initializeDoneText',
|
||||
'initializeUserText',
|
||||
'linkingUserDoneText',
|
||||
'loginText',
|
||||
'logoutText',
|
||||
'mfaProvidersText',
|
||||
'passwordChangeDoneText',
|
||||
'passwordChangeText',
|
||||
'passwordResetDoneText',
|
||||
'passwordText',
|
||||
'passwordlessText',
|
||||
'registrationOptionText',
|
||||
'registrationOrgText',
|
||||
'registrationUserText',
|
||||
'selectAccountText',
|
||||
'successLoginText',
|
||||
'usernameChangeDoneText',
|
||||
'usernameChangeText',
|
||||
'verifyMfaOtpText',
|
||||
'verifyMfaU2fText',
|
||||
];
|
||||
// tslint:enable
|
||||
|
||||
const REQUESTMAP = {
|
||||
[PolicyComponentServiceType.MGMT]: {
|
||||
get: new GetCustomLoginTextsRequest(),
|
||||
set: new SetCustomLoginTextsRequest(),
|
||||
getDefault: new GetDefaultLoginTextsRequest(),
|
||||
setFcn: (mgmtmap: Partial<SetCustomLoginTextsRequest.AsObject>): SetCustomLoginTextsRequest => {
|
||||
let req = new SetCustomLoginTextsRequest();
|
||||
req.setLanguage(mgmtmap.language ?? '');
|
||||
req = mapRequestValues(mgmtmap, req);
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[PolicyComponentServiceType.ADMIN]: {
|
||||
get: new AdminGetCustomLoginTextsRequest(),
|
||||
set: new AdminSetCustomLoginTextsRequest(),
|
||||
getDefault: new AdminGetDefaultLoginTextsRequest(),
|
||||
setFcn: (adminmap: Partial<AdminSetCustomLoginTextsRequest.AsObject>): AdminSetCustomLoginTextsRequest => {
|
||||
let req = new AdminSetCustomLoginTextsRequest();
|
||||
req.setLanguage(adminmap.language ?? '');
|
||||
req = mapRequestValues(adminmap, req);
|
||||
return req;
|
||||
},
|
||||
},
|
||||
};
|
||||
@Component({
|
||||
selector: 'app-login-texts',
|
||||
templateUrl: './login-texts.component.html',
|
||||
styleUrls: ['./login-texts.component.scss'],
|
||||
})
|
||||
export class LoginTextsComponent implements OnDestroy {
|
||||
public currentPolicyChangeDate!: Timestamp.AsObject | undefined;
|
||||
public newerPolicyChangeDate!: Timestamp.AsObject | undefined;
|
||||
|
||||
public totalCustomPolicy: { [key: string]: { [key: string]: string; }; } = {};
|
||||
|
||||
public getDefaultInitMessageTextMap$: Observable<{ [key: string]: string; }> = of({});
|
||||
public getCustomInitMessageTextMap$: BehaviorSubject<{ [key: string]: string; }> = new BehaviorSubject({});
|
||||
|
||||
public service!: ManagementService | AdminService;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public KeyNamesArray: string[] = KeyNamesArray;
|
||||
public LOCALES: string[] = ['en'];
|
||||
|
||||
private sub: Subscription = new Subscription();
|
||||
|
||||
public updateRequest!: SetCustomLoginTextsRequest;
|
||||
public currentPolicy: GridPolicy = LOGIN_TEXTS_POLICY;
|
||||
|
||||
public destroy$: Subject<void> = new Subject();
|
||||
|
||||
public form: FormGroup = new FormGroup({
|
||||
currentSubMap: new FormControl('emailVerificationDoneText'),
|
||||
locale: new FormControl('en'),
|
||||
});
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
) {
|
||||
this.sub = this.route.data.pipe(switchMap(data => {
|
||||
this.serviceType = data.serviceType;
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
|
||||
this.service.getSupportedLanguages().then(lang => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
|
||||
this.loadData();
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
|
||||
this.service.getSupportedLanguages().then(lang => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
|
||||
this.loadData();
|
||||
break;
|
||||
}
|
||||
|
||||
return this.route.params;
|
||||
})).subscribe(() => {
|
||||
interval(10000).pipe(
|
||||
// debounceTime(5000),
|
||||
takeUntil(this.destroy$),
|
||||
).subscribe(x => {
|
||||
this.checkForChanges();
|
||||
});
|
||||
});
|
||||
|
||||
this.form.valueChanges.pipe(
|
||||
startWith({ currentSubMap: 'emailVerificationDoneText', locale: 'en' }),
|
||||
pairwise(),
|
||||
takeUntil(this.destroy$),
|
||||
).subscribe(pair => {
|
||||
this.checkForUnsaved(pair[0].currentSubMap).then((wantsToSave) => {
|
||||
if (wantsToSave) {
|
||||
this.saveCurrentMessage().then(() => {
|
||||
this.loadData();
|
||||
}).catch(() => {
|
||||
// load even if save failed
|
||||
this.loadData();
|
||||
});
|
||||
} else {
|
||||
this.loadData();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getDefaultValues(req: any): Promise<any> {
|
||||
return this.service.getDefaultLoginTexts(req).then((res) => {
|
||||
if (res.customText) {
|
||||
// delete res.customText.details;
|
||||
return Object.assign({}, res.customText);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public getCurrentValues(req: any): Promise<any> {
|
||||
return (this.service as ManagementService).getCustomLoginTexts(req).then((res) => {
|
||||
if (res.customText) {
|
||||
this.currentPolicyChangeDate = res.customText.details?.changeDate;
|
||||
// delete res.customText.details;
|
||||
return Object.assign({}, res.customText);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async loadData(): Promise<any> {
|
||||
const reqDefaultInit = REQUESTMAP[this.serviceType].getDefault;
|
||||
reqDefaultInit.setLanguage(this.locale);
|
||||
this.getDefaultInitMessageTextMap$ = from(
|
||||
this.getDefaultValues(reqDefaultInit),
|
||||
).pipe(map(m => m[this.currentSubMap]));
|
||||
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
this.totalCustomPolicy = (await this.getCurrentValues(reqCustomInit));
|
||||
this.getCustomInitMessageTextMap$.next(
|
||||
this.totalCustomPolicy[this.currentSubMap],
|
||||
);
|
||||
}
|
||||
|
||||
private async patchSingleCurrentMap(): Promise<any> {
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
const pol = (await this.getCurrentValues(reqCustomInit));
|
||||
this.getCustomInitMessageTextMap$.next(
|
||||
pol[this.currentSubMap],
|
||||
);
|
||||
}
|
||||
|
||||
public checkForChanges(): void {
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType].get.setLanguage(this.locale);
|
||||
|
||||
(this.service as ManagementService).getCustomLoginTexts(reqCustomInit).then(policy => {
|
||||
this.newerPolicyChangeDate = policy.customText?.details?.changeDate;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param oldkey which was potentially unsaved
|
||||
* @returns a boolean if saving is desired
|
||||
*/
|
||||
public checkForUnsaved(oldkey: string): Promise<boolean> {
|
||||
const old = this.getCustomInitMessageTextMap$.getValue();
|
||||
const unsaved = this.totalCustomPolicy[oldkey];
|
||||
|
||||
if (old && unsaved && JSON.stringify(old) !== JSON.stringify(unsaved)) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.SAVE',
|
||||
cancelKey: 'ACTIONS.CONTINUEWITHOUTSAVE',
|
||||
titleKey: 'POLICY.LOGIN_TEXTS.UNSAVED_TITLE',
|
||||
descriptionKey: 'POLICY.LOGIN_TEXTS.UNSAVED_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
return dialogRef.afterClosed().toPromise();
|
||||
} else {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
public updateCurrentValues(values: { [key: string]: string; }): void {
|
||||
const setFcn = REQUESTMAP[this.serviceType].setFcn;
|
||||
this.totalCustomPolicy[this.currentSubMap] = values;
|
||||
|
||||
this.updateRequest = setFcn(this.totalCustomPolicy);
|
||||
this.updateRequest.setLanguage(this.locale);
|
||||
}
|
||||
|
||||
public saveCurrentMessage(): Promise<any> {
|
||||
const entirePayload = this.updateRequest.toObject();
|
||||
this.getCustomInitMessageTextMap$.next(
|
||||
(entirePayload as any)[this.currentSubMap],
|
||||
);
|
||||
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
return (this.service as ManagementService).setCustomLoginText(this.updateRequest).then(() => {
|
||||
this.toast.showInfo('POLICY.MESSAGE_TEXTS.TOAST.UPDATED', true);
|
||||
setTimeout(() => {
|
||||
this.patchSingleCurrentMap();
|
||||
}, 1000);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
return (this.service as AdminService).setCustomLoginText(this.updateRequest).then(() => {
|
||||
this.toast.showInfo('POLICY.MESSAGE_TEXTS.TOAST.UPDATED', true);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
}
|
||||
}
|
||||
|
||||
public resetDefault(): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
icon: 'las la-history',
|
||||
confirmKey: 'ACTIONS.RESTORE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'POLICY.LOGIN_TEXTS.RESET_TITLE',
|
||||
descriptionKey: 'POLICY.LOGIN_TEXTS.RESET_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
(this.service as ManagementService).resetCustomLoginTextToDefault(this.locale).then(() => {
|
||||
setTimeout(() => {
|
||||
this.loadData();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
(this.service as AdminService).resetCustomLoginTextToDefault(this.locale).then(() => {
|
||||
setTimeout(() => {
|
||||
this.loadData();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.sub.unsubscribe();
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
public get newerVersionExists(): boolean {
|
||||
const toDate = (ts: Timestamp.AsObject) => {
|
||||
return new Date(ts.seconds * 1000 + ts.nanos / 1000 / 1000);
|
||||
};
|
||||
if (this.newerPolicyChangeDate && this.currentPolicyChangeDate) {
|
||||
const ms = toDate(this.newerPolicyChangeDate).getTime() - toDate(this.currentPolicyChangeDate).getTime();
|
||||
// show button if changes are newer than 10s
|
||||
return ms / 1000 > 10;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public get locale(): string {
|
||||
return this.form.get('locale')?.value;
|
||||
}
|
||||
|
||||
public get currentSubMap(): string {
|
||||
return this.form.get('currentSubMap')?.value;
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
import { TextFieldModule } from '@angular/cdk/text-field';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
|
||||
import { HasRoleModule } from '../../../directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from '../../../modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from '../../../modules/input/input.module';
|
||||
import { HasFeaturePipeModule } from '../../../pipes/has-feature-pipe/has-feature-pipe.module';
|
||||
import { HasRolePipeModule } from '../../../pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { EditTextModule } from '../../edit-text/edit-text.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { WarnDialogModule } from '../../warn-dialog/warn-dialog.module';
|
||||
import { LoginTextsRoutingModule } from './login-texts-routing.module';
|
||||
import { LoginTextsComponent } from './login-texts.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginTextsComponent],
|
||||
imports: [
|
||||
LoginTextsRoutingModule,
|
||||
MatSelectModule,
|
||||
CommonModule,
|
||||
InfoSectionModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
FormFieldModule,
|
||||
EditTextModule,
|
||||
MatButtonModule,
|
||||
HasFeaturePipeModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
MatTooltipModule,
|
||||
DetailLayoutModule,
|
||||
MatProgressSpinnerModule,
|
||||
TextFieldModule,
|
||||
MatDialogModule,
|
||||
WarnDialogModule,
|
||||
PolicyGridModule,
|
||||
TimestampToDatePipeModule,
|
||||
LocalizedDatePipeModule,
|
||||
],
|
||||
})
|
||||
export class LoginTextsPolicyModule { }
|
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { MessageTextsComponent } from './message-texts.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: MessageTextsComponent,
|
||||
data: {
|
||||
animation: 'DetailPage',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class MessageTextsRoutingModule { }
|
@@ -0,0 +1,51 @@
|
||||
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
|
||||
[title]="'POLICY.MESSAGE_TEXTS.TITLE' | translate"
|
||||
[description]="'POLICY.MESSAGE_TEXTS.DESCRIPTION' | translate">
|
||||
|
||||
<div class="top-actions">
|
||||
<div class="message-type">
|
||||
<button (click)="setCurrentType(type.value)" [ngClass]="{'active': currentType == type.value}" mat-button *ngFor="let type of MESSAGETYPES | keyvalue">{{'POLICY.MESSAGE_TEXTS.TYPES.'+type.value | translate}}</button>
|
||||
</div>
|
||||
|
||||
<cnsl-form-field class="language">
|
||||
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
|
||||
<mat-select [(ngModel)]="locale" name="locale" (selectionChange)="changeLocale($event)">
|
||||
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
|
||||
<div class="centerline">
|
||||
<span>{{loc}} <span class="lighter">| {{'POLICY.LOGIN_TEXTS.LOCALES.'+loc | translate }}</span></span>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
||||
<cnsl-info-section class="warn"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false"
|
||||
type="WARN">
|
||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'custom_text'})}}
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="content" >
|
||||
<cnsl-edit-text [chips]="chips" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" label="one" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
|
||||
$event)"></cnsl-edit-text>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
|
||||
<button class="save-button" [disabled]="!updateRequest || serviceType == PolicyComponentServiceType.MGMT && (['custom_text'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<ng-container
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false">
|
||||
<cnsl-info-section type="WARN">{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'login_policy.idp'})}}
|
||||
</cnsl-info-section>
|
||||
</ng-container>
|
||||
|
||||
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
|
||||
</app-detail-layout>
|
@@ -0,0 +1,69 @@
|
||||
.spinner-wr {
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.top-actions {
|
||||
display: flex;
|
||||
margin: 0 -.5rem;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
|
||||
.message-type {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 11px;
|
||||
|
||||
.active {
|
||||
background: #cbf4c9;
|
||||
color: #0e6245;
|
||||
}
|
||||
}
|
||||
|
||||
.language {
|
||||
display: block;
|
||||
margin: 0 .5rem;
|
||||
min-width: 150px;
|
||||
|
||||
.lighter {
|
||||
font-size: 12px;
|
||||
color: var(--grey);
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warn {
|
||||
margin-top: 1rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: rgba(var(--grey), .5);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.save-button,
|
||||
.reset-button {
|
||||
display: block;
|
||||
margin: 0 .25rem 3rem .25rem;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
|
||||
describe('LoginPolicyComponent', () => {
|
||||
let component: LoginPolicyComponent;
|
||||
let fixture: ComponentFixture<LoginPolicyComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginPolicyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,461 @@
|
||||
import { Component, Injector, OnDestroy, Type } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import {
|
||||
GetCustomPasswordResetMessageTextRequest as AdminGetCustomPasswordResetMessageTextRequest,
|
||||
GetDefaultInitMessageTextRequest as AdminGetDefaultInitMessageTextRequest,
|
||||
GetDefaultVerifyEmailMessageTextRequest as AdminGetDefaultVerifyEmailMessageTextRequest,
|
||||
GetDefaultVerifyPhoneMessageTextRequest as AdminGetDefaultVerifyPhoneMessageTextRequest,
|
||||
SetDefaultDomainClaimedMessageTextRequest,
|
||||
SetDefaultInitMessageTextRequest,
|
||||
SetDefaultPasswordResetMessageTextRequest,
|
||||
SetDefaultVerifyEmailMessageTextRequest,
|
||||
SetDefaultVerifyPhoneMessageTextRequest,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
GetCustomDomainClaimedMessageTextRequest,
|
||||
GetCustomPasswordResetMessageTextRequest,
|
||||
GetCustomVerifyEmailMessageTextRequest,
|
||||
GetCustomVerifyPhoneMessageTextRequest,
|
||||
GetDefaultDomainClaimedMessageTextRequest,
|
||||
GetDefaultInitMessageTextRequest,
|
||||
GetDefaultPasswordResetMessageTextRequest,
|
||||
GetDefaultVerifyEmailMessageTextRequest,
|
||||
GetDefaultVerifyPhoneMessageTextRequest,
|
||||
SetCustomDomainClaimedMessageTextRequest,
|
||||
SetCustomInitMessageTextRequest,
|
||||
SetCustomPasswordResetMessageTextRequest,
|
||||
SetCustomVerifyEmailMessageTextRequest,
|
||||
SetCustomVerifyPhoneMessageTextRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { MessageCustomText } from 'src/app/proto/generated/zitadel/text_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { GridPolicy, MESSAGE_TEXTS_POLICY } from '../../policy-grid/policies';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
|
||||
enum MESSAGETYPES {
|
||||
INIT = 'INIT',
|
||||
VERIFYPHONE = 'VP',
|
||||
VERIFYEMAIL = 'VE',
|
||||
PASSWORDRESET = 'PR',
|
||||
DOMAINCLAIMED = 'DC',
|
||||
}
|
||||
|
||||
const REQUESTMAP = {
|
||||
[PolicyComponentServiceType.MGMT]: {
|
||||
[MESSAGETYPES.INIT]: {
|
||||
get: new GetDefaultInitMessageTextRequest(),
|
||||
set: new SetCustomInitMessageTextRequest(),
|
||||
getDefault: new GetDefaultInitMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>): SetCustomInitMessageTextRequest => {
|
||||
const req = new SetCustomInitMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.VERIFYEMAIL]: {
|
||||
get: new GetCustomVerifyEmailMessageTextRequest(),
|
||||
set: new SetCustomVerifyEmailMessageTextRequest(),
|
||||
getDefault: new GetDefaultVerifyEmailMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>): SetCustomVerifyEmailMessageTextRequest => {
|
||||
const req = new SetCustomVerifyEmailMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.VERIFYPHONE]: {
|
||||
get: new GetCustomVerifyPhoneMessageTextRequest(),
|
||||
set: new SetCustomVerifyPhoneMessageTextRequest(),
|
||||
getDefault: new GetDefaultVerifyPhoneMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>): SetCustomVerifyPhoneMessageTextRequest => {
|
||||
const req = new SetCustomVerifyPhoneMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.PASSWORDRESET]: {
|
||||
get: new GetCustomPasswordResetMessageTextRequest(),
|
||||
set: new SetCustomPasswordResetMessageTextRequest(),
|
||||
getDefault: new GetDefaultPasswordResetMessageTextRequest(),
|
||||
setFcn: (map: Partial<SetCustomPasswordResetMessageTextRequest.AsObject>):
|
||||
SetCustomPasswordResetMessageTextRequest => {
|
||||
const req = new SetCustomPasswordResetMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.DOMAINCLAIMED]: {
|
||||
get: new GetCustomDomainClaimedMessageTextRequest(),
|
||||
set: new SetCustomDomainClaimedMessageTextRequest(),
|
||||
getDefault: new GetDefaultDomainClaimedMessageTextRequest(),
|
||||
setFcn: (map: Partial<SetCustomDomainClaimedMessageTextRequest.AsObject>):
|
||||
SetCustomDomainClaimedMessageTextRequest => {
|
||||
const req = new SetCustomDomainClaimedMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
},
|
||||
[PolicyComponentServiceType.ADMIN]: {
|
||||
[MESSAGETYPES.INIT]: {
|
||||
get: new AdminGetDefaultInitMessageTextRequest(),
|
||||
set: new SetDefaultInitMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>):
|
||||
SetDefaultInitMessageTextRequest => {
|
||||
const req = new SetDefaultInitMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.VERIFYEMAIL]: {
|
||||
get: new AdminGetDefaultVerifyEmailMessageTextRequest(),
|
||||
set: new SetDefaultVerifyEmailMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>):
|
||||
SetDefaultVerifyEmailMessageTextRequest => {
|
||||
const req = new SetDefaultVerifyEmailMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.VERIFYPHONE]: {
|
||||
get: new AdminGetDefaultVerifyPhoneMessageTextRequest(),
|
||||
set: new SetDefaultVerifyPhoneMessageTextRequest(),
|
||||
setFcn: (map: Partial<MessageCustomText.AsObject>):
|
||||
SetDefaultVerifyPhoneMessageTextRequest => {
|
||||
const req = new SetDefaultVerifyPhoneMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.PASSWORDRESET]: {
|
||||
get: new AdminGetCustomPasswordResetMessageTextRequest(),
|
||||
set: new SetDefaultPasswordResetMessageTextRequest(),
|
||||
setFcn: (map: Partial<SetDefaultPasswordResetMessageTextRequest.AsObject>):
|
||||
SetDefaultPasswordResetMessageTextRequest => {
|
||||
const req = new SetDefaultPasswordResetMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
[MESSAGETYPES.DOMAINCLAIMED]: {
|
||||
get: new GetDefaultDomainClaimedMessageTextRequest(),
|
||||
set: new SetDefaultDomainClaimedMessageTextRequest(),
|
||||
setFcn: (map: Partial<SetDefaultDomainClaimedMessageTextRequest.AsObject>):
|
||||
SetDefaultDomainClaimedMessageTextRequest => {
|
||||
const req = new SetDefaultDomainClaimedMessageTextRequest();
|
||||
req.setButtonText(map.buttonText ?? '');
|
||||
req.setFooterText(map.footerText ?? '');
|
||||
req.setGreeting(map.greeting ?? '');
|
||||
req.setPreHeader(map.preHeader ?? '');
|
||||
req.setSubject(map.subject ?? '');
|
||||
req.setText(map.text ?? '');
|
||||
req.setTitle(map.title ?? '');
|
||||
|
||||
return req;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@Component({
|
||||
selector: 'app-message-texts',
|
||||
templateUrl: './message-texts.component.html',
|
||||
styleUrls: ['./message-texts.component.scss'],
|
||||
})
|
||||
export class MessageTextsComponent implements OnDestroy {
|
||||
public getDefaultInitMessageTextMap$: Observable<{ [key: string]: string; }> = of({});
|
||||
public getCustomInitMessageTextMap$: BehaviorSubject<{ [key: string]: string; }> = new BehaviorSubject({});
|
||||
|
||||
public currentType: MESSAGETYPES = MESSAGETYPES.INIT;
|
||||
|
||||
public service!: ManagementService | AdminService;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public MESSAGETYPES: any = MESSAGETYPES;
|
||||
|
||||
public updateRequest!: SetCustomInitMessageTextRequest | SetDefaultInitMessageTextRequest;
|
||||
|
||||
public chips: any[] = [
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.firstname', value: '{{.FirstName}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.lastname', value: '{{.Lastname}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.code', value: '{{.Code}}' },
|
||||
{ key: 'POLICY.MESSAGE_TEXTS.CHIPS.preferredLoginName', value: '{{.PreferredLoginName}}' },
|
||||
];
|
||||
|
||||
public locale: string = 'en';
|
||||
public LOCALES: string[] = ['en'];
|
||||
private sub: Subscription = new Subscription();
|
||||
public currentPolicy: GridPolicy = MESSAGE_TEXTS_POLICY;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
) {
|
||||
this.sub = this.route.data.pipe(switchMap(data => {
|
||||
this.serviceType = data.serviceType;
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.service.getSupportedLanguages().then(lang => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
this.loadData(this.currentType);
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
this.service.getSupportedLanguages().then(lang => {
|
||||
this.LOCALES = lang.languagesList;
|
||||
});
|
||||
this.loadData(this.currentType);
|
||||
break;
|
||||
}
|
||||
|
||||
return this.route.params;
|
||||
})).subscribe(() => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public getDefaultValues(type: MESSAGETYPES, req: any): Promise<any> {
|
||||
switch (type) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return this.stripDetails((this.service).getDefaultInitMessageText(req));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return this.stripDetails((this.service).getDefaultVerifyPhoneMessageText(req));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return this.stripDetails((this.service).getDefaultVerifyEmailMessageText(req));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return this.stripDetails((this.service).getDefaultPasswordResetMessageText(req));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return this.stripDetails((this.service).getDefaultDomainClaimedMessageText(req));
|
||||
}
|
||||
}
|
||||
|
||||
public getCurrentValues(type: MESSAGETYPES, req: any): Promise<any> | undefined {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
switch (type) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return this.stripDetails((this.service as ManagementService).getCustomInitMessageText(req));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return this.stripDetails((this.service as ManagementService).getCustomVerifyPhoneMessageText(req));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return this.stripDetails((this.service as ManagementService).getCustomVerifyEmailMessageText(req));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return this.stripDetails((this.service as ManagementService).getCustomPasswordResetMessageText(req));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return this.stripDetails((this.service as ManagementService).getCustomDomainClaimedMessageText(req));
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
switch (type) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return this.stripDetails((this.service as AdminService).getCustomInitMessageText(req));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return this.stripDetails((this.service as AdminService).getCustomVerifyPhoneMessageText(req));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return this.stripDetails((this.service as AdminService).getCustomVerifyEmailMessageText(req));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return this.stripDetails((this.service as AdminService).getCustomPasswordResetMessageText(req));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return this.stripDetails((this.service as AdminService).getCustomDomainClaimedMessageText(req));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public changeLocale(selection: MatSelectChange): void {
|
||||
this.locale = selection.value;
|
||||
this.loadData(this.currentType);
|
||||
}
|
||||
|
||||
public async loadData(type: MESSAGETYPES): Promise<any> {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const reqDefaultInit = REQUESTMAP[this.serviceType][type].getDefault;
|
||||
|
||||
reqDefaultInit.setLanguage(this.locale);
|
||||
console.log(this.locale);
|
||||
this.getDefaultInitMessageTextMap$ = from(
|
||||
this.getDefaultValues(type, reqDefaultInit),
|
||||
);
|
||||
}
|
||||
|
||||
const reqCustomInit = REQUESTMAP[this.serviceType][type].get.setLanguage(this.locale);
|
||||
this.getCustomInitMessageTextMap$.next(
|
||||
await this.getCurrentValues(type, reqCustomInit),
|
||||
);
|
||||
}
|
||||
|
||||
public updateCurrentValues(values: { [key: string]: string; }): void {
|
||||
const req = REQUESTMAP[this.serviceType][this.currentType].setFcn;
|
||||
const mappedValues = req(values);
|
||||
this.updateRequest = mappedValues;
|
||||
this.updateRequest.setLanguage(this.locale);
|
||||
}
|
||||
|
||||
public saveCurrentMessage(): any {
|
||||
const handler = (prom: Promise<any>): Promise<any> => {
|
||||
return prom.then(() => {
|
||||
this.toast.showInfo('POLICY.MESSAGE_TEXTS.TOAST.UPDATED', true);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
};
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
switch (this.currentType) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return handler((this.service as ManagementService).setCustomInitMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return handler((this.service as ManagementService).setCustomVerifyPhoneMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return handler((this.service as ManagementService).setCustomVerifyEmailMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return handler((this.service as ManagementService).setCustomPasswordResetMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return handler((this.service as ManagementService).setCustomDomainClaimedMessageCustomText(this.updateRequest));
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
switch (this.currentType) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return handler((this.service as AdminService).setDefaultInitMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return handler((this.service as AdminService).setDefaultVerifyPhoneMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return handler((this.service as AdminService).setDefaultVerifyEmailMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return handler((this.service as AdminService).setDefaultPasswordResetMessageText(this.updateRequest));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return handler((this.service as AdminService).setDefaultDomainClaimedMessageText(this.updateRequest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public resetDefault(): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
icon: 'las la-history',
|
||||
confirmKey: 'ACTIONS.RESTORE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'POLICY.LOGIN_TEXTS.RESET_TITLE',
|
||||
descriptionKey: 'POLICY.LOGIN_TEXTS.RESET_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const handler = (prom: Promise<any>): Promise<any> => {
|
||||
return prom.then(() => {
|
||||
setTimeout(() => {
|
||||
this.loadData(this.currentType);
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
};
|
||||
|
||||
switch (this.currentType) {
|
||||
case MESSAGETYPES.INIT:
|
||||
return handler((this.service as ManagementService).resetCustomInitMessageTextToDefault(this.locale));
|
||||
case MESSAGETYPES.VERIFYPHONE:
|
||||
return handler((this.service as ManagementService).resetCustomVerifyPhoneMessageTextToDefault(this.locale));
|
||||
case MESSAGETYPES.VERIFYEMAIL:
|
||||
return handler((this.service as ManagementService).resetCustomVerifyEmailMessageTextToDefault(this.locale));
|
||||
case MESSAGETYPES.PASSWORDRESET:
|
||||
return handler((this.service as ManagementService).resetCustomPasswordResetMessageTextToDefault(this.locale));
|
||||
case MESSAGETYPES.DOMAINCLAIMED:
|
||||
return handler((this.service as ManagementService).resetCustomDomainClaimedMessageTextToDefault(this.locale));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private stripDetails(prom: Promise<any>): Promise<any> {
|
||||
return prom.then(res => {
|
||||
if (res.customText) {
|
||||
delete res.customText.details;
|
||||
return Object.assign({}, res.customText as unknown as { [key: string]: string; });
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
public ngOnDestroy(): void {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
public setCurrentType(key: MESSAGETYPES): void {
|
||||
this.currentType = key;
|
||||
this.loadData(this.currentType);
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
import { TextFieldModule } from '@angular/cdk/text-field';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { HasFeaturePipeModule } from 'src/app/pipes/has-feature-pipe/has-feature-pipe.module';
|
||||
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
|
||||
|
||||
import { EditTextModule } from '../../edit-text/edit-text.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { MessageTextsRoutingModule } from './message-texts-routing.module';
|
||||
import { MessageTextsComponent } from './message-texts.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [MessageTextsComponent],
|
||||
imports: [
|
||||
MessageTextsRoutingModule,
|
||||
CommonModule,
|
||||
InfoSectionModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
FormFieldModule,
|
||||
EditTextModule,
|
||||
MatButtonModule,
|
||||
HasFeaturePipeModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
MatTooltipModule,
|
||||
MatSelectModule,
|
||||
DetailLayoutModule,
|
||||
MatProgressSpinnerModule,
|
||||
PolicyGridModule,
|
||||
TextFieldModule,
|
||||
],
|
||||
})
|
||||
export class MessageTextsPolicyModule { }
|
@@ -24,5 +24,5 @@
|
||||
}}</button>
|
||||
</div>
|
||||
|
||||
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
||||
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="login"></app-policy-grid>
|
||||
</app-detail-layout>
|
@@ -33,6 +33,7 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
margin-bottom: 50px;
|
||||
|
||||
button {
|
||||
margin-top: 3rem;
|
||||
|
@@ -11,15 +11,7 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CnslLinks } from '../../links/links.component';
|
||||
import {
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
ORG_COMPLEXITY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
} from '../../policy-grid/policy-links';
|
||||
import { GridPolicy, IAM_POLICY } from '../../policy-grid/policies';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
|
||||
@Component({
|
||||
@@ -37,7 +29,8 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
||||
private org!: Org.AsObject;
|
||||
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public nextLinks: Array<CnslLinks> = [];
|
||||
public currentPolicy: GridPolicy = IAM_POLICY;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
@@ -53,17 +46,6 @@ export class OrgIamPolicyComponent implements OnDestroy {
|
||||
this.serviceType = data.serviceType;
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
this.managementService = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.nextLinks = [
|
||||
ORG_COMPLEXITY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
];
|
||||
} else {
|
||||
this.nextLinks = [
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
];
|
||||
}
|
||||
return this.route.params;
|
||||
})).subscribe(_ => {
|
||||
|
@@ -9,28 +9,28 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { LinksModule } from '../../links/links.module';
|
||||
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { OrgIamPolicyRoutingModule } from './org-iam-policy-routing.module';
|
||||
import { OrgIamPolicyComponent } from './org-iam-policy.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [OrgIamPolicyComponent],
|
||||
imports: [
|
||||
OrgIamPolicyRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
MatTooltipModule,
|
||||
InfoSectionModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
LinksModule,
|
||||
],
|
||||
declarations: [OrgIamPolicyComponent],
|
||||
imports: [
|
||||
OrgIamPolicyRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
MatTooltipModule,
|
||||
InfoSectionModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
PolicyGridModule,
|
||||
],
|
||||
})
|
||||
export class OrgIamPolicyModule { }
|
||||
|
@@ -66,5 +66,5 @@
|
||||
}}</button>
|
||||
</div>
|
||||
|
||||
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
||||
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security"></app-policy-grid>
|
||||
</app-detail-layout>
|
@@ -42,6 +42,7 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
margin-bottom: 50px;
|
||||
|
||||
button {
|
||||
margin-top: 3rem;
|
||||
|
@@ -13,15 +13,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CnslLinks } from '../../links/links.component';
|
||||
import {
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
} from '../../policy-grid/policy-links';
|
||||
import { COMPLEXITY_POLICY, GridPolicy } from '../../policy-grid/policies';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
|
||||
@Component({
|
||||
@@ -39,7 +31,8 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
||||
public loading: boolean = false;
|
||||
public nextLinks: CnslLinks[] = [];
|
||||
public currentPolicy: GridPolicy = COMPLEXITY_POLICY;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private toast: ToastService,
|
||||
@@ -51,19 +44,9 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.nextLinks = [
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
ORG_PRIVATELABEL_LINK,
|
||||
];
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
this.nextLinks = [
|
||||
IAM_POLICY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_PRIVATELABEL_LINK,
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -10,27 +10,27 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { LinksModule } from '../../links/links.module';
|
||||
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { PasswordComplexityPolicyRoutingModule } from './password-complexity-policy-routing.module';
|
||||
import { PasswordComplexityPolicyComponent } from './password-complexity-policy.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PasswordComplexityPolicyComponent],
|
||||
imports: [
|
||||
PasswordComplexityPolicyRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
MatProgressSpinnerModule,
|
||||
LinksModule,
|
||||
],
|
||||
declarations: [PasswordComplexityPolicyComponent],
|
||||
imports: [
|
||||
PasswordComplexityPolicyRoutingModule,
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
MatButtonModule,
|
||||
MatSlideToggleModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
DetailLayoutModule,
|
||||
MatProgressSpinnerModule,
|
||||
PolicyGridModule,
|
||||
],
|
||||
})
|
||||
export class PasswordComplexityPolicyModule { }
|
||||
|
@@ -5,7 +5,11 @@ export enum PolicyComponentType {
|
||||
IAM = 'iam',
|
||||
LOGIN = 'login',
|
||||
PRIVATELABEL = 'privatelabel',
|
||||
MESSAGETEXTS = 'messagetexts',
|
||||
LOGINTEXTS = 'logintexts',
|
||||
PRIVACYPOLICY = 'privacypolicy',
|
||||
}
|
||||
|
||||
export enum PolicyComponentServiceType {
|
||||
MGMT = 'mgmt',
|
||||
ADMIN = 'admin',
|
||||
|
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { PrivacyPolicyComponent } from './privacy-policy.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PrivacyPolicyComponent,
|
||||
data: {
|
||||
animation: 'DetailPage',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class PrivacyPolicyRoutingModule { }
|
@@ -0,0 +1,37 @@
|
||||
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
|
||||
[title]="'POLICY.PRIVACY_POLICY.TITLE' | translate"
|
||||
[description]="'POLICY.PRIVACY_POLICY.DESCRIPTION' | translate">
|
||||
|
||||
<cnsl-info-section class="warn"
|
||||
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false"
|
||||
type="WARN">
|
||||
{{'FEATURES.NOTAVAILABLE' | translate: ({value:
|
||||
'privacy_policy'})}}
|
||||
</cnsl-info-section>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="content" >
|
||||
<form *ngIf="form" [formGroup]="form">
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.TOSLINK' | translate }}</cnsl-label>
|
||||
<input cnslInput name="tosLink" formControlName="tosLink" />
|
||||
</cnsl-form-field>
|
||||
|
||||
<cnsl-form-field class="formfield">
|
||||
<cnsl-label>{{ 'POLICY.PRIVACY_POLICY.POLICYLINK' | translate }}</cnsl-label>
|
||||
<input cnslInput name="privacyLink" formControlName="privacyLink" />
|
||||
</cnsl-form-field>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button *ngIf="!privacyPolicy?.isDefault" class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
|
||||
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
|
||||
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
|
||||
|
||||
</app-detail-layout>
|
@@ -0,0 +1,81 @@
|
||||
.spinner-wr {
|
||||
margin: .5rem 0;
|
||||
}
|
||||
|
||||
.top-actions {
|
||||
display: flex;
|
||||
margin: 0 -.5rem;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.keys {
|
||||
flex: 1;
|
||||
margin: 0 .5rem;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.language {
|
||||
margin: 0 .5rem;
|
||||
min-width: 150px;
|
||||
|
||||
.lighter {
|
||||
font-size: 12px;
|
||||
color: var(--grey);
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.centerline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.chips {
|
||||
display: flex;
|
||||
margin: 0 -.25rem;
|
||||
|
||||
.chip {
|
||||
border-radius: 50vw;
|
||||
padding: 2px .5rem;
|
||||
font-size: 12px;
|
||||
background: #cbf4c9;
|
||||
color: #0e6245;
|
||||
margin: .25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: rgba(#81868a, .5);
|
||||
margin: 1.5rem 0 0 0;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 0 -.25rem;
|
||||
|
||||
.save-button,
|
||||
.reset-button {
|
||||
display: block;
|
||||
margin: 0 .25rem 3rem .25rem;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
|
||||
describe('LoginPolicyComponent', () => {
|
||||
let component: LoginPolicyComponent;
|
||||
let fixture: ComponentFixture<LoginPolicyComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginPolicyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,147 @@
|
||||
import { Component, Injector, OnDestroy, Type } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import {
|
||||
GetPrivacyPolicyResponse as AdminGetPrivacyPolicyResponse,
|
||||
UpdatePrivacyPolicyRequest,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
AddCustomPrivacyPolicyRequest,
|
||||
GetPrivacyPolicyResponse,
|
||||
UpdateCustomPrivacyPolicyRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { PrivacyPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CnslLinks } from '../../links/links.component';
|
||||
import { GridPolicy, PRIVACY_POLICY } from '../../policy-grid/policies';
|
||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
|
||||
@Component({
|
||||
selector: 'app-privacy-policy',
|
||||
templateUrl: './privacy-policy.component.html',
|
||||
styleUrls: ['./privacy-policy.component.scss'],
|
||||
})
|
||||
export class PrivacyPolicyComponent implements OnDestroy {
|
||||
public service!: ManagementService | AdminService;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public nextLinks: CnslLinks[] = [];
|
||||
private sub: Subscription = new Subscription();
|
||||
|
||||
public privacyPolicy!: PrivacyPolicy.AsObject;
|
||||
public form!: FormGroup;
|
||||
public currentPolicy: GridPolicy = PRIVACY_POLICY;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private injector: Injector,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
private fb: FormBuilder,
|
||||
) {
|
||||
|
||||
this.form = this.fb.group({
|
||||
tosLink: ['', []],
|
||||
privacyLink: ['', []],
|
||||
});
|
||||
|
||||
this.route.data.pipe(switchMap(data => {
|
||||
this.serviceType = data.serviceType;
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.loadData();
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
this.loadData();
|
||||
break;
|
||||
}
|
||||
|
||||
return this.route.params;
|
||||
})).subscribe();
|
||||
}
|
||||
|
||||
public async loadData(): Promise<any> {
|
||||
const getData = ():
|
||||
Promise<AdminGetPrivacyPolicyResponse.AsObject | GetPrivacyPolicyResponse.AsObject> => {
|
||||
return (this.service as AdminService).getPrivacyPolicy();
|
||||
};
|
||||
|
||||
getData().then(resp => {
|
||||
if (resp.policy) {
|
||||
this.privacyPolicy = resp.policy;
|
||||
this.form.patchValue(this.privacyPolicy);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public saveCurrentMessage(): void {
|
||||
console.log(this.form.get('privacyLink')?.value, this.form.get('tosLink')?.value);
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if ((this.privacyPolicy as PrivacyPolicy.AsObject).isDefault) {
|
||||
const req = new AddCustomPrivacyPolicyRequest();
|
||||
req.setPrivacyLink(this.form.get('privacyLink')?.value);
|
||||
req.setTosLink(this.form.get('tosLink')?.value);
|
||||
(this.service as ManagementService).addCustomPrivacyPolicy(req).then(() => {
|
||||
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
} else {
|
||||
const req = new UpdateCustomPrivacyPolicyRequest();
|
||||
req.setPrivacyLink(this.form.get('privacyLink')?.value);
|
||||
req.setTosLink(this.form.get('tosLink')?.value);
|
||||
(this.service as ManagementService).updateCustomPrivacyPolicy(req).then(() => {
|
||||
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
}
|
||||
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
const req = new UpdatePrivacyPolicyRequest();
|
||||
req.setPrivacyLink(this.form.get('privacyLink')?.value);
|
||||
req.setTosLink(this.form.get('tosLink')?.value);
|
||||
|
||||
(this.service as AdminService).updatePrivacyPolicy(req).then(() => {
|
||||
this.toast.showInfo('POLICY.PRIVACY_POLICY.SAVED', true);
|
||||
}).catch(error => this.toast.showError(error));
|
||||
}
|
||||
}
|
||||
|
||||
public resetDefault(): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
icon: 'las la-history',
|
||||
confirmKey: 'ACTIONS.RESTORE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'POLICY.PRIVACY_POLICY.RESET_TITLE',
|
||||
descriptionKey: 'POLICY.PRIVACY_POLICY.RESET_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
(this.service as ManagementService).resetPrivacyPolicyToDefault().then(() => {
|
||||
setTimeout(() => {
|
||||
this.loadData();
|
||||
}, 1000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
import { TextFieldModule } from '@angular/cdk/text-field';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { HasRoleModule } from '../../../directives/has-role/has-role.module';
|
||||
import { DetailLayoutModule } from '../../../modules/detail-layout/detail-layout.module';
|
||||
import { InputModule } from '../../../modules/input/input.module';
|
||||
import { HasFeaturePipeModule } from '../../../pipes/has-feature-pipe/has-feature-pipe.module';
|
||||
import { HasRolePipeModule } from '../../../pipes/has-role-pipe/has-role-pipe.module';
|
||||
import { FormFieldModule } from '../../form-field/form-field.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { WarnDialogModule } from '../../warn-dialog/warn-dialog.module';
|
||||
import { PrivacyPolicyRoutingModule } from './privacy-policy-routing.module';
|
||||
import { PrivacyPolicyComponent } from './privacy-policy.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [PrivacyPolicyComponent],
|
||||
imports: [
|
||||
PrivacyPolicyRoutingModule,
|
||||
MatSelectModule,
|
||||
CommonModule,
|
||||
InfoSectionModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
InputModule,
|
||||
FormFieldModule,
|
||||
MatButtonModule,
|
||||
HasFeaturePipeModule,
|
||||
MatIconModule,
|
||||
HasRoleModule,
|
||||
HasRolePipeModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
MatTooltipModule,
|
||||
DetailLayoutModule,
|
||||
MatProgressSpinnerModule,
|
||||
TextFieldModule,
|
||||
MatDialogModule,
|
||||
WarnDialogModule,
|
||||
PolicyGridModule,
|
||||
],
|
||||
})
|
||||
export class PrivacyPolicyModule { }
|
@@ -279,5 +279,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
|
||||
<app-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
|
||||
</div>
|
@@ -453,3 +453,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: block;
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
@@ -24,15 +24,7 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { StorageService } from 'src/app/services/storage.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { CnslLinks } from '../../links/links.component';
|
||||
import {
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_POLICY_LINK,
|
||||
ORG_COMPLEXITY_LINK,
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
} from '../../policy-grid/policy-links';
|
||||
import { GridPolicy, PRIVATELABEL_POLICY } from '../../policy-grid/policies';
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
|
||||
export enum Theme {
|
||||
@@ -85,11 +77,6 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
||||
public loading: boolean = false;
|
||||
public nextLinks: CnslLinks[] = [
|
||||
IAM_COMPLEXITY_LINK,
|
||||
IAM_POLICY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
];
|
||||
|
||||
public Theme: any = Theme;
|
||||
public Preview: any = Preview;
|
||||
@@ -99,7 +86,7 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
|
||||
public refreshPreview: EventEmitter<void> = new EventEmitter();
|
||||
public loadingImages: boolean = false;
|
||||
private org!: Org.AsObject;
|
||||
|
||||
public currentPolicy: GridPolicy = PRIVATELABEL_POLICY;
|
||||
constructor(
|
||||
private authService: GrpcAuthService,
|
||||
private route: ActivatedRoute,
|
||||
@@ -121,19 +108,9 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
this.service = this.injector.get(ManagementService as Type<ManagementService>);
|
||||
this.nextLinks = [
|
||||
ORG_IAM_POLICY_LINK,
|
||||
ORG_LOGIN_POLICY_LINK,
|
||||
ORG_COMPLEXITY_LINK,
|
||||
];
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
this.service = this.injector.get(AdminService as Type<AdminService>);
|
||||
this.nextLinks = [
|
||||
IAM_POLICY_LINK,
|
||||
IAM_LOGIN_POLICY_LINK,
|
||||
IAM_COMPLEXITY_LINK,
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@ import { DropzoneModule } from '../../../directives/dropzone/dropzone.module';
|
||||
import { DetailLayoutModule } from '../../detail-layout/detail-layout.module';
|
||||
import { InfoSectionModule } from '../../info-section/info-section.module';
|
||||
import { InputModule } from '../../input/input.module';
|
||||
import { LinksModule } from '../../links/links.module';
|
||||
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
|
||||
import { ColorComponent } from './color/color.component';
|
||||
import { PreviewComponent } from './preview/preview.component';
|
||||
import { PrivateLabelingPolicyRoutingModule } from './private-labeling-policy-routing.module';
|
||||
@@ -45,7 +45,7 @@ import { PrivateLabelingPolicyComponent } from './private-labeling-policy.compon
|
||||
DetailLayoutModule,
|
||||
DropzoneModule,
|
||||
MatProgressSpinnerModule,
|
||||
LinksModule,
|
||||
PolicyGridModule,
|
||||
MatExpansionModule,
|
||||
InfoSectionModule,
|
||||
HasFeaturePipeModule,
|
||||
|
Reference in New Issue
Block a user