feat(console): add new step to activate SMTP provider (#7956)

# Which Problems Are Solved

- In #7929 it was detected that it would be better to show the
activate/deactivate action for a SMTP configuration in the wizard as for
some users it'd not be intuitive that the SMTP provider must be
activated so Zitadel can use it to send notifications.

# How the Problems Are Solved

- When a new SMTP provider is added or updated, the wizard has a new
step that allow us to activate or deactivate the provider configured in
the previous step. The following video shows the new wizard:


https://github.com/zitadel/zitadel/assets/30386061/178234d6-73dc-4719-af0b-1d6f19bf3f7d

# Additional Context

- Closes #7929
This commit is contained in:
Miguel Cabrerizo
2024-05-22 11:23:35 +02:00
committed by GitHub
parent 5b1160de1e
commit cca342187b
20 changed files with 350 additions and 37 deletions
@@ -2,7 +2,7 @@
title="{{
id ? ('SMTP.DETAIL.TITLE' | translate) : ('SMTP.CREATE.STEPS.TITLE' | translate: { value: providerDefaultSetting.name })
}}"
[createSteps]="2"
[createSteps]="3"
[currentCreateStep]="currentCreateStep"
(closed)="close()"
>
@@ -133,7 +133,7 @@
class="create-button"
color="primary"
data-e2e="create-button"
(click)="savePolicy()"
(click)="savePolicy(stepper)"
[disabled]="
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
"
@@ -143,6 +143,82 @@
</div>
</mat-step>
<mat-step [editable]="true">
<form>
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.NEXT_STEPS' | translate }}</ng-template>
<cnsl-info-section *ngIf="!isActive">
<div class="title-row">
<div class="left">
<h2 class="title">{{ 'SMTP.CREATE.STEPS.ACTIVATE.TITLE' | translate }}</h2>
<div>
<a
mat-icon-button
card-actions
mat-icon-button
href="https://zitadel.com/docs/guides/manage/console/default-settings#smtp"
rel="noreferrer"
target="_blank"
>
<mat-icon class="next-icon">info_outline</mat-icon>
</a>
</div>
</div>
<div class="right">
<button
color="primary"
mat-raised-button
class="continue-button"
data-e2e="activate-button"
(click)="activateSMTPConfig(); $event.stopPropagation()"
>
{{ 'ACTIONS.ACTIVATE' | translate }}
</button>
</div>
</div>
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.ACTIVATE.DESCRIPTION' | translate }}</p>
</cnsl-info-section>
<cnsl-info-section *ngIf="isActive">
<div class="title-row">
<div class="left">
<h2 class="title">{{ 'SMTP.CREATE.STEPS.DEACTIVATE.TITLE' | translate }}</h2>
<div>
<a
mat-icon-button
card-actions
mat-icon-button
href="https://zitadel.com/docs/guides/manage/console/default-settings#smtp"
rel="noreferrer"
target="_blank"
>
<mat-icon class="next-icon">info_outline</mat-icon>
</a>
</div>
</div>
<div class="right">
<button
color="primary"
mat-raised-button
class="continue-button"
data-e2e="deactivate-button"
(click)="deactivateSMTPConfig(); $event.stopPropagation()"
>
{{ 'ACTIONS.DEACTIVATE' | translate }}
</button>
</div>
</div>
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.DEACTIVATE.DESCRIPTION' | translate }}</p>
</cnsl-info-section>
<div class="smtp-create-actions">
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
<button mat-raised-button class="create-button" color="primary" data-e2e="close-button" (click)="this.close()">
{{ 'ACTIONS.CLOSE' | translate }}
</button>
</div>
</form>
</mat-step>
<ng-template matStepperIcon="edit">
<mat-icon>check</mat-icon>
</ng-template>
@@ -31,6 +31,8 @@ import {
OutlookDefaultSettings,
SendgridDefaultSettings,
} from './known-smtp-providers-settings';
import { MatStepper } from '@angular/material/stepper';
import { SMTPConfigState } from 'src/app/proto/generated/zitadel/settings_pb';
@Component({
selector: 'cnsl-smtp-provider',
@@ -48,7 +50,7 @@ export class SMTPProviderComponent {
public smtpLoading: boolean = false;
public hasSMTPConfig: boolean = false;
public isActive: boolean = false;
public updateClientSecret: boolean = false;
// stepper
@@ -166,6 +168,7 @@ export class SMTPProviderComponent {
.then((data) => {
this.smtpLoading = false;
if (data.smtpConfig) {
this.isActive = data.smtpConfig.state === SMTPConfigState.SMTP_CONFIG_ACTIVE;
this.hasSMTPConfig = true;
this.firstFormGroup.patchValue({
['description']: data.smtpConfig.description,
@@ -188,7 +191,7 @@ export class SMTPProviderComponent {
});
}
private updateData(): Promise<UpdateSMTPConfigResponse.AsObject | AddSMTPConfigResponse> {
private updateData(): Promise<UpdateSMTPConfigResponse.AsObject | AddSMTPConfigResponse.AsObject> {
if (this.hasSMTPConfig) {
const req = new UpdateSMTPConfigRequest();
req.setId(this.id);
@@ -228,19 +231,49 @@ export class SMTPProviderComponent {
}
}
public savePolicy(): void {
this.updateData()
public activateSMTPConfig() {
this.service
.activateSMTPConfig(this.id)
.then(() => {
this.toast.showInfo('SMTP.LIST.DIALOG.ACTIVATED', true);
this.isActive = true;
})
.catch((error) => {
this.toast.showError(error);
});
}
public deactivateSMTPConfig() {
this.service
.deactivateSMTPConfig(this.id)
.then(() => {
this.toast.showInfo('SMTP.LIST.DIALOG.DEACTIVATED', true);
this.isActive = false;
})
.catch((error) => {
this.toast.showError(error);
});
}
public savePolicy(stepper: MatStepper): void {
this.updateData()
.then((resp) => {
if (!this.id) {
// This is a new SMTP provider let's get the ID from the addSMTPConfig response
let createResponse = resp as AddSMTPConfigResponse.AsObject;
this.id = createResponse.id;
}
this.toast.showInfo('SETTING.SMTP.SAVED', true);
setTimeout(() => {
this.close();
stepper.next();
}, 2000);
})
.catch((error: unknown) => {
if (`${error}`.includes('No changes')) {
this.toast.showInfo('SETTING.SMTP.NOCHANGES', true);
setTimeout(() => {
this.close();
stepper.next();
}, 2000);
} else {
this.toast.showError(error);
@@ -68,4 +68,32 @@
font-size: 14px;
}
}
.title-row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
.left {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.right {
flex-shrink: 0;
}
.title {
margin: 1.2rem 0;
}
.next-icon {
font-size: 1.2rem;
height: 1.2rem;
width: 1.2rem;
}
}
}