From f8268e09e50dbb04049e534c758fc79c927cc479 Mon Sep 17 00:00:00 2001 From: Jeff Daley Date: Wed, 16 Aug 2023 14:14:30 -0400 Subject: [PATCH] Improve share modal UX --- web/app/components/document/modal.hbs | 1 + web/app/components/document/modal.ts | 1 + web/app/components/document/sidebar.hbs | 66 +++++++++------ web/app/components/document/sidebar.ts | 48 ++++++++++- web/mirage/config.ts | 23 +++++ .../acceptance/authenticated/document-test.ts | 84 ++++++++++++++++++- 6 files changed, 194 insertions(+), 29 deletions(-) diff --git a/web/app/components/document/modal.hbs b/web/app/components/document/modal.hbs index c21f29fbf..a5e3c097b 100644 --- a/web/app/components/document/modal.hbs +++ b/web/app/components/document/modal.hbs @@ -1,4 +1,5 @@ <:default as |M|> {{#if M.taskIsRunning}} -
+

Submitting for review...

@@ -668,49 +673,60 @@ {{/if}} {{#if this.docPublishedModalIsShown}} - +
Document published!
-

+

Your doc is now available to everyone in your workspace.
Weʼve notified your approvers and subscribers to this product/area.

- - + {{#unless this.docNumberLookupHasFailed}} + + + {{/unless}}
- - + {{#unless this.docNumberLookupHasFailed}} + + {{/unless}} diff --git a/web/app/components/document/sidebar.ts b/web/app/components/document/sidebar.ts index 33a089d0e..b1a3fda09 100644 --- a/web/app/components/document/sidebar.ts +++ b/web/app/components/document/sidebar.ts @@ -24,12 +24,13 @@ import Ember from "ember"; import htmlElement from "hermes/utils/html-element"; import ConfigService from "hermes/services/config"; import isValidURL from "hermes/utils/is-valid-u-r-l"; +import { HermesDocumentType } from "hermes/types/document-type"; interface DocumentSidebarComponentSignature { Args: { profile: AuthenticatedUser; document: HermesDocument; - docType: string; + docType: HermesDocumentType; deleteDraft: (docId: string) => void; isCollapsed: boolean; toggleCollapsed: () => void; @@ -76,8 +77,14 @@ export default class DocumentSidebarComponent extends Component { + const numberOfTries = 10; + + for (let i = 0; i < numberOfTries; i++) { + if (!this.args.document.docNumber.endsWith("?")) { + return; + } else { + await timeout(Ember.testing ? 0 : 1000); + } + } + + this.docNumberLookupHasFailed = true; + }); + deleteDraft = task(async () => { try { await this.args.deleteDraft(this.docID); diff --git a/web/mirage/config.ts b/web/mirage/config.ts index 315b8ecaf..28a2bdf1d 100644 --- a/web/mirage/config.ts +++ b/web/mirage/config.ts @@ -194,6 +194,29 @@ export default function (mirageConfig) { return new Response(200, {}, matches.models); }); + /** + * Used when publishing a draft for review. + * Updates the document's status and isDraft properties. + * + * TODO: Add docNumber assignment. + */ + this.post("/reviews/:document_id", (schema, request) => { + const document = schema.document.findBy({ + objectID: request.params.document_id, + }); + + if (document) { + document.update({ + status: "In Review", + isDraft: false, + }); + + return new Response(200, {}, document.attrs); + } + + return new Response(404, {}, {}); + }); + /** * Used by the AuthenticatedUserService to add and remove subscriptions. */ diff --git a/web/tests/acceptance/authenticated/document-test.ts b/web/tests/acceptance/authenticated/document-test.ts index 5aa9378c3..bc9378bc9 100644 --- a/web/tests/acceptance/authenticated/document-test.ts +++ b/web/tests/acceptance/authenticated/document-test.ts @@ -5,6 +5,7 @@ import { triggerEvent, visit, waitFor, + waitUntil, } from "@ember/test-helpers"; import { setupApplicationTest } from "ember-qunit"; import { module, test } from "qunit"; @@ -18,7 +19,6 @@ import { } from "hermes/components/document/sidebar"; import { capitalize } from "@ember/string"; import window from "ember-window-mock"; -import sinon from "sinon"; import { TEST_SHORT_LINK_BASE_URL } from "hermes/utils/hermes-urls"; const ADD_RELATED_RESOURCE_BUTTON_SELECTOR = @@ -48,6 +48,21 @@ const READ_ONLY_PRODUCT_AREA_SELECTOR = const READ_ONLY_CONTRIBUTORS_SELECTOR = "[data-test-document-contributors-read-only]"; const READ_ONLY_APPROVERS_SELECTOR = "[data-test-document-approvers-read-only]"; +const SIDEBAR_PUBLISH_FOR_REVIEW_BUTTON_SELECTOR = + "[data-test-sidebar-publish-for-review-button"; +const PUBLISH_FOR_REVIEW_MODAL_SELECTOR = + "[data-test-publish-for-review-modal]"; +const DOCUMENT_MODAL_PRIMARY_BUTTON_SELECTOR = + "[data-test-document-modal-primary-button]"; +const PUBLISHING_FOR_REVIEW_MESSAGE_SELECTOR = + "[data-test-publishing-for-review-message]"; +const DOC_PUBLISHED_MODAL_SELECTOR = "[data-test-doc-published-modal]"; +const SHARE_DOCUMENT_URL_INPUT_SELECTOR = + "[data-test-share-document-url-input]"; +const CONTINUE_TO_DOCUMENT_BUTTON_SELECTOR = + "[data-test-continue-to-document-button]"; +const DOC_PUBLISHED_COPY_URL_BUTTON_SELECTOR = + "[data-test-doc-published-copy-url-button]"; const assertEditingIsDisabled = (assert: Assert) => { assert.dom(EDITABLE_TITLE_SELECTOR).doesNotExist(); @@ -442,4 +457,71 @@ module("Acceptance | authenticated/document", function (hooks) { assertEditingIsDisabled(assert); }); + + test("doc owners can publish their docs for review", async function (this: AuthenticatedDocumentRouteTestContext, assert) { + this.server.create("document", { + objectID: 1, + isDraft: true, + docType: "PRD", + }); + + await visit("/document/1?draft=true"); + + await click(SIDEBAR_PUBLISH_FOR_REVIEW_BUTTON_SELECTOR); + + assert.dom(PUBLISH_FOR_REVIEW_MODAL_SELECTOR).exists(); + + let clickPromise = click(DOCUMENT_MODAL_PRIMARY_BUTTON_SELECTOR); + + await waitFor(PUBLISHING_FOR_REVIEW_MESSAGE_SELECTOR); + assert.dom(PUBLISHING_FOR_REVIEW_MESSAGE_SELECTOR).exists(); + + await clickPromise; + + await waitFor(DOC_PUBLISHED_MODAL_SELECTOR); + assert.dom(DOC_PUBLISHED_MODAL_SELECTOR).exists(); + + assert + .dom(SHARE_DOCUMENT_URL_INPUT_SELECTOR) + .exists() + .hasValue(`${TEST_SHORT_LINK_BASE_URL}/prd/hcp-001`); + + assert.dom(DOC_PUBLISHED_COPY_URL_BUTTON_SELECTOR).hasText("Copy link"); + assert + .dom(CONTINUE_TO_DOCUMENT_BUTTON_SELECTOR) + .hasText("Continue to document") + .hasAttribute("data-test-color", "tertiary"); + + // TODO: Assert that clicking the modal dismisses it. + // Requires @hashicorp/design-system-components 2.9.0+ + // https://github.com/hashicorp/design-system/commit/a6553ea032f70f0167f149589801b72154c3cf75 + }); + + test('the "document published" modal hides the share elements if the docNumber fails to load', async function (this: AuthenticatedDocumentRouteTestContext, assert) { + this.server.create("document", { + objectID: 1, + isDraft: true, + docType: "PRD", + docNumber: "LAB-???", + }); + + await visit("/document/1?draft=true"); + + await click(SIDEBAR_PUBLISH_FOR_REVIEW_BUTTON_SELECTOR); + await click(DOCUMENT_MODAL_PRIMARY_BUTTON_SELECTOR); + + await waitFor(DOC_PUBLISHED_MODAL_SELECTOR); + assert.dom(DOC_PUBLISHED_MODAL_SELECTOR).exists(); + + assert.dom(SHARE_DOCUMENT_URL_INPUT_SELECTOR).doesNotExist(); + assert.dom(DOC_PUBLISHED_COPY_URL_BUTTON_SELECTOR).doesNotExist(); + + assert + .dom(CONTINUE_TO_DOCUMENT_BUTTON_SELECTOR) + .hasAttribute( + "data-test-color", + "primary", + "the Continue button becomes the primary button when the copy link is hidden" + ); + }); });