Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EC-556] refactor cl button #3537

Merged
merged 11 commits into from
Sep 27, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@

<div class="tw-mb-3 tw-flex">
<ng-container *ngIf="!accountCreated">
<bit-submit-button [loading]="form.loading">{{ "createAccount" | i18n }}</bit-submit-button>
<button type="submit" bitButton [loading]="form.loading">
{{ "createAccount" | i18n }}
</button>
<a
bitButton
buttonType="secondary"
Expand All @@ -126,7 +128,7 @@
</a>
</ng-container>
<ng-container *ngIf="accountCreated">
<bit-submit-button [loading]="form.loading">{{ "logIn" | i18n }}</bit-submit-button>
<button type="submit" bitButton [loading]="form.loading">{{ "logIn" | i18n }}</button>
</ng-container>
</div>
<bit-error-summary *ngIf="showErrorSummary" [formGroup]="formGroup"></bit-error-summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ <h2 class="tw-mb-3 tw-text-base tw-font-semibold">{{ "paymentType" | i18n }}</h2
</div>

<div class="tw-flex tw-space-x-2">
<bit-submit-button [loading]="form.loading">{{ "startTrial" | i18n }}</bit-submit-button>
<button type="submit" bitButton [loading]="form.loading">{{ "startTrial" | i18n }}</button>

<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ <h1>{{ "myOrganization" | i18n }}</h1>
<app-avatar data="{{ org.name }}" dynamic="true" size="75" fontSize="35"></app-avatar>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "save" | i18n }}
</bit-submit-button>
</button>
</form>
<ng-container *ngIf="canUseApi">
<div class="secondary-header border-0 mb-0">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ <h1 class="modal-title" id="enrollMasterPasswordResetTitle">
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
</div>
<div class="modal-footer">
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
<button
bitButton
buttonType="secondary"
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/reports/pages/breach-report.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ <h1>{{ "dataBreachReport" | i18n }}</h1>
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "checkBreaches" | i18n }}
</bit-submit-button>
</button>
</form>
<div class="mt-4" *ngIf="!form.loading && checkedUsername">
<p *ngIf="error">{{ "reportError" | i18n }}...</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<h1>{{ "exposedPasswordsReport" | i18n }}</h1>
</div>
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
<bit-submit-button [loading]="loading" (click)="load()">
<button type="submit" bitButton [loading]="loading" (click)="load()">
{{ "checkExposedPasswords" | i18n }}
</bit-submit-button>
</button>
<div class="mt-4" *ngIf="hasLoaded">
<app-callout type="success" title="{{ 'goodNews' | i18n }}" *ngIf="!ciphers.length">
{{ "noExposedPasswords" | i18n }}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/app/settings/change-kdf.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ <h1>{{ "encKeySettings" | i18n }}</h1>
</div>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "changeKdf" | i18n }}
</bit-submit-button>
</button>
</form>
4 changes: 2 additions & 2 deletions apps/web/src/app/settings/change-password.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ <h1>{{ "changeMasterPassword" | i18n }}</h1>
</a>
</div>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "changeMasterPassword" | i18n }}
</bit-submit-button>
</button>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ <h3>
</div>
</div>
<div class="modal-footer">
<bit-submit-button [loading]="loading || form.loading" [disabled]="readOnly">
<button type="submit" bitButton [loading]="loading || form.loading" [disabled]="readOnly">
{{ "save" | i18n }}
</bit-submit-button>
</button>
<button bitButton buttonType="secondary" type="button" data-dismiss="modal">
{{ "cancel" | i18n }}
</button>
Expand Down
6 changes: 3 additions & 3 deletions apps/web/src/app/settings/organization-plans.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ <h2 class="spaced-header mb-4">
<app-callout [type]="'error'">{{ "singleOrgBlockCreateMessage" | i18n }}</app-callout>
</div>
<div class="mt-4">
<bit-submit-button [loading]="form.loading" [disabled]="!formGroup.valid">{{
"submit" | i18n
}}</bit-submit-button>
<button type="submit" bitButton [loading]="form.loading" [disabled]="!formGroup.valid">
{{ "submit" | i18n }}
</button>
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
{{ "cancel" | i18n }}
</button>
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/app/settings/premium.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ <h1>{{ "goPremium" | i18n }}</h1>
"licenseFileDesc" | i18n: "bitwarden_premium_license.json"
}}</small>
</div>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
</form>
</ng-container>
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate *ngIf="!selfHosted">
Expand Down Expand Up @@ -118,7 +118,7 @@ <h2 class="spaced-header mb-4">{{ "paymentInformation" | i18n }}</h2>
</p>
</div>
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
<bit-submit-button [loading]="form.loading">
<button type="submit" bitButton [loading]="form.loading">
{{ "submit" | i18n }}
</bit-submit-button>
</button>
</form>
9 changes: 7 additions & 2 deletions apps/web/src/app/settings/two-factor-setup.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ <h2 class="mt-5 spaced-header">
</div>
<small class="form-text text-muted">{{ "deviceVerificationDesc" | i18n }}</small>
</div>
<bit-submit-button [loading]="form.loading" *ngIf="isDeviceVerificationSectionEnabled">
<button
type="submit"
bitButton
[loading]="form.loading"
*ngIf="isDeviceVerificationSectionEnabled"
>
{{ "save" | i18n }}
</bit-submit-button>
</button>
</div>
</div>
</form>
Expand Down
3 changes: 0 additions & 3 deletions apps/web/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
ButtonModule,
CalloutModule,
FormFieldModule,
SubmitButtonModule,
MenuModule,
IconModule,
} from "@bitwarden/components";
Expand Down Expand Up @@ -44,7 +43,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
SubmitButtonModule,
IconModule,
],
exports: [
Expand All @@ -63,7 +61,6 @@ import "./locales";
ButtonModule,
MenuModule,
FormFieldModule,
SubmitButtonModule,
IconModule,
],
providers: [DatePipe],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,13 @@ <h1>{{ "scim" | i18n }}</h1>
<bit-hint>{{ "scimApiKeyHelperText" | i18n }}</bit-hint>
</bit-form-field>

<bit-submit-button buttonType="primary" [loading]="form.loading" [disabled]="form.loading">
<button
type="submit"
bitButton
buttonType="primary"
[loading]="form.loading"
[disabled]="form.loading"
>
{{ "save" | i18n }}
</bit-submit-button>
</button>
</form>
8 changes: 8 additions & 0 deletions libs/components/src/button/button.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<span class="tw-relative">
<span [ngClass]="{ 'tw-invisible': loading }">
<ng-content></ng-content>
</span>
<span class="tw-absolute tw-inset-0" [ngClass]="{ 'tw-invisible': !loading }">
<i class="bwi bwi-spinner bwi-lg bwi-spin tw-align-baseline" aria-hidden="true"></i>
</span>
</span>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe("Button", () => {
let fixture: ComponentFixture<TestApp>;
let testAppComponent: TestApp;
let buttonDebugElement: DebugElement;
let disabledButtonDebugElement: DebugElement;
let linkDebugElement: DebugElement;

beforeEach(waitForAsync(() => {
Expand All @@ -20,6 +21,7 @@ describe("Button", () => {
fixture = TestBed.createComponent(TestApp);
testAppComponent = fixture.debugElement.componentInstance;
buttonDebugElement = fixture.debugElement.query(By.css("button"));
disabledButtonDebugElement = fixture.debugElement.query(By.css("button#disabled"));
linkDebugElement = fixture.debugElement.query(By.css("a"));
}));

Expand Down Expand Up @@ -60,16 +62,67 @@ describe("Button", () => {
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
});

it("should not be disabled when loading and disabled are false", () => {
testAppComponent.loading = false;
testAppComponent.disabled = false;
fixture.detectChanges();

expect(buttonDebugElement.attributes["loading"]).toBeFalsy();
expect(linkDebugElement.attributes["loading"]).toBeFalsy();
expect(buttonDebugElement.nativeElement.disabled).toBeFalsy();
});

it("should be disabled when disabled is true", () => {
testAppComponent.disabled = true;
fixture.detectChanges();

expect(buttonDebugElement.nativeElement.disabled).toBeTruthy();
// Anchor tags cannot be disabled.
});

it("should be disabled when attribute disabled is true", () => {
expect(disabledButtonDebugElement.nativeElement.disabled).toBeTruthy();
});

it("should be disabled when loading is true", () => {
testAppComponent.loading = true;
fixture.detectChanges();

expect(buttonDebugElement.nativeElement.disabled).toBeTruthy();
});
});

@Component({
selector: "test-app",
template: `
<button type="button" bitButton [buttonType]="buttonType" [block]="block">Button</button>
<a href="#" bitButton [buttonType]="buttonType" [block]="block"> Link </a>
<button
type="button"
bitButton
[buttonType]="buttonType"
[block]="block"
[disabled]="disabled"
[loading]="loading"
>
Button
</button>
<a
href="#"
bitButton
[buttonType]="buttonType"
[block]="block"
[disabled]="disabled"
[loading]="loading"
>
Link
</a>

<button id="disabled" type="button" bitButton disabled>Button</button>
`,
})
class TestApp {
buttonType: string;
block: boolean;
disabled: boolean;
loading: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Input, HostBinding, Directive } from "@angular/core";
import { Input, HostBinding, Component } from "@angular/core";

export type ButtonTypes = "primary" | "secondary" | "danger";

Expand Down Expand Up @@ -38,10 +38,11 @@ const buttonStyles: Record<ButtonTypes, string[]> = {
],
};

@Directive({
@Component({
selector: "button[bitButton], a[bitButton]",
templateUrl: "button.component.html",
})
export class ButtonDirective {
export class ButtonComponent {
@HostBinding("class") get classList() {
return [
"tw-font-semibold",
Expand All @@ -65,6 +66,14 @@ export class ButtonDirective {
.concat(buttonStyles[this.buttonType ?? "secondary"]);
}

@HostBinding("attr.disabled")
get disabledAttr() {
const disabled = this.disabled != null && this.disabled !== false;
return disabled || this.loading ? true : null;
}

@Input() buttonType: ButtonTypes = null;
@Input() block?: boolean;
@Input() loading = false;
@Input() disabled = false;
coroiu marked this conversation as resolved.
Show resolved Hide resolved
}
6 changes: 3 additions & 3 deletions libs/components/src/button/button.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";

import { ButtonDirective } from "./button.directive";
import { ButtonComponent } from "./button.component";

@NgModule({
imports: [CommonModule],
exports: [ButtonDirective],
declarations: [ButtonDirective],
exports: [ButtonComponent],
declarations: [ButtonComponent],
})
export class ButtonModule {}
Loading