1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 14:53:33 +00:00

[EC-558] Reflecting async progress on buttons and forms (#3548)

* [EC-556] feat: convert button into component

* [EC-556] feat: implement loading state

* [EC-556] feat: remove loading from submit button

* [EC-556] fix: add missing import

* [EC-556] fix: disabling button using regular attribute

* [EC-556] feat: implement bitFormButton

* [EC-556] feat: use bitFormButton in submit button

* [EC-556] fix: missing import

* [EC-558] chore: rename file to match class name

* [EC-558] feat: allow skipping bitButton on form buttons

* [EC-558]: only show spinner on submit button

* [EC-558] feat: add new bit async directive

* [EC-558] feat: add functionToObservable util

* [EC-558] feat: implement bitAction directive

* [EC-558] refactor: simplify bitSubmit using functionToObservable

* [EC-558] feat: connect bit action with form button

* [EC-558] feat: execute function immediately to allow for form validation

* [EC-558] feat: disable form on loading

* [EC-558] chore: remove duplicate types

* [EC-558] feat: move validation service to common

* [EC-558] feat: add error handling using validation service

* [EC-558] feat: add support for icon button

* [EC-558] fix: icon button hover border styles

* [EC-558] chore: refactor icon button story to show all styles

* [EC-558] fix: better align loading spinner to middle

* [EC-558] fix: simplify try catch

* [EC-558] chore: reorganize async actions

* [EC-558] chore: rename stories

* [EC-558] docs: add documentation

* [EC-558] feat: decouple buttons and form buttons

* [EC-558] chore: rename button like abstraction

* [EC-558] chore: remove null check

* [EC-558] docs: add jsdocs to directives

* [EC-558] fix: switch abs imports to relative

* [EC-558] chore: add async actions module to web shared module

* [EC-558] chore: remove unecessary null check

* [EC-558] chore: apply suggestions from code review

Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>

* [EC-558] fix: whitespaces

* [EC-558] feat: dont disable form by default

* [EC-558] fix: bug where form could be submit during a previous submit

* [EC-558] feat: remove ability to disable form

Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
This commit is contained in:
Andreas Coroiu
2022-10-10 16:04:29 +02:00
committed by GitHub
parent 96c99058c4
commit bb4f063fe7
32 changed files with 955 additions and 65 deletions

View File

@@ -0,0 +1,97 @@
import { Component } from "@angular/core";
import { action } from "@storybook/addon-actions";
import { Meta, moduleMetadata, Story } from "@storybook/angular";
import { delay, of } from "rxjs";
import { ValidationService } from "@bitwarden/common/abstractions/validation.service";
import { ButtonModule } from "../button";
import { IconButtonModule } from "../icon-button";
import { BitActionDirective } from "./bit-action.directive";
const template = `
<button bitButton buttonType="primary" [bitAction]="action" class="tw-mr-2">
Perform action
</button>
<button bitIconButton="bwi-trash" buttonType="danger" [bitAction]="action"></button>`;
@Component({
template,
selector: "app-promise-example",
})
class PromiseExampleComponent {
action = async () => {
await new Promise<void>((resolve, reject) => {
setTimeout(resolve, 2000);
});
};
}
@Component({
template,
selector: "app-observable-example",
})
class ObservableExampleComponent {
action = () => {
return of("fake observable").pipe(delay(2000));
};
}
@Component({
template,
selector: "app-rejected-promise-example",
})
class RejectedPromiseExampleComponent {
action = async () => {
await new Promise<void>((resolve, reject) => {
setTimeout(() => reject(new Error("Simulated error")), 2000);
});
};
}
export default {
title: "Component Library/Async Actions/Standalone",
decorators: [
moduleMetadata({
declarations: [
BitActionDirective,
PromiseExampleComponent,
ObservableExampleComponent,
RejectedPromiseExampleComponent,
],
imports: [ButtonModule, IconButtonModule],
providers: [
{
provide: ValidationService,
useValue: {
showError: action("ValidationService.showError"),
} as Partial<ValidationService>,
},
],
}),
],
} as Meta;
const PromiseTemplate: Story<PromiseExampleComponent> = (args: PromiseExampleComponent) => ({
props: args,
template: `<app-promise-example></app-promise-example>`,
});
export const UsingPromise = PromiseTemplate.bind({});
const ObservableTemplate: Story<ObservableExampleComponent> = (
args: ObservableExampleComponent
) => ({
template: `<app-observable-example></app-observable-example>`,
});
export const UsingObservable = ObservableTemplate.bind({});
const RejectedPromiseTemplate: Story<ObservableExampleComponent> = (
args: ObservableExampleComponent
) => ({
template: `<app-rejected-promise-example></app-rejected-promise-example>`,
});
export const RejectedPromise = RejectedPromiseTemplate.bind({});