mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[ACS-3742] Layout changes for workspace (#2980)
* Layout changes for workspace sidemenu * added header and search layout changes * implemented review comments and removed process related code * Added expand and collapse functionality * Modified the paths * linting fixes * use standard material settings icon * use only specific modules needed for page layout * use standard "menu" icon for now * use standard avatar icon for now * cleanup user profile menu item * cleanup About component layout * remove hardcoded settings route * deprecate "headerImagePath" * deprecate "headerTextColor" customisation * deprecate "headerColor" customisation * proper toggle of the side menu * proper sidebar header implementation * user profile basic cleanup * minor fixes * cleanup buttons * remove old app layout and use ADF one * remove old header component * cleanup old layout module * fix unit tests * cleanup unit tests * cleanup header actions module * deprecate unused main-action component * cleanup styles * restore removed method * cleanup search results toolbar * restore expand menu functionality * cleanup code, back buttons for about and profile * restore original code * proper collapse button * remove unused i18n key * styles cleanup * cleanup sidebar * cleanup user profile * add safety checks for focus after close * layout fixes * update view profile unit tests * code cleanup after reviews * cleanup header actions * fix menu population, user info * improved upload and create actions * remove useless tests * fix folder rules tests * search button workaround * e2e: remove wait * add create/upload tooltips * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * e2e fix * try fix e2e * update e2e extension configs * try fix e2e * try fix e2e * fix eslint config * try fix e2e * move search button to extensions * move upload and create to extensions * remove header actions as no longer needed * cleanup * e2e fixes and cleanup for unwanted files * linting fixes * linting fixes * added button type to support text buttons * linting fixes * added more unit tests to achieve code coverage requirement * fixing code covergae for aca-content * fixed code coverage for aca-shared * linting fixes * linting fixes * cleanup * version fix --------- Co-authored-by: SheenaMalhotra182 <sheena.malhotra@globallogic.com> Co-authored-by: Denys Vuika <denys.vuika@gmail.com> Co-authored-by: SheenaMalhotra182 <sheena.malhotra@contractors.onbase.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
|
||||
export * from './login/login';
|
||||
export * from './header/header';
|
||||
export * from './pageLayoutHeader/pageLayoutHeader';
|
||||
export * from './header/user-info';
|
||||
export * from './data-table/data-table';
|
||||
export * from './dialog/confirm-dialog';
|
||||
|
@@ -34,7 +34,7 @@ import { BrowserActions } from '@alfresco/adf-testing';
|
||||
export class Header extends Component {
|
||||
logoLink = this.byCss('.app-menu__title');
|
||||
moreActions = browser.element(by.id('app.header.more'));
|
||||
sidenavToggle = this.byCss(`[id='adf-sidebar-toggle-start']`);
|
||||
sidenavToggle = this.byCss(`.sidenav-header-title-logo`);
|
||||
|
||||
userInfo = new UserInfo();
|
||||
menu = new Menu();
|
||||
@@ -42,7 +42,7 @@ export class Header extends Component {
|
||||
searchInput = new SearchInput();
|
||||
|
||||
constructor(ancestor?: string) {
|
||||
super('adf-layout-header', ancestor);
|
||||
super('app-sidenav-header', ancestor);
|
||||
}
|
||||
|
||||
async openMoreMenu(): Promise<void> {
|
||||
|
@@ -0,0 +1,76 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { by, browser } from 'protractor';
|
||||
import { Component } from '../component';
|
||||
import { Menu } from '../menu/menu';
|
||||
import { Toolbar } from '../toolbar/toolbar';
|
||||
import { SearchInput } from '../search/search-input';
|
||||
import { waitElement } from '../../utilities/utils';
|
||||
import { BrowserActions } from '@alfresco/adf-testing';
|
||||
|
||||
export class PageLayoutHeader extends Component {
|
||||
logoLink = this.byCss('.app-menu__title');
|
||||
moreActions = browser.element(by.id('app.header.more'));
|
||||
sidenavToggle = this.byCss(`.sidenav-header-title-logo`);
|
||||
|
||||
menu = new Menu();
|
||||
toolbar = new Toolbar();
|
||||
searchInput = new SearchInput();
|
||||
|
||||
constructor(ancestor?: string) {
|
||||
super('aca-page-layout', ancestor);
|
||||
}
|
||||
|
||||
async openMoreMenu(): Promise<void> {
|
||||
await BrowserActions.click(this.moreActions);
|
||||
await this.menu.waitForMenuToOpen();
|
||||
}
|
||||
|
||||
async closeMoreMenu(): Promise<void> {
|
||||
await BrowserActions.click(this.moreActions);
|
||||
await this.menu.waitForMenuToClose();
|
||||
}
|
||||
|
||||
async isSidenavExpanded(): Promise<boolean> {
|
||||
return browser.isElementPresent(by.css(`[data-automation-id='expanded']`));
|
||||
}
|
||||
|
||||
async expandSideNav(): Promise<void> {
|
||||
const expanded = await this.isSidenavExpanded();
|
||||
if (!expanded) {
|
||||
await BrowserActions.click(this.sidenavToggle);
|
||||
await waitElement(`[data-automation-id='expanded']`);
|
||||
}
|
||||
}
|
||||
|
||||
async collapseSideNav(): Promise<void> {
|
||||
const expanded = await this.isSidenavExpanded();
|
||||
if (expanded) {
|
||||
await BrowserActions.click(this.sidenavToggle);
|
||||
await waitElement(`[data-automation-id='collapsed']`);
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,7 +28,10 @@ import { waitForPresence, waitElement } from '../../utilities/utils';
|
||||
import { BrowserActions, BrowserVisibility, TestElement } from '@alfresco/adf-testing';
|
||||
|
||||
export class SearchInput extends Component {
|
||||
searchButton = this.component.element(by.css('.app-search-button'));
|
||||
get searchButton() {
|
||||
return browser.element(by.css('.app-search-button'));
|
||||
}
|
||||
|
||||
searchContainer = browser.element(by.css('.app-search-container'));
|
||||
searchControl = browser.element(by.css('.app-search-control'));
|
||||
|
||||
@@ -58,6 +61,7 @@ export class SearchInput extends Component {
|
||||
|
||||
async clickSearchButton() {
|
||||
await BrowserActions.click(this.searchButton);
|
||||
|
||||
await this.waitForSearchControl();
|
||||
}
|
||||
|
||||
@@ -151,28 +155,33 @@ export class SearchInput extends Component {
|
||||
await this.clickLibrariesOption();
|
||||
}
|
||||
|
||||
async searchForLibrary(text: string) {
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.searchInput.elementFinder);
|
||||
await this.searchInput.typeText(text);
|
||||
}
|
||||
|
||||
async searchFor(text: string) {
|
||||
await BrowserVisibility.waitUntilElementIsClickable(this.searchInput.elementFinder);
|
||||
await this.searchInput.typeText(text);
|
||||
await BrowserActions.click(this.searchButton);
|
||||
}
|
||||
|
||||
async searchByURL(text: string){
|
||||
async searchByURL(text: string) {
|
||||
const query = Buffer.from(text, 'utf-8').toString();
|
||||
await BrowserActions.getUrl(`#/search;q=${query}`);
|
||||
}
|
||||
|
||||
async searchUntilResult(text: string, methodType: 'URL' | 'UI', waitPerSearch: number = 2000, timeout: number = 20000) {
|
||||
const attempts = Math.round(timeout/waitPerSearch);
|
||||
const attempts = Math.round(timeout / waitPerSearch);
|
||||
let loopCount = 0;
|
||||
let myPromise = new Promise((resolve, reject) => {
|
||||
const check = async () => {
|
||||
loopCount++;
|
||||
loopCount >= attempts ? reject('File not found') : methodType === 'UI' ? await this.searchFor(text) : await this.searchByURL(text);
|
||||
await this.searchResult.isPresent(waitPerSearch) ? resolve('File found') : setTimeout(check, waitPerSearch);
|
||||
}
|
||||
loopCount++;
|
||||
loopCount >= attempts ? reject('File not found') : methodType === 'UI' ? await this.searchFor(text) : await this.searchByURL(text);
|
||||
(await this.searchResult.isPresent(waitPerSearch)) ? resolve('File found') : setTimeout(check, waitPerSearch);
|
||||
};
|
||||
return check();
|
||||
});
|
||||
return myPromise;
|
||||
});
|
||||
return myPromise;
|
||||
}
|
||||
}
|
||||
|
@@ -22,16 +22,16 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ElementFinder, by, element, browser } from 'protractor';
|
||||
import { ElementFinder, by, element, browser, By } from 'protractor';
|
||||
import { Logger, BrowserActions } from '@alfresco/adf-testing';
|
||||
import { SIDEBAR_LABELS, BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||
import { Menu } from '../menu/menu';
|
||||
import { Component } from '../component';
|
||||
import { waitElement } from '../../utilities';
|
||||
|
||||
export class Sidenav extends Component {
|
||||
links = this.component.all(by.css('.item'));
|
||||
activeLink = this.byCss('.action-button--active');
|
||||
newButton = this.allByCss('[data-automation-id="create-button"]');
|
||||
newButton = element(By.css('[id="app.toolbar.create"]'));
|
||||
personalFiles = this.byCss(`[data-automation-id='app.navbar.personalFiles']`);
|
||||
fileLibraries = this.byCss(`[data-automation-id='app.navbar.libraries.menu']`);
|
||||
myLibraries = this.byCss(`[data-automation-id='app.navbar.libraries.files']`, browser);
|
||||
@@ -40,6 +40,7 @@ export class Sidenav extends Component {
|
||||
recentFiles = this.byCss(`[data-automation-id='app.navbar.recentFiles']`);
|
||||
favorites = this.byCss(`[data-automation-id='app.navbar.favorites']`);
|
||||
trash = this.byCss(`[data-automation-id='app.navbar.trashcan']`);
|
||||
sidenavToggle = this.byCss(`.sidenav-header-title-logo`);
|
||||
|
||||
menu: Menu = new Menu();
|
||||
|
||||
@@ -47,27 +48,33 @@ export class Sidenav extends Component {
|
||||
super('app-sidenav', ancestor);
|
||||
}
|
||||
|
||||
private async expandMenu(name: string): Promise<void> {
|
||||
try {
|
||||
if (await element(by.cssContainingText('.mat-expanded', name)).isPresent()) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
const link = this.getLink(name);
|
||||
await BrowserActions.click(link);
|
||||
await element(by.css('.mat-expansion-panel-body')).isPresent();
|
||||
}
|
||||
} catch (e) {
|
||||
Logger.error(`---- sidebar navigation catch expandMenu: failed to expand ${name} menu : `, e);
|
||||
async isSidenavExpanded(): Promise<boolean> {
|
||||
return browser.isElementPresent(by.css(`[data-automation-id='expanded']`));
|
||||
}
|
||||
|
||||
async expandSideNav(): Promise<void> {
|
||||
const expanded = await this.isSidenavExpanded();
|
||||
if (!expanded) {
|
||||
await BrowserActions.click(this.sidenavToggle);
|
||||
await waitElement(`[data-automation-id='expanded']`);
|
||||
}
|
||||
}
|
||||
|
||||
async collapseSideNav(): Promise<void> {
|
||||
const expanded = await this.isSidenavExpanded();
|
||||
if (expanded) {
|
||||
await BrowserActions.click(this.sidenavToggle);
|
||||
await waitElement(`[data-automation-id='collapsed']`);
|
||||
}
|
||||
}
|
||||
|
||||
async openNewMenu(): Promise<void> {
|
||||
await BrowserActions.click(this.newButton.first());
|
||||
await BrowserActions.click(this.newButton);
|
||||
await this.menu.waitForMenuToOpen();
|
||||
}
|
||||
|
||||
async closeNewMenu(): Promise<void> {
|
||||
await BrowserActions.click(element(by.css('button[data-automation-id="create-button"] span span')));
|
||||
await BrowserActions.click(element(by.css('button[id="app.toolbar.create"] span span')));
|
||||
await this.menu.waitForMenuToClose();
|
||||
}
|
||||
|
||||
@@ -130,11 +137,6 @@ export class Sidenav extends Component {
|
||||
|
||||
async getLinkTooltip(name: string): Promise<string> {
|
||||
const link = this.getLinkLabel(name);
|
||||
const condition = () => link.getAttribute('title').then((value) => value && value.length > 0);
|
||||
|
||||
await browser.actions().mouseMove(link).perform();
|
||||
await browser.wait(condition, BROWSER_WAIT_TIMEOUT);
|
||||
|
||||
return link.getAttribute('title');
|
||||
}
|
||||
|
||||
@@ -146,12 +148,4 @@ export class Sidenav extends Component {
|
||||
Logger.error(`---- clickLink catch : sidebar navigation failed to click on - ${name} : `, error);
|
||||
}
|
||||
}
|
||||
|
||||
async isFileLibrariesMenuExpanded(): Promise<boolean> {
|
||||
return element(by.cssContainingText('.mat-expanded', SIDEBAR_LABELS.FILE_LIBRARIES)).isPresent();
|
||||
}
|
||||
|
||||
async expandFileLibraries(): Promise<void> {
|
||||
await this.expandMenu(SIDEBAR_LABELS.FILE_LIBRARIES);
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ElementFinder, by, browser } from 'protractor';
|
||||
import { ElementFinder, by, browser, By, element } from 'protractor';
|
||||
import { BrowserActions } from '@alfresco/adf-testing';
|
||||
import { Menu } from '../menu/menu';
|
||||
import { Component } from '../component';
|
||||
@@ -32,17 +32,20 @@ export class Toolbar extends Component {
|
||||
menu = new Menu();
|
||||
|
||||
buttons = this.allByCss('button');
|
||||
shareButton = this.byId('share-action-button');
|
||||
viewButton = this.byCss(`.mat-icon-button[title='View']`);
|
||||
downloadButton = this.byCss(`.mat-icon-button[title='Download']`);
|
||||
editFolderButton = this.byId('app.toolbar.editFolder');
|
||||
viewDetailsButton = this.byCss(`.mat-icon-button[title='View Details']`);
|
||||
printButton = this.byCss(`.mat-icon-button[title='Print']`);
|
||||
fullScreenButton = this.byCss(`.mat-icon-button[title='Activate full-screen mode']`);
|
||||
joinButton = this.byCss(`.mat-icon-button[title='Join']`);
|
||||
leaveButton = this.byCss(`.mat-icon-button[title='Leave Library']`);
|
||||
permanentlyDeleteButton = this.byCss(`.mat-icon-button[title='Permanently Delete']`);
|
||||
restoreButton = this.byCss(`.mat-icon-button[title='Restore']`);
|
||||
createButton = element(By.css('[id="app.toolbar.create"]'));
|
||||
uploadButton = element(By.css('[id="app.toolbar.upload"]'));
|
||||
shareButton = element(By.css('button[data-automation-id="share-action-button"]'));
|
||||
viewButton = element(By.css(`button[title='View']`));
|
||||
downloadButton = element(By.css(`.mat-icon-button[title='Download']`));
|
||||
viewDetailsButton = element(By.css(`button[title='View Details']`));
|
||||
printButton = element(By.css(`button[title='Print']`));
|
||||
fullScreenButton = element(By.css(`button[title='Activate full-screen mode']`));
|
||||
joinButton = element(By.css(`button[title='Join']`));
|
||||
leaveButton = element(By.css(`button[title='Leave Library']`));
|
||||
permanentlyDeleteButton = element(By.css(`button[title='Permanently Delete']`));
|
||||
restoreButton = element(By.css(`button[title='Restore']`));
|
||||
searchIconButton = element(By.css(`button[title='Search']`));
|
||||
viewerDownloadButton = element(By.css('[id="app.viewer.download"]'));
|
||||
|
||||
constructor(ancestor?: string) {
|
||||
super('.adf-toolbar', ancestor);
|
||||
@@ -72,11 +75,23 @@ export class Toolbar extends Component {
|
||||
return this.component.element(by.id(id));
|
||||
}
|
||||
|
||||
async openMoreMenu(): Promise<void> {
|
||||
await this.isButtonPresent('More Actions');
|
||||
async clickSearchIconButton() {
|
||||
await BrowserActions.click(this.searchIconButton);
|
||||
}
|
||||
|
||||
const moreMenu = this.getButtonByTitleAttribute('More Actions');
|
||||
await BrowserActions.click(moreMenu);
|
||||
async openViewerMoreMenu(): Promise<void> {
|
||||
const btnMoreActions = element(By.css('button[id="app.viewer.toolbar.more"]'));
|
||||
await btnMoreActions.isPresent();
|
||||
await BrowserActions.click(btnMoreActions);
|
||||
|
||||
await this.menu.waitForMenuToOpen();
|
||||
await browser.sleep(500);
|
||||
}
|
||||
|
||||
async openMoreMenu(): Promise<void> {
|
||||
const btnMoreActions = element(By.css('button[id="app.toolbar.more"]'));
|
||||
await btnMoreActions.isPresent();
|
||||
await BrowserActions.click(btnMoreActions);
|
||||
|
||||
await this.menu.waitForMenuToOpen();
|
||||
await browser.sleep(500);
|
||||
@@ -98,6 +113,46 @@ export class Toolbar extends Component {
|
||||
return browser.isElementPresent(this.printButton);
|
||||
}
|
||||
|
||||
async openCreateFolderDialog(): Promise<void> {
|
||||
await this.openCreateMenu();
|
||||
await BrowserActions.click(this.menu.createFolderAction);
|
||||
}
|
||||
|
||||
async openCreateLibraryDialog(): Promise<void> {
|
||||
await this.openCreateMenu();
|
||||
await BrowserActions.click(this.menu.createLibraryAction);
|
||||
}
|
||||
|
||||
async openCreateFileFromTemplateDialog(): Promise<void> {
|
||||
await this.openCreateMenu();
|
||||
await BrowserActions.click(this.menu.createFileFromTemplateAction);
|
||||
}
|
||||
|
||||
async openCreateFolderFromTemplateDialog(): Promise<void> {
|
||||
await this.openCreateMenu();
|
||||
await BrowserActions.click(this.menu.createFolderFromTemplateAction);
|
||||
}
|
||||
|
||||
async openCreateMenu(): Promise<void> {
|
||||
await BrowserActions.click(this.createButton);
|
||||
await this.menu.waitForMenuToOpen();
|
||||
}
|
||||
|
||||
async closeCreateMenu(): Promise<void> {
|
||||
await BrowserActions.click(element(by.css('button[id="app.toolbar.create"]')));
|
||||
await this.menu.waitForMenuToClose();
|
||||
}
|
||||
|
||||
async openUploadMenu(): Promise<void> {
|
||||
await BrowserActions.click(this.uploadButton);
|
||||
await this.menu.waitForMenuToOpen();
|
||||
}
|
||||
|
||||
async closeUploadMenu(): Promise<void> {
|
||||
await BrowserActions.click(element(by.css('button[id="app.toolbar.upload"]')));
|
||||
await this.menu.waitForMenuToClose();
|
||||
}
|
||||
|
||||
async clickMoreActionsFavorite(): Promise<void> {
|
||||
await this.openMoreMenu();
|
||||
await this.menu.clickMenuItem('Favorite');
|
||||
|
@@ -47,7 +47,6 @@ export const APP_ROUTES = {
|
||||
// Sidebar labels
|
||||
export const SIDEBAR_LABELS = {
|
||||
PERSONAL_FILES: 'Personal Files',
|
||||
FILE_LIBRARIES: 'File Libraries',
|
||||
MY_LIBRARIES: 'My Libraries',
|
||||
FAVORITE_LIBRARIES: 'Favorite Libraries',
|
||||
SHARED_FILES: 'Shared',
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Header, DataTable, Pagination, Toolbar, Breadcrumb, Sidenav } from '../components/components';
|
||||
import { Header, DataTable, Pagination, Toolbar, Breadcrumb, Sidenav, PageLayoutHeader } from '../components/components';
|
||||
import { SIDEBAR_LABELS } from './../configs';
|
||||
import { Page } from './page';
|
||||
|
||||
@@ -31,6 +31,7 @@ export class BrowsingPage extends Page {
|
||||
sidenav = new Sidenav(this.appRoot);
|
||||
toolbar = new Toolbar(this.appRoot);
|
||||
breadcrumb = new Breadcrumb(this.appRoot);
|
||||
pageLayoutHeader = new PageLayoutHeader(this.appRoot);
|
||||
dataTable = new DataTable(this.appRoot);
|
||||
pagination = new Pagination(this.appRoot);
|
||||
|
||||
@@ -43,19 +44,7 @@ export class BrowsingPage extends Page {
|
||||
await this.dataTable.waitForHeader();
|
||||
}
|
||||
|
||||
async clickFileLibraries(): Promise<void> {
|
||||
await this.sidenav.clickLink(SIDEBAR_LABELS.FILE_LIBRARIES);
|
||||
}
|
||||
|
||||
async clickFileLibrariesAndWait(): Promise<void> {
|
||||
await this.clickFileLibraries();
|
||||
await this.dataTable.waitForHeader();
|
||||
}
|
||||
|
||||
async goToFavoriteLibraries(): Promise<void> {
|
||||
if (!(await this.sidenav.isFileLibrariesMenuExpanded())) {
|
||||
await this.sidenav.expandFileLibraries();
|
||||
}
|
||||
await this.sidenav.clickLink(SIDEBAR_LABELS.FAVORITE_LIBRARIES);
|
||||
}
|
||||
|
||||
@@ -65,9 +54,6 @@ export class BrowsingPage extends Page {
|
||||
}
|
||||
|
||||
async goToMyLibraries(): Promise<void> {
|
||||
if (!(await this.sidenav.isFileLibrariesMenuExpanded())) {
|
||||
await this.sidenav.expandFileLibraries();
|
||||
}
|
||||
await this.sidenav.clickLink(SIDEBAR_LABELS.MY_LIBRARIES);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user