Skip to content

Commit

Permalink
[Office upload] Implement cancel confirmation dialog for setup
Browse files Browse the repository at this point in the history
Bug: b/260035590
Change-Id: I78f7217da9664d2a42a77be6d6534d8073ff7407
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4054757
Reviewed-by: Luciano Pacheco <lucmult@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Commit-Queue: Austin Tankiang <austinct@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1076591}
  • Loading branch information
Austin Tankiang authored and Chromium LUCI CQ committed Nov 29, 2022
1 parent 422b5c3 commit fdb2324
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 10 deletions.
1 change: 1 addition & 0 deletions chrome/browser/resources/chromeos/cloud_upload/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ build_webui("build") {
"move_confirmation_page.ts",
"office_pwa_install_page.ts",
"one_drive_upload_page.ts",
"setup_cancel_dialog.ts",
"sign_in_page.ts",
"welcome_page.ts",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import './setup_cancel_dialog.js';

import {assert} from 'chrome://resources/js/assert_ts.js';

import {CANCEL_SETUP_EVENT, NEXT_PAGE_EVENT} from './base_setup_page.js';
import {UserAction} from './cloud_upload.mojom-webui.js';
import {CloudUploadBrowserProxy} from './cloud_upload_browser_proxy.js';
import {OfficePwaInstallPageElement} from './office_pwa_install_page.js';
import {OneDriveUploadPageElement} from './one_drive_upload_page.js';
import type {SetupCancelDialogElement} from './setup_cancel_dialog.js';
import {SignInPageElement} from './sign_in_page.js';
import {WelcomePageElement} from './welcome_page.js';

Expand All @@ -17,6 +20,8 @@ import {WelcomePageElement} from './welcome_page.js';
* individual setup pages and determines which one to show.
*/
export class CloudUploadElement extends HTMLElement {
private proxy = CloudUploadBrowserProxy.getInstance();

/** Resolved once the element's shadow DOM has finished initializing. */
initPromise: Promise<void>;

Expand All @@ -26,12 +31,21 @@ export class CloudUploadElement extends HTMLElement {
/** The current page index into `pages`. */
private currentPageIdx: number = 0;

/** The modal dialog shown to confirm if the user wants to cancel setup. */
private cancelDialog: SetupCancelDialogElement;

/** The names of the files to upload. */
private fileNames: string[] = [];

constructor() {
super();
this.attachShadow({mode: 'open'});
const shadow = this.attachShadow({mode: 'open'});

this.cancelDialog = document.createElement('setup-cancel-dialog');
shadow.appendChild(this.cancelDialog);

document.addEventListener('keydown', this.onKeyDown.bind(this));

this.initPromise = this.init();
}

Expand Down Expand Up @@ -67,10 +81,6 @@ export class CloudUploadElement extends HTMLElement {
this.switchPage(0);
}

get proxy() {
return CloudUploadBrowserProxy.getInstance();
}

$<T extends HTMLElement>(query: string): T {
return this.shadowRoot!.querySelector(query)!;
}
Expand All @@ -89,7 +99,7 @@ export class CloudUploadElement extends HTMLElement {
private switchPage(page: number): void {
this.currentPage?.remove();
this.currentPageIdx = page;
this.shadowRoot?.appendChild(this.currentPage!);
this.shadowRoot!.appendChild(this.currentPage!);
}

/**
Expand All @@ -106,11 +116,26 @@ export class CloudUploadElement extends HTMLElement {
}
}

private onKeyDown(event: KeyboardEvent) {
if (event.key === 'Escape' && !this.cancelDialog.open) {
this.cancelSetup();
// Stop escape from also immediately closing the dialog.
event.stopImmediatePropagation();
event.preventDefault();
}
}

/**
* Invoked when a page fires a `CANCEL_SETUP_EVENT` event.
*/
private cancelSetup(): void {
this.proxy.handler.respondAndClose(UserAction.kCancel);
if (this.currentPage instanceof OneDriveUploadPageElement) {
// No need to show the cancel dialog as setup is finished.
this.proxy.handler.respondAndClose(UserAction.kCancel);
return;
}
this.cancelDialog.show(
() => this.proxy.handler.respondAndClose(UserAction.kCancel));
}

/**
Expand All @@ -123,4 +148,10 @@ export class CloudUploadElement extends HTMLElement {
}
}

declare global {
interface HTMLElementTagNameMap {
'cloud-upload': CloudUploadElement;
}
}

customElements.define('cloud-upload', CloudUploadElement);
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<style>
cr-dialog {
--cr-dialog-width: 448px;
}

cr-dialog [slot=title] {
color: var(--cros-text-color-primary);
/* TODO(austinct): replace once proper font is in cros_typography */
font: var(--cros-display-7-font);
padding: 24px 24px 16px;
}

cr-dialog [slot=body] {
color: var(--cros-text-color-secondary);
font: var(--cros-body-2-font);
padding: 0 24px;
}

cr-dialog [slot=button-container] {
padding: 49px 24px 24px;
}

</style>

<!-- TODO(b/254586358): Use localized strings -->
<cr-dialog>
<div slot="title">Are you sure you want to cancel setup?</div>
<div slot="body">
You won't be able to open files in Microsoft 365 until setup is complete.
</div>
<div slot="button-container">
<cr-button class="cancel-button">Cancel setup</cr-button>
<cr-button class="action-button">Resume setup</cr-button>
</div>
</cr-dialog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';

import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';

import {getTemplate} from './setup_cancel_dialog.html.js';

/**
* The SetupCancelDialogElement represents the confirmation dialog shown when
* the user wants to cancel the setup part way through.
*/
export class SetupCancelDialogElement extends HTMLElement {
private dialog: CrDialogElement;

/** Callback called if the user chooses to cancel the setup. */
private cancelCallback: (() => void)|null = null;

constructor() {
super();

this.attachShadow({mode: 'open'}).innerHTML = getTemplate();
this.dialog = this.$('cr-dialog');
this.$('.action-button')!.addEventListener(
'click', () => this.onResumeButtonClick());
this.$('.cancel-button')!.addEventListener(
'click', () => this.onCancelButtonClick());
}

$<T extends HTMLElement>(query: string): T {
return this.shadowRoot!.querySelector(query)!;
}

get open(): boolean {
return this.dialog.open;
}

show(cancelCallback: () => void): void {
this.cancelCallback = cancelCallback;
this.dialog.showModal();
}

private onResumeButtonClick(): void {
this.dialog.close();
}

private onCancelButtonClick(): void {
this.cancelCallback!();
}
}

declare global {
interface HTMLElementTagNameMap {
'setup-cancel-dialog': SetupCancelDialogElement;
}
}

customElements.define('setup-cancel-dialog', SetupCancelDialogElement);
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ CloudUploadDialog::CloudUploadDialog(mojom::DialogArgsPtr args,

CloudUploadDialog::~CloudUploadDialog() = default;

bool CloudUploadDialog::ShouldCloseDialogOnEscape() const {
// The One Drive setup dialog handles escape in the webui as it needs to
// display a confirmation dialog on cancellation.
return dialog_page_ != mojom::DialogPage::kOneDriveSetup;
}

bool CloudUploadDialog::ShouldShowCloseButton() const {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class CloudUploadDialog : public SystemWebDialogDelegate {
UploadRequestCallback callback,
const mojom::DialogPage dialog_page);
~CloudUploadDialog() override;
bool ShouldCloseDialogOnEscape() const override;
bool ShouldShowCloseButton() const override;
void GetDialogSize(gfx::Size* size) const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {CloudUploadBrowserProxy} from 'chrome://cloud-upload/cloud_upload_browse
import {CloudUploadElement} from 'chrome://cloud-upload/cloud_upload_dialog.js';
import {OfficePwaInstallPageElement} from 'chrome://cloud-upload/office_pwa_install_page.js';
import {OneDriveUploadPageElement} from 'chrome://cloud-upload/one_drive_upload_page.js';
import {SetupCancelDialogElement} from 'chrome://cloud-upload/setup_cancel_dialog.js';
import {SignInPageElement} from 'chrome://cloud-upload/sign_in_page.js';
import {WelcomePageElement} from 'chrome://cloud-upload/welcome_page.js';
import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
Expand Down Expand Up @@ -221,10 +222,10 @@ suite('<cloud-upload>', () => {
});

/**
* Tests that clicking the close button triggers the right `respondAndClose`
* mojo request.
* Tests that clicking the close button on the last page triggers the right
* `respondAndClose` mojo request.
*/
test('Close button', async () => {
test('Close button on last page', async () => {
await setUp({
fileName: 'file.docx',
officePWAInstalled: false,
Expand All @@ -242,4 +243,40 @@ suite('<cloud-upload>', () => {
assertDeepEquals(
[UserAction.kCancel], testProxy.handler.getArgs('respondAndClose'));
});

/**
* Tests that the cancel button should show the cancel dialog on each page
* except the last page.
*/
[1, 2, 3].forEach(
page => test(`Close button on page ${page}`, async () => {
await setUp({officePWAInstalled: false});

// Go to the specified page.
if (page > 1) {
await doWelcomePage();
}
if (page > 2) {
await doPWAInstallPage();
}

// Bring up the cancel dialog and dismiss it.
cloudUploadApp.$('.cancel-button').click();
const cancelDialog =
cloudUploadApp.$<SetupCancelDialogElement>('setup-cancel-dialog')!;
assertTrue(cancelDialog.open);
cancelDialog.$('.action-button').click();
assertFalse(cancelDialog.open);

// Bring up the cancel dialog and cancel setup.
cloudUploadApp.$('.cancel-button').click();
assertTrue(cancelDialog.open);
assertEquals(0, testProxy.handler.getCallCount('respondAndClose'));

cancelDialog.$('.cancel-button').click();
await testProxy.handler.whenCalled('respondAndClose');
assertEquals(1, testProxy.handler.getCallCount('respondAndClose'));
assertDeepEquals(
[UserAction.kCancel], testProxy.handler.getArgs('respondAndClose'));
}));
});

0 comments on commit fdb2324

Please sign in to comment.