Skip to content

Commit

Permalink
Improve "request review" state (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffdaley committed May 17, 2023
1 parent 423ee2b commit 43b1877
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 95 deletions.
47 changes: 28 additions & 19 deletions web/app/components/document/modal.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{! @glint-nocheck - not typesafe yet }}
<Hds::Modal
@color={{@color}}
@onClose={{@close}}
Expand All @@ -22,23 +23,31 @@
/>
{{/if}}
</M.Body>
<M.Footer as |F|>
<Hds::ButtonSet>
<Hds::Button
data-test-document-modal-primary-button
@text={{if this.taskIsRunning @taskButtonLoadingText @taskButtonText}}
@color={{@color}}
@icon={{if this.taskIsRunning "loading" @taskButtonIcon}}
disabled={{or @taskButtonIsDisabled this.taskIsRunning}}
{{on "click" (perform this.task)}}
/>
<Hds::Button
data-test-document-modal-secondary-button
@text="Cancel"
@color="secondary"
disabled={{this.taskIsRunning}}
{{on "click" F.close}}
/>
</Hds::ButtonSet>
</M.Footer>
{{#unless (and @hideFooterWhileSaving this.taskIsRunning)}}
<M.Footer data-test-document-modal-footer as |F|>
<Hds::ButtonSet>
<Hds::Button
data-test-document-modal-primary-button
@text={{if this.taskIsRunning @taskButtonLoadingText @taskButtonText}}
@color={{@color}}
@icon={{if this.taskIsRunning "loading" @taskButtonIcon}}
disabled={{or @taskButtonIsDisabled this.taskIsRunning}}
{{on "click" (perform this.task)}}
/>
{{#if (and this.taskIsRunning @savingMessage)}}
<span class="text-body-100">
{{@savingMessage}}
</span>
{{else}}
<Hds::Button
data-test-document-modal-secondary-button
@text="Cancel"
@color="secondary"
disabled={{this.taskIsRunning}}
{{on "click" F.close}}
/>
{{/if}}
</Hds::ButtonSet>
</M.Footer>
{{/unless}}
</Hds::Modal>
12 changes: 11 additions & 1 deletion web/app/components/document/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ interface DocumentModalComponentSignature {
taskButtonLoadingText: string;
taskButtonIcon?: string;
taskButtonIsDisabled?: boolean;
hideFooterWhileSaving?: boolean;
close: () => void;
task: () => Promise<void>;
};
Blocks: {
default: [taskIsRunning: boolean];
};
}

export default class DocumentModalsArchiveComponent extends Component<DocumentModalComponentSignature> {
export default class DocumentModalComponent extends Component<DocumentModalComponentSignature> {
@tracked taskIsRunning = false;

@tracked protected errorIsShown = false;
Expand Down Expand Up @@ -48,3 +52,9 @@ export default class DocumentModalsArchiveComponent extends Component<DocumentMo
}
});
}

declare module "@glint/environment-ember-loose/registry" {
export default interface Registry {
"Document::Modal": typeof DocumentModalComponent;
}
}
132 changes: 77 additions & 55 deletions web/app/components/document/sidebar.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -507,74 +507,96 @@

{{#if this.requestReviewModalIsActive}}
<Document::Modal
@headerText="Request review?"
@headerText="Request review"
@errorTitle="Error requesting review"
@close={{this.closeRequestReviewModal}}
@task={{perform this.requestReview}}
@taskButtonText="Request review"
@taskButtonLoadingText="Requesting review..."
@taskButtonIcon="test"
@hideFooterWhileSaving={{true}}
@taskButtonIsDisabled={{and
(not this.docTypeCheckboxValue)
@docType.checks.length
}}
>
<:default as |M|>
<p class="mb-4 pr-16 text-body-300 text-color-foreground-primary">
This will publish your document company-wide, and anyone you request
below will receive a notification to review.
</p>
<Hds::Form::Field @layout="vertical" as |F|>
<F.Control>
<Inputs::PeopleSelect
@renderInPlace={{true}}
@selected={{this.approvers}}
@onChange={{this.updateApprovers}}
@disabled={{M.taskIsRunning}}
class="mb-0"
/>
</F.Control>
<F.Label>Add approvers</F.Label>
</Hds::Form::Field>
{{#if @docType.checks.length}}
{{! For now, we only support one check }}
{{#each (take 1 @docType.checks) as |check|}}
<div class="mt-3.5">
<Hds::Form::Checkbox::Field
{{on "change" this.onDocTypeCheckboxChange}}
checked={{this.docTypeCheckboxValue}}
disabled={{M.taskIsRunning}}
required
as |F|
>
<F.Label>
{{check.label}}
</F.Label>
{{#if check.helperText}}
<F.HelperText>
{{check.helperText}}
</F.HelperText>
{{/if}}
</Hds::Form::Checkbox::Field>
{{#if M.taskIsRunning}}
<div class="grid place-items-center pt-1 pb-12">
<div class="text-center">
<FlightIcon @name="loading" @size={{24}} class="mb-5" />
<h2>Submitting for review...</h2>
<p class="text-body-300 mb-2">This usually takes about a minute.</p>
<span
class="block text-[12px] text-color-foreground-faint mb-8"
>We appreciate your patience.</span>
<div class="flex justify-center space-x-2 items-center">
<div class="h-px w-4 bg-color-border-primary"></div>
<FlightIcon
@name="hashicorp"
class="text-color-foreground-faint"
/>
<div class="h-px w-4 bg-color-border-primary"></div>
</div>
</div>
{{#if check.links.length}}
<ul class="list-none pl-6 mt-1.5">
{{#each check.links as |link|}}
<li>
<Hds::Link::Inline
@icon="external-link"
@iconPosition="trailing"
@hrefIsExternal={{true}}
@href={{link.url}}
class="no-underline text-body-100"
>
{{link.text}}
</Hds::Link::Inline>
</li>
{{/each}}
</ul>
{{/if}}
{{/each}}
</div>
{{else}}
<p class="mb-4 pr-16 text-body-300 text-color-foreground-primary">
This will publish your document company-wide, and anyone you request
below will receive a notification to review.
</p>
<Hds::Form::Field @layout="vertical" as |F|>
<F.Control>
<Inputs::PeopleSelect
@renderInPlace={{true}}
@selected={{this.approvers}}
@onChange={{this.updateApprovers}}
@disabled={{M.taskIsRunning}}
class="mb-0"
/>
</F.Control>
<F.Label>Add approvers</F.Label>
</Hds::Form::Field>
{{#if @docType.checks.length}}
{{! For now, we only support one check }}
{{#each (take 1 @docType.checks) as |check|}}
<div class="mt-3.5">
<Hds::Form::Checkbox::Field
{{on "change" this.onDocTypeCheckboxChange}}
checked={{this.docTypeCheckboxValue}}
disabled={{M.taskIsRunning}}
required
as |F|
>
<F.Label>
{{check.label}}
</F.Label>
{{#if check.helperText}}
<F.HelperText>
{{check.helperText}}
</F.HelperText>
{{/if}}
</Hds::Form::Checkbox::Field>
</div>
{{#if check.links.length}}
<ul class="list-none pl-6 mt-1.5">
{{#each check.links as |link|}}
<li>
<Hds::Link::Inline
@icon="external-link"
@iconPosition="trailing"
@hrefIsExternal={{true}}
@href={{link.url}}
class="no-underline text-body-100"
>
{{link.text}}
</Hds::Link::Inline>
</li>
{{/each}}
</ul>
{{/if}}
{{/each}}
{{/if}}
{{/if}}
</:default>
</Document::Modal>
Expand Down
74 changes: 54 additions & 20 deletions web/tests/integration/components/document/modal-test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { module, test } from "qunit";
import { setupRenderingTest } from "ember-qunit";
import { click, find, render, waitFor, waitUntil } from "@ember/test-helpers";
import {
TestContext,
click,
find,
render,
waitFor,
waitUntil,
} from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";
import { assert as emberAssert } from "@ember/debug";

const FACETS = {
one: {},
two: {},
three: {},
four: {},
five: {},
six: {},
seven: {},
eight: {},
nine: {},
ten: {},
eleven: {},
};
interface DocumentModalTestContext extends TestContext {
color?: string;
headerText: string;
errorTitle: string;
bodyText?: string;
taskButtonText: string;
taskButtonLoadingText: string;
taskButtonIcon?: string;
taskButtonIsDisabled?: boolean;
hideFooterWhileSaving?: boolean;
close: () => void;
task: () => Promise<void>;
}

const NOOP = () => {};

Expand All @@ -35,8 +42,8 @@ module("Integration | Component | document/modal", function (hooks) {
});
});

test("it renders correctly", async function (assert) {
await render(hbs`
test("it renders correctly", async function (this: DocumentModalTestContext, assert) {
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@color="critical"
@headerText={{this.headerText}}
Expand Down Expand Up @@ -99,7 +106,7 @@ module("Integration | Component | document/modal", function (hooks) {
});

test("it yields a body block with a taskIsRunning property", async function (assert) {
await render(hbs`
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@color="critical"
@headerText={{this.headerText}}
Expand All @@ -113,6 +120,7 @@ module("Integration | Component | document/modal", function (hooks) {
>
<:default as |modal|>
<div data-test-body-block>
{{! @glint-ignore - blocks not yet typed}}
{{#if modal.taskIsRunning}}
<span>running</span>
{{else}}
Expand All @@ -138,7 +146,7 @@ module("Integration | Component | document/modal", function (hooks) {
});

test("it shows a loading state when the primary task is running", async function (assert) {
await render(hbs`
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@color="critical"
@headerText={{this.headerText}}
Expand Down Expand Up @@ -169,7 +177,7 @@ module("Integration | Component | document/modal", function (hooks) {
});

test("the task button can be disabled by the parent component", async function (assert) {
await render(hbs`
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@color="critical"
@headerText={{this.headerText}}
Expand All @@ -193,7 +201,7 @@ module("Integration | Component | document/modal", function (hooks) {
let count = 0;
this.set("close", () => count++);

await render(hbs`
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@color="critical"
@headerText={{this.headerText}}
Expand All @@ -212,4 +220,30 @@ module("Integration | Component | document/modal", function (hooks) {

assert.equal(count, 1);
});

test("the footer can be hidden while saving", async function (assert) {
await render<DocumentModalTestContext>(hbs`
<Document::Modal
@headerText={{this.headerText}}
@errorTitle={{this.errorTitle}}
@taskButtonText={{this.taskButtonText}}
@taskButtonLoadingText={{this.taskButtonLoadingText}}
@hideFooterWhileSaving={{true}}
@close={{this.close}}
@task={{this.task}}
/>
`);

assert.dom("[data-test-document-modal-footer]").exists();

const clickPromise = click("[data-test-document-modal-primary-button]");

await waitUntil(() => {
return find("[data-test-document-modal-footer]") === null;
});

assert.dom("[data-test-document-modal-footer]").doesNotExist();

await clickPromise;
});
});

0 comments on commit 43b1877

Please sign in to comment.