diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..1c3cdbc27 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx + +COPY nginx.conf /etc/nginx/nginx.conf + +WORKDIR /usr/share/nginx/html +COPY dist/ . + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..3ecf2b560 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3.1' + +services: + app: + image: 'alfresco/content-app' + build: '.' + ports: + - 3000:80 diff --git a/e2e/components/login/login.ts b/e2e/components/login/login.ts index 742f08635..ceb89a61c 100644 --- a/e2e/components/login/login.ts +++ b/e2e/components/login/login.ts @@ -19,7 +19,7 @@ import { by, ElementFinder, promise } from 'protractor'; import { Component } from '../component'; export class LoginComponent extends Component { - static selector = 'alfresco-login'; + static selector = 'adf-login'; private locators = { usernameInput: by.css('input#username'), diff --git a/e2e/pages/login-page.ts b/e2e/pages/login-page.ts index 2a6f90f33..d5ca2dc98 100644 --- a/e2e/pages/login-page.ts +++ b/e2e/pages/login-page.ts @@ -40,7 +40,10 @@ export class LoginPage extends Page { const { submitButton } = this.login; const hasSumbitButton = EC.presenceOf(submitButton); - return browser.wait(hasSumbitButton, BROWSER_WAIT_TIMEOUT); + return browser.wait(hasSumbitButton, BROWSER_WAIT_TIMEOUT) + .then(() => browser.executeScript('window.localStorage.clear();')) + .then(() => browser.executeScript('window.sessionStorage.clear();')) + .then(() => browser.driver.manage().deleteAllCookies()); }); } diff --git a/e2e/pages/logout-page.ts b/e2e/pages/logout-page.ts index f1c0b65ce..5a8f6082a 100644 --- a/e2e/pages/logout-page.ts +++ b/e2e/pages/logout-page.ts @@ -22,7 +22,7 @@ import { APP_ROUTES } from '../configs'; export class LogoutPage extends Page { /** @override */ constructor() { - super(APP_ROUTES.LOGOUT); + super(APP_ROUTES.LOGIN); } /** @override */ diff --git a/e2e/pages/page.ts b/e2e/pages/page.ts index 0ee4009cb..7ec381401 100644 --- a/e2e/pages/page.ts +++ b/e2e/pages/page.ts @@ -18,7 +18,7 @@ import { browser, element, by, ElementFinder, promise } from 'protractor'; export abstract class Page { - private static USE_HASH_STRATEGY = true; + private static USE_HASH_STRATEGY = false; private locators = { app: by.css('app-root'), diff --git a/e2e/suites/actions/create-folder.test.ts b/e2e/suites/actions/create-folder.test.ts index 27d5f37de..c608562cf 100644 --- a/e2e/suites/actions/create-folder.test.ts +++ b/e2e/suites/actions/create-folder.test.ts @@ -17,21 +17,24 @@ import { protractor, browser, by, ElementFinder } from 'protractor'; -import { APP_ROUTES, BROWSER_WAIT_TIMEOUT } from '../../configs'; +import { APP_ROUTES, BROWSER_WAIT_TIMEOUT, SITE_VISIBILITY, SITE_ROLES } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; import { CreateOrEditFolderDialog } from '../../components/dialog/create-edit-folder-dialog'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client'; describe('Create folder', () => { const username = 'jane.doe'; const password = 'jane.doe'; + const parent = 'parent-folder'; const folderName1 = 'my-folder1'; const folderName2 = 'my-folder2'; const folderDescription = 'description of my folder'; const duplicateFolderName = 'duplicate-folder-name'; - const nameWithSpaces = ' folder name '; + const nameWithSpaces = ' folder-name '; + + const siteName = 'site-private'; const apis = { admin: new RepoClient(), @@ -55,7 +58,10 @@ describe('Create folder', () => { beforeAll(done => { apis.admin.people.createUser(username, password) - .then(() => apis.user.nodes.createFolders([ duplicateFolderName ])) + .then(() => apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PRIVATE)) + .then(() => apis.admin.nodes.createFolders([ folderName1 ], `Sites/${siteName}/documentLibrary`)) + .then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_CONSUMER)) + .then(() => apis.user.nodes.createFolders([ duplicateFolderName ], parent)) .then(() => loginPage.load()) .then(() => loginPage.loginWith(username, password)) .then(done); @@ -74,80 +80,84 @@ describe('Create folder', () => { afterAll(done => { Promise .all([ - apis.user.nodes.deleteNodes([ - folderName1, - folderName2, - duplicateFolderName, - nameWithSpaces.trim() - ]), + apis.user.nodes.deleteNodes([ parent ]), logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) ]) .then(done); }); it('option is enabled when having enough permissions', () => { - personalFilesPage.sidenav.openNewMenu() - .then((menu) => { - const isEnabled = menu.getItemByLabel('Create folder').getWebElement().isEnabled(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => personalFilesPage.sidenav.openNewMenu() + .then((menu) => { + const isEnabled = menu.getItemByLabel('Create folder').getWebElement().isEnabled(); - expect(isEnabled).toBe(true, 'Create folder is not enabled'); - }); + expect(isEnabled).toBe(true, 'Create folder is not enabled'); + }) + ); }); it('creates new folder with name', () => { - openCreateDialog() - .then(() => createDialog.enterName(folderName1).clickCreate()) - .then(() => createDialog.waitForDialogToClose()) - .then(() => dataTable.waitForHeader()) - .then(() => { - const isPresent = dataTable.getRowByContainingText(folderName1).isPresent(); - expect(isPresent).toBe(true, 'Folder not displayed in list view'); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => createDialog.enterName(folderName1).clickCreate()) + .then(() => createDialog.waitForDialogToClose()) + .then(() => dataTable.waitForHeader()) + .then(() => { + const isPresent = dataTable.getRowByContainingText(folderName1).isPresent(); + expect(isPresent).toBe(true, 'Folder not displayed in list view'); + }) + ); }); it('creates new folder with name and description', () => { - openCreateDialog() - .then(() => { - createDialog - .enterName(folderName2) - .enterDescription(folderDescription) - .clickCreate(); - }) - .then(() => createDialog.waitForDialogToClose()) - .then(() => dataTable.waitForHeader()) - .then(() => { - const isPresent = dataTable.getRowByContainingText(folderName2).isPresent(); - expect(isPresent).toBe(true, 'Folder not displayed in list view'); - }) - .then(() => { - apis.user.nodes.getNodeDescription(folderName2) - .then((description) => { - expect(description).toEqual(folderDescription, 'Description is not correct'); - }); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => { + createDialog + .enterName(folderName2) + .enterDescription(folderDescription) + .clickCreate(); + }) + .then(() => createDialog.waitForDialogToClose()) + .then(() => dataTable.waitForHeader()) + .then(() => { + const isPresent = dataTable.getRowByContainingText(folderName2).isPresent(); + expect(isPresent).toBe(true, 'Folder not displayed in list view'); + }) + .then(() => { + apis.user.nodes.getNodeDescription(folderName2) + .then((description) => { + expect(description).toEqual(folderDescription, 'Description is not correct'); + }); + }) + ); }); it('enabled option tooltip', () => { - personalFilesPage.sidenav.openNewMenu() - .then(menu => { - const action = browser.actions().mouseMove(menu.getItemByLabel('Create folder')); - action.perform(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => personalFilesPage.sidenav.openNewMenu() + .then(menu => { + const action = browser.actions().mouseMove(menu.getItemByLabel('Create folder')); + action.perform(); - return menu; - }) - .then((menu) => { - const tooltip = menu.getItemTooltip('Create folder'); - expect(tooltip).toContain('Create new folder'); - }); + return menu; + }) + .then((menu) => { + const tooltip = menu.getItemTooltip('Create folder'); + expect(tooltip).toContain('Create new folder'); + }) + ); }); it('option is disabled when not enough permissions', () => { - // refactor after implementing Breadcrumb automation component - const breadcrumbRoot: ElementFinder = protractor.element(by.css('.adf-breadcrumb-item[title="User Homes"]')); + const fileLibrariesPage = new BrowsingPage(APP_ROUTES.FILE_LIBRARIES); - browser.actions().mouseMove(breadcrumbRoot).click().perform() - .then(() => personalFilesPage.sidenav.openNewMenu()) + fileLibrariesPage.sidenav.navigateToLinkByLabel('File Libraries') + .then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(siteName)) + .then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(folderName1)) + .then(() => fileLibrariesPage.sidenav.openNewMenu()) .then(menu => { const isEnabled = menu.getItemByLabel('Create folder').getWebElement().isEnabled(); expect(isEnabled).toBe(false, 'Create folder is not disabled'); @@ -155,11 +165,12 @@ describe('Create folder', () => { }); it('disabled option tooltip', () => { - // refactor after implementing Breadcrumb automation component - const breadcrumbRoot: ElementFinder = protractor.element(by.css('.adf-breadcrumb-item[title="User Homes"]')); + const fileLibrariesPage = new BrowsingPage(APP_ROUTES.FILE_LIBRARIES); - browser.actions().mouseMove(breadcrumbRoot).click().perform() - .then(() => personalFilesPage.sidenav.openNewMenu()) + fileLibrariesPage.sidenav.navigateToLinkByLabel('File Libraries') + .then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(siteName)) + .then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(folderName1)) + .then(() => fileLibrariesPage.sidenav.openNewMenu()) .then(menu => { const action = browser.actions().mouseMove(menu.getItemByLabel('Create folder')); action.perform() @@ -171,107 +182,123 @@ describe('Create folder', () => { }); it('dialog UI elements', () => { - openCreateDialog().then(() => { - const dialogTitle = createDialog.getTitle(); - const isFolderNameDisplayed = createDialog.nameInput.getWebElement().isDisplayed(); - const isDescriptionDisplayed = createDialog.descriptionTextArea.getWebElement().isDisplayed(); - const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); - const isCancelEnabled = createDialog.cancelButton.getWebElement().isEnabled(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog().then(() => { + const dialogTitle = createDialog.getTitle(); + const isFolderNameDisplayed = createDialog.nameInput.getWebElement().isDisplayed(); + const isDescriptionDisplayed = createDialog.descriptionTextArea.getWebElement().isDisplayed(); + const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); + const isCancelEnabled = createDialog.cancelButton.getWebElement().isEnabled(); - expect(dialogTitle).toBe('Create new folder'); - expect(isFolderNameDisplayed).toBe(true, 'Name input is not displayed'); - expect(isDescriptionDisplayed).toBe(true, 'Description field is not displayed'); - expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); - expect(isCancelEnabled).toBe(true, 'Cancel button is not enabled'); - }); + expect(dialogTitle).toBe('Create new folder'); + expect(isFolderNameDisplayed).toBe(true, 'Name input is not displayed'); + expect(isDescriptionDisplayed).toBe(true, 'Description field is not displayed'); + expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); + expect(isCancelEnabled).toBe(true, 'Cancel button is not enabled'); + }) + ); }); it('with empty folder name', () => { - openCreateDialog() - .then(() => { - createDialog.deleteNameWithBackspace(); - }) - .then(() => { - const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); - const validationMessage = createDialog.getValidationMessage(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => { + createDialog.deleteNameWithBackspace(); + }) + .then(() => { + const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); + const validationMessage = createDialog.getValidationMessage(); - expect(isCreateEnabled).toBe(false, 'Create button is enabled'); - expect(validationMessage).toMatch('Folder name is required'); - }); + expect(isCreateEnabled).toBe(false, 'Create button is enabled'); + expect(validationMessage).toMatch('Folder name is required'); + }) + ); }); it('with folder name ending with a dot "."', () => { - openCreateDialog() - .then(() => createDialog.enterName('folder-name.')) - .then((dialog) => { - const isCreateEnabled = dialog.createButton.getWebElement().isEnabled(); - const validationMessage = dialog.getValidationMessage(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => createDialog.enterName('folder-name.')) + .then((dialog) => { + const isCreateEnabled = dialog.createButton.getWebElement().isEnabled(); + const validationMessage = dialog.getValidationMessage(); - expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); - expect(validationMessage).toMatch(`Folder name can't end with a period .`); - }); + expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); + expect(validationMessage).toMatch(`Folder name can't end with a period .`); + }) + ); }); it('with folder name containing special characters', () => { const namesWithSpecialChars = [ 'a*a', 'a"a', 'aa', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a' ]; - openCreateDialog() - .then(() => { - namesWithSpecialChars.forEach(name => { - createDialog.enterName(name); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => { + namesWithSpecialChars.forEach(name => { + createDialog.enterName(name); - const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); - const validationMessage = createDialog.getValidationMessage(); + const isCreateEnabled = createDialog.createButton.getWebElement().isEnabled(); + const validationMessage = createDialog.getValidationMessage(); - expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); - expect(validationMessage).toContain(`Folder name can't contain these characters`); - }); - }); + expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); + expect(validationMessage).toContain(`Folder name can't contain these characters`); + }); + }) + ); }); it('with folder name containing only spaces', () => { - openCreateDialog() - .then(() => createDialog.enterName(' ')) - .then((dialog) => { - const isCreateEnabled = dialog.createButton.getWebElement().isEnabled(); - const validationMessage = dialog.getValidationMessage(); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => createDialog.enterName(' ')) + .then((dialog) => { + const isCreateEnabled = dialog.createButton.getWebElement().isEnabled(); + const validationMessage = dialog.getValidationMessage(); - expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); - expect(validationMessage).toMatch(`Folder name can't contain only spaces`); - }); + expect(isCreateEnabled).toBe(false, 'Create button is not disabled'); + expect(validationMessage).toMatch(`Folder name can't contain only spaces`); + }) + ); }); it('cancel folder creation', () => { - openCreateDialog() - .then(() => { - createDialog - .enterName('test') - .enterDescription('test description') - .clickCancel(); - }) - .then(() => expect(createDialog.component.isPresent()).not.toBe(true, 'dialog is not closed')); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => { + createDialog + .enterName('test') + .enterDescription('test description') + .clickCancel(); + }) + .then(() => expect(createDialog.component.isPresent()).not.toBe(true, 'dialog is not closed')) + ); }); it('duplicate folder name', () => { - openCreateDialog() - .then(() => createDialog.enterName(duplicateFolderName).clickCreate()) - .then(() => { - personalFilesPage.getSnackBarMessage() - .then(message => { - expect(message).toEqual(`There's already a folder with this name. Try a different name.`); - expect(createDialog.component.isPresent()).toBe(true, 'dialog is not present'); - }); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => createDialog.enterName(duplicateFolderName).clickCreate()) + .then(() => { + personalFilesPage.getSnackBarMessage() + .then(message => { + expect(message).toEqual(`There's already a folder with this name. Try a different name.`); + expect(createDialog.component.isPresent()).toBe(true, 'dialog is not present'); + }); + }) + ); }); it('trim ending spaces from folder name', () => { - openCreateDialog() - .then(() => createDialog.enterName(nameWithSpaces).clickCreate()) - .then(() => createDialog.waitForDialogToClose()) - .then(() => dataTable.waitForHeader()) - .then(() => { - const isPresent = dataTable.getRowByContainingText(nameWithSpaces.trim()).isPresent(); - expect(isPresent).toBe(true, 'Folder not displayed in list view'); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => openCreateDialog() + .then(() => createDialog.enterName(nameWithSpaces).clickCreate()) + .then(() => createDialog.waitForDialogToClose()) + .then(() => dataTable.waitForHeader()) + .then(() => { + const isPresent = dataTable.getRowByContainingText(nameWithSpaces.trim()).isPresent(); + expect(isPresent).toBe(true, 'Folder not displayed in list view'); + }) + ); }); }); diff --git a/e2e/suites/actions/edit-folder.test.ts b/e2e/suites/actions/edit-folder.test.ts index 47bf0b749..441ba60fa 100644 --- a/e2e/suites/actions/edit-folder.test.ts +++ b/e2e/suites/actions/edit-folder.test.ts @@ -20,12 +20,13 @@ import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES } from '../../configs'; import { RepoClient } from '../../utilities/repo-client/repo-client'; import { CreateOrEditFolderDialog } from '../../components/dialog/create-edit-folder-dialog'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; describe('Edit folder', () => { - const username = 'jane.doe'; - const password = 'jane.doe'; + const username = 'john.doe'; + const password = 'john.doe'; + const parent = 'parent-folder'; const folderName = 'my-folder'; const folderDescription = 'my folder description'; @@ -44,7 +45,7 @@ describe('Edit folder', () => { const loginPage = new LoginPage(); const logoutPage = new LogoutPage(); - const personalFilesPage = new BrowsingPage(); + const personalFilesPage = new BrowsingPage(APP_ROUTES.PERSONAL_FILES); const editDialog = new CreateOrEditFolderDialog(); const dataTable = personalFilesPage.dataTable; const editButton = personalFilesPage.toolbar.actions.getButtonByTitleAttribute('Edit'); @@ -58,11 +59,11 @@ describe('Edit folder', () => { ]) .then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_CONSUMER)) .then(() => Promise.all([ - apis.user.nodes.createNodeWithProperties( folderName, '', folderDescription ), - apis.user.nodes.createFolders([ folderNameToEdit, duplicateFolderName ]), + apis.user.nodes.createNodeWithProperties( folderName, '', folderDescription, parent ), + apis.user.nodes.createFolders([ folderNameToEdit, duplicateFolderName ], parent), loginPage.load() ])) - .then(() => { loginPage.loginWith(username, password); }) + .then(() => loginPage.loginWith(username, password)) .then(done); }); @@ -80,57 +81,63 @@ describe('Edit folder', () => { Promise .all([ apis.admin.sites.deleteSite(siteName, true), - apis.user.nodes.deleteNodes([ folderName, folderNameEdited, duplicateFolderName ]), + apis.user.nodes.deleteNodes([ parent ]), logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) ]) .then(done); }); it('button is enabled when having permissions', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => { - expect(editButton.isEnabled()).toBe(true); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => { + expect(editButton.isEnabled()).toBe(true); + }) + ); }); it('dialog UI defaults', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => { - expect(editDialog.getTitle()).toBe('Edit folder'); - expect(editDialog.nameInput.getWebElement().getAttribute('value')).toBe(folderName); - expect(editDialog.descriptionTextArea.getWebElement().getAttribute('value')).toBe(folderDescription); - expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(true, 'upload button is not enabled'); - expect(editDialog.cancelButton.getWebElement().isEnabled()).toBe(true, 'cancel button is not enabled'); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => { + expect(editDialog.getTitle()).toBe('Edit folder'); + expect(editDialog.nameInput.getWebElement().getAttribute('value')).toBe(folderName); + expect(editDialog.descriptionTextArea.getWebElement().getAttribute('value')).toBe(folderDescription); + expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(true, 'upload button is not enabled'); + expect(editDialog.cancelButton.getWebElement().isEnabled()).toBe(true, 'cancel button is not enabled'); + }) + ); }); it('folder properties are modified when pressing OK', () => { - dataTable.clickOnRowByContainingText(folderNameToEdit) - .then(() => editButton.click()) - .then(() => { - editDialog - .enterName(folderNameEdited) - .enterDescription(folderDescriptionEdited) - .clickUpdate(); - }) - .then(() => editDialog.waitForDialogToClose()) - .then(() => dataTable.waitForHeader()) - .then(() => { - const isPresent = dataTable.getRowByContainingText(folderNameEdited).isPresent(); - expect(isPresent).toBe(true, 'Folder not displayed in list view'); - }) - .then(() => { - apis.user.nodes.getNodeDescription(folderNameEdited) - .then((description) => { - expect(description).toEqual(folderDescriptionEdited); - }); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderNameToEdit) + .then(() => editButton.click()) + .then(() => { + editDialog + .enterName(folderNameEdited) + .enterDescription(folderDescriptionEdited) + .clickUpdate(); + }) + .then(() => editDialog.waitForDialogToClose()) + .then(() => dataTable.waitForHeader()) + .then(() => { + const isPresent = dataTable.getRowByContainingText(folderNameEdited).isPresent(); + expect(isPresent).toBe(true, 'Folder not displayed in list view'); + }) + .then(() => { + apis.user.nodes.getNodeDescription(folderNameEdited) + .then((description) => { + expect(description).toEqual(folderDescriptionEdited); + }); + }) + ); }); it('button is not displayed when not enough permissions', () => { - const fileLibrariesPage = new BrowsingPage(); + const fileLibrariesPage = new BrowsingPage(APP_ROUTES.FILE_LIBRARIES); fileLibrariesPage.sidenav.navigateToLinkByLabel('File Libraries') .then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(siteName)) @@ -141,71 +148,85 @@ describe('Edit folder', () => { }); it('with empty folder name', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => { - editDialog.deleteNameWithBackspace(); - }) - .then(() => { - expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled'); - expect(editDialog.getValidationMessage()).toMatch('Folder name is required'); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => { + editDialog.deleteNameWithBackspace(); + }) + .then(() => { + expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled'); + expect(editDialog.getValidationMessage()).toMatch('Folder name is required'); + }) + ); }); it('with name with special characters', () => { const namesWithSpecialChars = [ 'a*a', 'a"a', 'aa', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a' ]; - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => { - namesWithSpecialChars.forEach(name => { - editDialog.enterName(name); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => { + namesWithSpecialChars.forEach(name => { + editDialog.enterName(name); - expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not disabled'); - expect(editDialog.getValidationMessage()).toContain(`Folder name can't contain these characters`); - }); - }); + expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not disabled'); + expect(editDialog.getValidationMessage()).toContain(`Folder name can't contain these characters`); + }); + }) + ); }); it('with name ending with a dot', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => editDialog.nameInput.sendKeys('.')) - .then(() => { - expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled'); - expect(editDialog.getValidationMessage()).toMatch(`Folder name can't end with a period .`); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => editDialog.nameInput.sendKeys('.')) + .then(() => { + expect(editDialog.updateButton.getWebElement().isEnabled()).toBe(false, 'upload button is not enabled'); + expect(editDialog.getValidationMessage()).toMatch(`Folder name can't end with a period .`); + }) + ); }); it('Cancel button', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => editDialog.clickCancel()) - .then(() => { expect(editDialog.component.isPresent()).not.toBe(true, 'dialog is not closed'); }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => editDialog.clickCancel()) + .then(() => { + expect(editDialog.component.isPresent()).not.toBe(true, 'dialog is not closed'); + }) + ); }); it('with duplicate folder name', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => editDialog.enterName(duplicateFolderName).clickUpdate()) - .then(() => { - personalFilesPage.getSnackBarMessage() - .then(message => { - expect(message).toEqual(`There's already a folder with this name. Try a different name.`); - expect(editDialog.component.isPresent()).toBe(true, 'dialog is not present'); - }); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => editDialog.enterName(duplicateFolderName).clickUpdate()) + .then(() => { + personalFilesPage.getSnackBarMessage() + .then(message => { + expect(message).toEqual(`There's already a folder with this name. Try a different name.`); + expect(editDialog.component.isPresent()).toBe(true, 'dialog is not present'); + }); + }) + ); }); it('trim ending spaces', () => { - dataTable.clickOnRowByContainingText(folderName) - .then(() => editButton.click()) - .then(() => editDialog.nameInput.sendKeys(' ')) - .then(() => editDialog.clickUpdate()) - .then(() => editDialog.waitForDialogToClose()) - .then(() => { - expect(personalFilesPage.snackBar.isPresent()).not.toBe(true, 'notification appears'); - expect(dataTable.getRowByContainingText(folderName).isPresent()).toBe(true, 'Folder not displayed in list view'); - }); + personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent) + .then(() => dataTable.clickOnRowByContainingText(folderName) + .then(() => editButton.click()) + .then(() => editDialog.nameInput.sendKeys(' ')) + .then(() => editDialog.clickUpdate()) + .then(() => editDialog.waitForDialogToClose()) + .then(() => { + expect(personalFilesPage.snackBar.isPresent()).not.toBe(true, 'notification appears'); + expect(dataTable.getRowByContainingText(folderName).isPresent()).toBe(true, 'Folder not displayed in list view'); + }) + ); }); }); diff --git a/e2e/suites/application/page-titles.test.ts b/e2e/suites/application/page-titles.test.ts index b9085a6f7..6906435af 100644 --- a/e2e/suites/application/page-titles.test.ts +++ b/e2e/suites/application/page-titles.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { SIDEBAR_LABELS } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; describe('Page titles', () => { const loginPage = new LoginPage(); @@ -65,7 +65,7 @@ describe('Page titles', () => { afterAll(done => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); diff --git a/e2e/suites/authentication/login.test.ts b/e2e/suites/authentication/login.test.ts index 922386dad..56d804805 100644 --- a/e2e/suites/authentication/login.test.ts +++ b/e2e/suites/authentication/login.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { APP_ROUTES } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; import { RepoClient } from '../../utilities/repo-client/repo-client'; describe('Login', () => { @@ -63,7 +63,7 @@ describe('Login', () => { afterEach(done => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); diff --git a/e2e/suites/authentication/logout.test.ts b/e2e/suites/authentication/logout.test.ts index 050e2913a..6a48edc25 100644 --- a/e2e/suites/authentication/logout.test.ts +++ b/e2e/suites/authentication/logout.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { APP_ROUTES, BROWSER_WAIT_TIMEOUT } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; import { RepoClient } from '../../utilities/repo-client/repo-client'; describe('Logout', () => { @@ -48,7 +48,7 @@ describe('Logout', () => { afterEach((done) => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); diff --git a/e2e/suites/list-views/personal-files.test.ts b/e2e/suites/list-views/personal-files.test.ts index 891e729a6..efe263793 100644 --- a/e2e/suites/list-views/personal-files.test.ts +++ b/e2e/suites/list-views/personal-files.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { APP_ROUTES } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client'; describe('Personal Files', () => { @@ -81,7 +81,7 @@ describe('Personal Files', () => { afterAll(done => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); @@ -109,7 +109,7 @@ describe('Personal Files', () => { afterAll(done => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); diff --git a/e2e/suites/navigation/side-navigation.test.ts b/e2e/suites/navigation/side-navigation.test.ts index 93e6219fe..bf6c8541d 100644 --- a/e2e/suites/navigation/side-navigation.test.ts +++ b/e2e/suites/navigation/side-navigation.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { APP_ROUTES, SIDEBAR_LABELS } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; describe('Side navigation', () => { const loginPage = new LoginPage(); @@ -38,7 +38,7 @@ describe('Side navigation', () => { afterAll(done => { logoutPage.load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(done); }); diff --git a/e2e/suites/pagination/pagination.test.ts b/e2e/suites/pagination/pagination.test.ts index f0298ff51..7fb40c359 100644 --- a/e2e/suites/pagination/pagination.test.ts +++ b/e2e/suites/pagination/pagination.test.ts @@ -19,7 +19,7 @@ import { browser } from 'protractor'; import { APP_ROUTES } from '../../configs'; import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages'; -import { LocalStorageUtility } from '../../utilities/local-storage'; +import { Utils } from '../../utilities/utils'; import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client'; describe('Pagination', () => { @@ -75,7 +75,7 @@ describe('Pagination', () => { afterAll(done => { logoutPage .load() - .then(() => LocalStorageUtility.clear()) + .then(() => Utils.clearLocalStorage()) .then(() => nodesApi.deleteNodes([ content.name ])) .then(done); }); diff --git a/e2e/utilities/repo-client/apis/favorites/favorites-api.ts b/e2e/utilities/repo-client/apis/favorites/favorites-api.ts new file mode 100644 index 000000000..ced51018d --- /dev/null +++ b/e2e/utilities/repo-client/apis/favorites/favorites-api.ts @@ -0,0 +1,60 @@ +/*! + * @license + * Copyright 2017 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { promise } from 'protractor'; +import { RepoApi } from '../repo-api'; +import { NodesApi } from '../nodes/nodes-api'; +import { RepoClient } from './../../repo-client'; + +export class FavoritesApi extends RepoApi { + + addFavorite(api: RepoClient, nodeType: string, name: string): Promise { + return api.nodes.getNodeByPath(name) + .then((response) => { + const { id } = response.data.entry; + return ([{ + target: { + [nodeType]: { + guid: id + } + } + }]); + }) + .then((data) => { + return this.post(`/people/-me-/favorites`, { data }); + }) + .catch(this.handleError); + } + + getFavorite(api: RepoClient, name: string): Promise { + return api.nodes.getNodeByPath(name) + .then((response) => { + const { id } = response.data.entry; + return this.get(`/people/-me-/favorites/${id}`); + }) + .catch((response) => Promise.resolve(response)); + } + + removeFavorite(api: RepoClient, nodeType: string, name: string): Promise { + return api.nodes.getNodeByPath(name) + .then((response) => { + const { id } = response.data.entry; + return this.delete(`/people/-me-/favorites/${id}`); + }) + .catch(this.handleError); + } +} diff --git a/e2e/utilities/repo-client/repo-client.ts b/e2e/utilities/repo-client/repo-client.ts index 80d37360b..889c4c1f3 100644 --- a/e2e/utilities/repo-client/repo-client.ts +++ b/e2e/utilities/repo-client/repo-client.ts @@ -20,12 +20,13 @@ import { RepoClientAuth, RepoClientConfig } from './repo-client-models'; import { PeopleApi } from './apis/people/people-api'; import { NodesApi } from './apis/nodes/nodes-api'; import { SitesApi } from './apis/sites/sites-api'; +import { FavoritesApi } from './apis/favorites/favorites-api'; export class RepoClient { public people: PeopleApi = new PeopleApi(this.auth, this.config); public nodes: NodesApi = new NodesApi(this.auth, this.config); public sites: SitesApi = new SitesApi(this.auth, this.config); - // public favorites: FavoritesApi = new FavoritesApi(this.auth, this.config); + public favorites: FavoritesApi = new FavoritesApi(this.auth, this.config); // public shared: SharedLinksApi = new SharedLinksApi(this.auth, this.config); constructor( diff --git a/e2e/utilities/local-storage.ts b/e2e/utilities/utils.ts similarity index 64% rename from e2e/utilities/local-storage.ts rename to e2e/utilities/utils.ts index 46d7d7926..0a6072f68 100644 --- a/e2e/utilities/local-storage.ts +++ b/e2e/utilities/utils.ts @@ -17,18 +17,14 @@ import { browser, promise } from 'protractor'; -declare var window; - -export class LocalStorageUtility { - static clear(): promise.Promise { - return browser.executeScript(() => { - return window.localStorage.clear(); - }); +export class Utils { + // generate a random value + static random(): string { + return Math.random().toString(36).substring(3, 10); } - static getTicket(): promise.Promise { - return browser.executeScript(() => { - return window.localStorage.getItem('ticket-ECM'); - }); + // local storage + static clearLocalStorage(): promise.Promise { + return browser.executeScript('window.localStorage.clear();'); } } diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 000000000..ea9434b3d --- /dev/null +++ b/nginx.conf @@ -0,0 +1,25 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html index.htm; + include /etc/nginx/mime.types; + + gzip on; + gzip_min_length 1000; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + location / { + try_files $uri $uri/ /index.html; + } + } +} diff --git a/package.json b/package.json index 5349356db..7319ef40a 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,8 @@ "ng": "ng", "start": "ng serve --open", "build": "ng build", + "build:prod": "ng build --prod", + "build:dev": "ng build && node postbuild-dev.js", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e", @@ -24,17 +26,17 @@ "@angular/platform-browser": "4.4.5", "@angular/platform-browser-dynamic": "4.4.5", "@angular/router": "4.4.5", - "@ngx-translate/core": "7.0.0", - "alfresco-js-api": "1.10.0-beta5", + "@ngx-translate/core": "8.0.0", + "alfresco-js-api": "1.10.0-beta6", "core-js": "^2.4.1", "hammerjs": "2.0.8", - "ng2-alfresco-core": "1.10.0-beta5", - "ng2-alfresco-datatable": "1.10.0-beta5", - "ng2-alfresco-documentlist": "1.10.0-beta5", - "ng2-alfresco-login": "1.10.0-beta5", - "ng2-alfresco-search": "1.10.0-beta5", - "ng2-alfresco-upload": "1.10.0-beta5", - "ng2-alfresco-viewer": "1.10.0-beta5", + "ng2-alfresco-core": "1.10.0-beta6", + "ng2-alfresco-datatable": "1.10.0-beta6", + "ng2-alfresco-documentlist": "1.10.0-beta6", + "ng2-alfresco-login": "1.10.0-beta6", + "ng2-alfresco-search": "1.10.0-beta6", + "ng2-alfresco-upload": "1.10.0-beta6", + "ng2-alfresco-viewer": "1.10.0-beta6", "pdfjs-dist": "1.8.557", "rxjs": "5.1.0", "wsrv": "0.2.2", @@ -44,14 +46,14 @@ "@angular/cli": "1.4.7", "@angular/compiler-cli": "4.4.5", "@angular/language-service": "4.4.5", - "@types/jasmine": "~2.5.53", - "@types/jasminewd2": "~2.0.2", + "@types/jasmine": "^2.5.53", + "@types/jasminewd2": "^2.0.2", "@types/node": "~6.0.60", "codelyzer": "~3.2.0", - "jasmine-core": "~2.6.2", - "jasmine-reporters": "2.2.1", - "jasmine-spec-reporter": "~4.1.0", - "jasmine2-protractor-utils": "1.3.0", + "jasmine-core": "^2.6.2", + "jasmine-reporters": "^2.2.1", + "jasmine-spec-reporter": "^4.1.0", + "jasmine2-protractor-utils": "^1.3.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", @@ -59,7 +61,7 @@ "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "node-rest-client": "^3.1.0", - "protractor": "~5.1.2", + "protractor": "^5.1.2", "ts-node": "~3.2.0", "tslint": "~5.7.0", "typescript": "~2.3.3" diff --git a/postbuild-dev.js b/postbuild-dev.js new file mode 100644 index 000000000..02544050d --- /dev/null +++ b/postbuild-dev.js @@ -0,0 +1,26 @@ +/*! + * @license + * Copyright 2017 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var fs = require('fs'); +var config = require('./dist/app.config.json'); + +config.ecmHost = 'http://localhost:8080'; + +fs.writeFileSync( + './dist/app.config.json', + JSON.stringify(config, null, 4) +); diff --git a/protractor.conf.js b/protractor.conf.js index 9db00659f..9141ac324 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -8,49 +8,54 @@ const jasmineReporters = require('jasmine-reporters'); const projectRoot = path.resolve(__dirname); exports.config = { - allScriptsTimeout: 11000, - specs: [ - './e2e/**/*.test.ts' - ], - capabilities: { - 'browserName': 'chrome', - chromeOptions: { - prefs: { - 'credentials_enable_service': false + allScriptsTimeout: 11000, + specs: [ + './e2e/suites/authentication/*.test.ts', + './e2e/suites/list-views/*.test.ts', + './e2e/suites/application/page-titles.test.ts', + './e2e/suites/navigation/side-navigation.test.ts', + './e2e/suites/pagination/pagination.test.ts', + './e2e/suites/actions/*.test.ts' + ], + capabilities: { + 'browserName': 'chrome', + chromeOptions: { + prefs: { + 'credentials_enable_service': false + } } - } - }, - directConnect: true, - baseUrl: 'http://localhost:3000', - framework: 'jasmine', - jasmineNodeOpts: { - showColors: true, - defaultTimeoutInterval: 30000, - print: function() {} - }, - plugins: [{ - package: 'jasmine2-protractor-utils', - disableHTMLReport: false, - disableScreenshot: false, - screenshotOnExpectFailure: true, - screenshotOnSpecFailure: false, - clearFoldersBeforeTest: true, - htmlReportDir: `${projectRoot}/e2e-output/html-report/`, - screenshotPath: `${projectRoot}/e2e-output/screenshots/` - }], - onPrepare() { - require('ts-node').register({ - project: 'e2e/tsconfig.e2e.json' - }); - jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + }, + directConnect: true, + baseUrl: 'http://localhost:3000', + framework: 'jasmine2', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + plugins: [{ + package: 'jasmine2-protractor-utils', + disableHTMLReport: false, + disableScreenshot: false, + screenshotOnExpectFailure: true, + screenshotOnSpecFailure: false, + clearFoldersBeforeTest: true, + htmlReportDir: `${projectRoot}/e2e-output/html-report/`, + screenshotPath: `${projectRoot}/e2e-output/screenshots/` + }], + onPrepare() { + require('ts-node').register({ + project: 'e2e/tsconfig.e2e.json' + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); - jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({ - consolidateAll: true, - savePath: `${projectRoot}/e2e-output/junit-report`, - filePrefix: 'results.xml', - useDotNotation: false, - useFullTestName: false, - reportFailedUrl: true - })); - } + jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({ + consolidateAll: true, + savePath: `${projectRoot}/e2e-output/junit-report`, + filePrefix: 'results.xml', + useDotNotation: false, + useFullTestName: false, + reportFailedUrl: true + })); + } }; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 36072abef..9be78dbd3 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -46,7 +46,6 @@ import { SidenavComponent } from './components/sidenav/sidenav.component'; imports: [ BrowserModule, RouterModule.forRoot(APP_ROUTES, { - useHash: true, enableTracing: false // enable for debug only }), AdfModule, diff --git a/src/app/common/common.module.ts b/src/app/common/common.module.ts index 5e008c78c..a31010d56 100644 --- a/src/app/common/common.module.ts +++ b/src/app/common/common.module.ts @@ -23,10 +23,6 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { AdfModule } from '../adf.module'; import { MaterialModule } from './material.module'; -import { FolderDialogComponent } from './dialogs/folder-dialog.component'; - -import { FolderCreateDirective } from './directives/folder-create.directive'; -import { FolderEditDirective } from './directives/folder-edit.directive'; import { NodeCopyDirective } from './directives/node-copy.directive'; import { NodeDeleteDirective } from './directives/node-delete.directive'; import { NodeMoveDirective } from './directives/node-move.directive'; @@ -51,10 +47,6 @@ export function modules() { export function declarations() { return [ - FolderDialogComponent, - - FolderCreateDirective, - FolderEditDirective, NodeCopyDirective, NodeDeleteDirective, NodeMoveDirective, @@ -77,9 +69,7 @@ export function providers() { @NgModule({ imports: modules(), declarations: declarations(), - entryComponents: [ - FolderDialogComponent - ], + entryComponents: [], providers: providers(), exports: [ ...modules(), diff --git a/src/app/common/dialogs/folder-dialog.component.html b/src/app/common/dialogs/folder-dialog.component.html deleted file mode 100644 index b392bea9d..000000000 --- a/src/app/common/dialogs/folder-dialog.component.html +++ /dev/null @@ -1,62 +0,0 @@ -

- {{ - (editing - ? 'APP.FOLDER_DIALOG.EDIT_FOLDER_TITLE' - : 'APP.FOLDER_DIALOG.CREATE_FOLDER_TITLE' - ) | translate - }} -

- - -
- - - - - - {{ 'APP.FOLDER_DIALOG.FOLDER_NAME.ERRORS.REQUIRED' | translate }} - - - - {{ form.controls['name'].errors?.message | translate }} - - - - -
-
- - - - -
-
- - - - - - diff --git a/src/app/common/dialogs/folder-dialog.component.spec.ts b/src/app/common/dialogs/folder-dialog.component.spec.ts deleted file mode 100644 index ef118baa6..000000000 --- a/src/app/common/dialogs/folder-dialog.component.spec.ts +++ /dev/null @@ -1,260 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TestBed, async } from '@angular/core/testing'; -import { Observable } from 'rxjs/Rx'; -import { MatDialogModule, MatDialogRef } from '@angular/material'; -import { CoreModule, NodesApiService, TranslationService, NotificationService } from 'ng2-alfresco-core'; - -import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; -import { FolderDialogComponent } from './folder-dialog.component'; -import { ComponentFixture } from '@angular/core/testing'; - -describe('FolderDialogComponent', () => { - - let fixture: ComponentFixture; - let component: FolderDialogComponent; - let translationService: TranslationService; - let nodesApi: NodesApiService; - let notificationService: NotificationService; - let dialogRef; - - beforeEach(async(() => { - dialogRef = { - close: jasmine.createSpy('close') - }; - - TestBed.configureTestingModule({ - imports: [ - CoreModule, - MatDialogModule - ], - declarations: [ - FolderDialogComponent - ], - providers: [ - { provide: MatDialogRef, useValue: dialogRef } - ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(FolderDialogComponent); - component = fixture.componentInstance; - - nodesApi = TestBed.get(NodesApiService); - notificationService = TestBed.get(NotificationService); - - translationService = TestBed.get(TranslationService); - spyOn(translationService, 'get').and.returnValue(Observable.of('message')); - }); - - describe('Edit', () => { - - beforeEach(() => { - component.data = { - folder: { - id: 'node-id', - name: 'folder-name', - properties: { - ['cm:description']: 'folder-description' - } - } - }; - component.ngOnInit(); - }); - - it('should init form with folder name and description', () => { - expect(component.name).toBe('folder-name'); - expect(component.description).toBe('folder-description'); - }); - - it('should update form input', () => { - component.form.controls['name'].setValue('folder-name-update'); - component.form.controls['description'].setValue('folder-description-update'); - - expect(component.name).toBe('folder-name-update'); - expect(component.description).toBe('folder-description-update'); - }); - - it('should submit updated values if form is valid', () => { - spyOn(nodesApi, 'updateNode').and.returnValue(Observable.of({})); - - component.form.controls['name'].setValue('folder-name-update'); - component.form.controls['description'].setValue('folder-description-update'); - - component.submit(); - - expect(nodesApi.updateNode).toHaveBeenCalledWith( - 'node-id', - { - name: 'folder-name-update', - properties: { - 'cm:title': 'folder-name-update', - 'cm:description': 'folder-description-update' - } - } - ); - }); - - it('should call dialog to close with form data when submit is succesfluly', () => { - const folder = { - data: 'folder-data' - }; - - spyOn(nodesApi, 'updateNode').and.returnValue(Observable.of(folder)); - - component.submit(); - - expect(dialogRef.close).toHaveBeenCalledWith(folder); - }); - - it('should not submit if form is invalid', () => { - spyOn(nodesApi, 'updateNode'); - - component.form.controls['name'].setValue(''); - component.form.controls['description'].setValue(''); - - component.submit(); - - expect(component.form.valid).toBe(false); - expect(nodesApi.updateNode).not.toHaveBeenCalled(); - }); - - it('should not call dialog to close if submit fails', () => { - spyOn(nodesApi, 'updateNode').and.returnValue(Observable.throw('error')); - spyOn(component, 'handleError').and.callFake(val => val); - - component.submit(); - - expect(component.handleError).toHaveBeenCalled(); - expect(dialogRef.close).not.toHaveBeenCalled(); - }); - }); - - describe('Create', () => { - beforeEach(() => { - component.data = { - parentNodeId: 'parentNodeId', - folder: null - }; - component.ngOnInit(); - }); - - it('should init form with empty inputs', () => { - expect(component.name).toBe(''); - expect(component.description).toBe(''); - }); - - it('should update form input', () => { - component.form.controls['name'].setValue('folder-name-update'); - component.form.controls['description'].setValue('folder-description-update'); - - expect(component.name).toBe('folder-name-update'); - expect(component.description).toBe('folder-description-update'); - }); - - it('should submit updated values if form is valid', () => { - spyOn(nodesApi, 'createFolder').and.returnValue(Observable.of({})); - - component.form.controls['name'].setValue('folder-name-update'); - component.form.controls['description'].setValue('folder-description-update'); - - component.submit(); - - expect(nodesApi.createFolder).toHaveBeenCalledWith( - 'parentNodeId', - { - name: 'folder-name-update', - properties: { - 'cm:title': 'folder-name-update', - 'cm:description': 'folder-description-update' - } - } - ); - }); - - it('should call dialog to close with form data when submit is succesfluly', () => { - const folder = { - data: 'folder-data' - }; - - component.form.controls['name'].setValue('name'); - component.form.controls['description'].setValue('description'); - - spyOn(nodesApi, 'createFolder').and.returnValue(Observable.of(folder)); - - component.submit(); - - expect(dialogRef.close).toHaveBeenCalledWith(folder); - }); - - it('should not submit if form is invalid', () => { - spyOn(nodesApi, 'createFolder'); - - component.form.controls['name'].setValue(''); - component.form.controls['description'].setValue(''); - - component.submit(); - - expect(component.form.valid).toBe(false); - expect(nodesApi.createFolder).not.toHaveBeenCalled(); - }); - - it('should not call dialog to close if submit fails', () => { - spyOn(nodesApi, 'createFolder').and.returnValue(Observable.throw('error')); - spyOn(component, 'handleError').and.callFake(val => val); - - component.form.controls['name'].setValue('name'); - component.form.controls['description'].setValue('description'); - - component.submit(); - - expect(component.handleError).toHaveBeenCalled(); - expect(dialogRef.close).not.toHaveBeenCalled(); - }); - }); - - describe('handleError()', () => { - it('should raise error for 409', () => { - spyOn(notificationService, 'openSnackMessage').and.stub(); - - const error = { - message: '{ "error": { "statusCode" : 409 } }' - }; - - component.handleError(error); - - expect(notificationService.openSnackMessage).toHaveBeenCalled(); - expect(translationService.get).toHaveBeenCalledWith('APP.MESSAGES.ERRORS.EXISTENT_FOLDER'); - }); - - it('should raise generic error', () => { - spyOn(notificationService, 'openSnackMessage').and.stub(); - - const error = { - message: '{ "error": { "statusCode" : 123 } }' - }; - - component.handleError(error); - - expect(notificationService.openSnackMessage).toHaveBeenCalled(); - expect(translationService.get).toHaveBeenCalledWith('APP.MESSAGES.ERRORS.GENERIC'); - }); - }); -}); diff --git a/src/app/common/dialogs/folder-dialog.component.ts b/src/app/common/dialogs/folder-dialog.component.ts deleted file mode 100644 index e8a395511..000000000 --- a/src/app/common/dialogs/folder-dialog.component.ts +++ /dev/null @@ -1,138 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Observable } from 'rxjs/Rx'; - -import { Component, Inject, Optional, OnInit } from '@angular/core'; -import { FormGroup, FormBuilder, Validators } from '@angular/forms'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; - -import { TranslationService, NodesApiService, NotificationService } from 'ng2-alfresco-core'; -import { MinimalNodeEntryEntity } from 'alfresco-js-api'; - -import { forbidSpecialCharacters, forbidEndingDot, forbidOnlySpaces } from './folder-name.validators'; - -@Component({ - selector: 'app-folder-dialog', - templateUrl: './folder-dialog.component.html' -}) -export class FolderDialogComponent implements OnInit { - form: FormGroup; - folder: MinimalNodeEntryEntity = null; - - constructor( - private formBuilder: FormBuilder, - private dialog: MatDialogRef, - private nodesApi: NodesApiService, - private translation: TranslationService, - private notification: NotificationService, - @Optional() - @Inject(MAT_DIALOG_DATA) - public data: any - ) {} - - get editing(): boolean { - return !!this.data.folder; - } - - ngOnInit() { - const { folder } = this.data; - let name = '', description = ''; - - if (folder) { - const { properties } = folder; - - name = folder.name || ''; - description = properties ? properties['cm:description'] : ''; - } - - const validators = { - name: [ - Validators.required, - forbidSpecialCharacters, - forbidEndingDot, - forbidOnlySpaces - ] - }; - - this.form = this.formBuilder.group({ - name: [ name, validators.name ], - description: [ description ] - }); - } - - get name(): string { - const { name } = this.form.value; - - return (name || '').trim(); - } - - get description(): string { - const { description } = this.form.value; - - return (description || '').trim(); - } - - private get properties(): any { - const { name: title, description } = this; - - return { - 'cm:title': title, - 'cm:description': description - }; - } - - private create(): Observable { - const { name, properties, nodesApi, data: { parentNodeId} } = this; - return nodesApi.createFolder(parentNodeId, { name, properties }); - } - - private edit(): Observable { - const { name, properties, nodesApi, data: { folder: { id: nodeId }} } = this; - return nodesApi.updateNode(nodeId, { name, properties }); - } - - submit() { - const { form, dialog, editing } = this; - - if (!form.valid) { return; } - - (editing ? this.edit() : this.create()) - .subscribe( - (folder: MinimalNodeEntryEntity) => dialog.close(folder), - (error) => this.handleError(error) - ); - } - - handleError(error: any): any { - let i18nMessageString = 'APP.MESSAGES.ERRORS.GENERIC'; - - try { - const { error: { statusCode } } = JSON.parse(error.message); - - if (statusCode === 409) { - i18nMessageString = 'APP.MESSAGES.ERRORS.EXISTENT_FOLDER'; - } - } catch (err) { /* Do nothing, keep the original message */ } - - this.translation.get(i18nMessageString).subscribe(message => { - this.notification.openSnackMessage(message, 3000); - }); - - return error; - } -} diff --git a/src/app/common/dialogs/folder-name.validators.ts b/src/app/common/dialogs/folder-name.validators.ts deleted file mode 100644 index 714ac127f..000000000 --- a/src/app/common/dialogs/folder-name.validators.ts +++ /dev/null @@ -1,45 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { FormControl } from '@angular/forms'; - -const I18N_ERRORS_PATH = 'APP.FOLDER_DIALOG.FOLDER_NAME.ERRORS'; - -export function forbidSpecialCharacters({ value }: FormControl) { - const specialCharacters: RegExp = /([\*\"\<\>\\\/\?\:\|])/; - const isValid: boolean = !specialCharacters.test(value); - - return (isValid) ? null : { - message: `${I18N_ERRORS_PATH}.SPECIAL_CHARACTERS` - }; -} - -export function forbidEndingDot({ value }: FormControl) { - const isValid: boolean = ((value || '').split('').pop() !== '.'); - - return isValid ? null : { - message: `${I18N_ERRORS_PATH}.ENDING_DOT` - }; -} - -export function forbidOnlySpaces({ value }: FormControl) { - const isValid: boolean = !!((value || '')).trim(); - - return isValid ? null : { - message: `${I18N_ERRORS_PATH}.ONLY_SPACES` - }; -} diff --git a/src/app/common/directives/folder-create.directive.spec.ts b/src/app/common/directives/folder-create.directive.spec.ts deleted file mode 100644 index a77ef95da..000000000 --- a/src/app/common/directives/folder-create.directive.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Component } from '@angular/core'; -import { Observable } from 'rxjs/Rx'; -import { MatDialogModule, MatDialog } from '@angular/material'; - -import { FolderCreateDirective } from './folder-create.directive'; -import { ContentManagementService } from '../services/content-management.service'; - -@Component({ - template: '
' -}) -class TestComponent { - parentNode = ''; -} - -describe('FolderCreateDirective', () => { - let fixture: ComponentFixture; - let element; - let node: any; - let dialog: MatDialog; - let contentService: ContentManagementService; - let dialogRefMock; - - const event: any = { - type: 'click', - preventDefault: () => null - }; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ MatDialogModule ], - declarations: [ - TestComponent, - FolderCreateDirective - ] - , - providers: [ - ContentManagementService - ] - }); - - fixture = TestBed.createComponent(TestComponent); - element = fixture.debugElement.query(By.directive(FolderCreateDirective)); - dialog = TestBed.get(MatDialog); - contentService = TestBed.get(ContentManagementService); - }); - - beforeEach(() => { - node = { entry: { id: 'nodeId' } }; - - dialogRefMock = { - afterClosed: val => Observable.of(val) - }; - - spyOn(dialog, 'open').and.returnValue(dialogRefMock); - }); - - it('emits createFolder event when input value is not undefined', () => { - spyOn(dialogRefMock, 'afterClosed').and.returnValue(Observable.of(node)); - - contentService.createFolder.subscribe((val) => { - expect(val).toBe(node); - }); - - element.triggerEventHandler('click', event); - fixture.detectChanges(); - }); - - it('does not emits createFolder event when input value is undefined', () => { - spyOn(dialogRefMock, 'afterClosed').and.returnValue(Observable.of(null)); - spyOn(contentService.createFolder, 'next'); - - element.triggerEventHandler('click', event); - fixture.detectChanges(); - - expect(contentService.createFolder.next).not.toHaveBeenCalled(); - }); -}); diff --git a/src/app/common/directives/folder-create.directive.ts b/src/app/common/directives/folder-create.directive.ts deleted file mode 100644 index 36d6a67f7..000000000 --- a/src/app/common/directives/folder-create.directive.ts +++ /dev/null @@ -1,66 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Directive, HostListener, Input } from '@angular/core'; -import { MatDialog, MatDialogConfig } from '@angular/material'; - -import { MinimalNodeEntryEntity } from 'alfresco-js-api'; - -import { FolderDialogComponent } from '../dialogs/folder-dialog.component'; -import { ContentManagementService } from '../services/content-management.service'; - -@Directive({ - selector: '[app-create-folder]' -}) -export class FolderCreateDirective { - static DIALOG_WIDTH: number = 400; - - @Input('app-create-folder') - parentNodeId: string; - - @HostListener('click', [ '$event' ]) - onClick(event) { - event.preventDefault(); - this.openDialog(); - } - - constructor( - public dialogRef: MatDialog, - public content: ContentManagementService - ) {} - - private get dialogConfig(): MatDialogConfig { - const { DIALOG_WIDTH: width } = FolderCreateDirective; - const { parentNodeId } = this; - - return { - data: { parentNodeId }, - width: `${width}px` - }; - } - - private openDialog(): void { - const { dialogRef, dialogConfig, content } = this; - const dialogInstance = dialogRef.open(FolderDialogComponent, dialogConfig); - - dialogInstance.afterClosed().subscribe((node: MinimalNodeEntryEntity) => { - if (node) { - content.createFolder.next(node); - } - }); - } -} diff --git a/src/app/common/directives/folder-edit.directive.spec.ts b/src/app/common/directives/folder-edit.directive.spec.ts deleted file mode 100644 index a330ef9f8..000000000 --- a/src/app/common/directives/folder-edit.directive.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { Component } from '@angular/core'; -import { Observable } from 'rxjs/Rx'; -import { MatDialogModule, MatDialog } from '@angular/material'; - -import { FolderEditDirective } from './folder-edit.directive'; -import { ContentManagementService } from '../services/content-management.service'; - -@Component({ - template: '
' -}) -class TestComponent { - folder = {}; -} - -describe('FolderEditDirective', () => { - let fixture: ComponentFixture; - let element; - let node: any; - let dialog: MatDialog; - let contentService: ContentManagementService; - let dialogRefMock; - - const event = { - type: 'click', - preventDefault: () => null - }; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ MatDialogModule ], - declarations: [ - TestComponent, - FolderEditDirective - ] - , - providers: [ - ContentManagementService - ] - }); - - fixture = TestBed.createComponent(TestComponent); - element = fixture.debugElement.query(By.directive(FolderEditDirective)); - dialog = TestBed.get(MatDialog); - contentService = TestBed.get(ContentManagementService); - }); - - beforeEach(() => { - node = { entry: { id: 'folderId' } }; - - dialogRefMock = { - afterClosed: val => Observable.of(val) - }; - - spyOn(dialog, 'open').and.returnValue(dialogRefMock); - }); - - it('emits editFolder event when input value is not undefined', () => { - spyOn(dialogRefMock, 'afterClosed').and.returnValue(Observable.of(node)); - - contentService.createFolder.subscribe((val) => { - expect(val).toBe(node); - }); - - element.triggerEventHandler('click', event); - fixture.detectChanges(); - }); - - it('does not emits FolderEditDirective event when input value is undefined', () => { - spyOn(dialogRefMock, 'afterClosed').and.returnValue(Observable.of(null)); - spyOn(contentService.createFolder, 'next'); - - element.triggerEventHandler('click', event); - fixture.detectChanges(); - - expect(contentService.createFolder.next).not.toHaveBeenCalled(); - }); -}); diff --git a/src/app/common/directives/folder-edit.directive.ts b/src/app/common/directives/folder-edit.directive.ts deleted file mode 100644 index 482c510e5..000000000 --- a/src/app/common/directives/folder-edit.directive.ts +++ /dev/null @@ -1,67 +0,0 @@ -/*! - * @license - * Copyright 2017 Alfresco Software, Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Directive, HostListener, ElementRef, Input } from '@angular/core'; -import { MatDialog, MatDialogConfig } from '@angular/material'; - -import { MinimalNodeEntryEntity } from 'alfresco-js-api'; - -import { FolderDialogComponent } from '../dialogs/folder-dialog.component'; -import { ContentManagementService } from '../services/content-management.service'; - -@Directive({ - selector: '[app-edit-folder]' -}) -export class FolderEditDirective { - static DIALOG_WIDTH = 400; - - @Input('app-edit-folder') - folder: MinimalNodeEntryEntity; - - @HostListener('click', [ '$event' ]) - onClick(event) { - event.preventDefault(); - this.openDialog(); - } - - constructor( - public dialogRef: MatDialog, - public elementRef: ElementRef, - public content: ContentManagementService - ) {} - - private get dialogConfig(): MatDialogConfig { - const { DIALOG_WIDTH: width } = FolderEditDirective; - const { folder } = this; - - return { - data: { folder }, - width: `${width}px` - }; - } - - private openDialog(): void { - const { dialogRef, dialogConfig, content } = this; - const dialogInstance = dialogRef.open(FolderDialogComponent, dialogConfig); - - dialogInstance.afterClosed().subscribe((node: MinimalNodeEntryEntity) => { - if (node) { - content.editFolder.next(node); - } - }); - } -} diff --git a/src/app/common/services/content-management.service.ts b/src/app/common/services/content-management.service.ts index 3fcc47199..7aa324d71 100644 --- a/src/app/common/services/content-management.service.ts +++ b/src/app/common/services/content-management.service.ts @@ -18,12 +18,8 @@ import { Subject } from 'rxjs/Rx'; import { Injectable } from '@angular/core'; -import { MinimalNodeEntryEntity } from 'alfresco-js-api'; - @Injectable() export class ContentManagementService { - createFolder = new Subject(); - editFolder = new Subject(); deleteNode = new Subject(); moveNode = new Subject(); restoreNode = new Subject(); diff --git a/src/app/components/favorites/favorites.component.html b/src/app/components/favorites/favorites.component.html index 32d684417..1ec5194c5 100644 --- a/src/app/components/favorites/favorites.component.html +++ b/src/app/components/favorites/favorites.component.html @@ -25,7 +25,7 @@ mat-icon-button *ngIf="canEditFolder(documentList.selection)" title="{{ 'APP.ACTIONS.EDIT' | translate }}" - [app-edit-folder]="documentList.selection[0]?.entry"> + [adf-edit-folder]="documentList.selection[0]?.entry"> create diff --git a/src/app/components/favorites/favorites.component.spec.ts b/src/app/components/favorites/favorites.component.spec.ts index 0728982b9..ec8e88cdb 100644 --- a/src/app/components/favorites/favorites.component.spec.ts +++ b/src/app/components/favorites/favorites.component.spec.ts @@ -20,7 +20,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { TestBed, async } from '@angular/core/testing'; import { Observable } from 'rxjs/Rx'; -import { CoreModule, NodesApiService, AlfrescoApiService } from 'ng2-alfresco-core'; +import { CoreModule, NodesApiService, AlfrescoApiService, AlfrescoContentService } from 'ng2-alfresco-core'; import { CommonModule } from '../../common/common.module'; import { ContentManagementService } from '../../common/services/content-management.service'; @@ -32,6 +32,7 @@ describe('Favorites Routed Component', () => { let component: FavoritesComponent; let nodesApi: NodesApiService; let alfrescoApi: AlfrescoApiService; + let alfrescoContentService: AlfrescoContentService; let contentService: ContentManagementService; let router: Router; let page; @@ -80,6 +81,7 @@ describe('Favorites Routed Component', () => { nodesApi = TestBed.get(NodesApiService); alfrescoApi = TestBed.get(AlfrescoApiService); + alfrescoContentService = TestBed.get(AlfrescoContentService); contentService = TestBed.get(ContentManagementService); router = TestBed.get(Router); }); @@ -94,7 +96,7 @@ describe('Favorites Routed Component', () => { spyOn(component, 'refresh'); fixture.detectChanges(); - contentService.editFolder.next(null); + alfrescoContentService.folderEdit.next(null); expect(component.refresh).toHaveBeenCalled(); }); diff --git a/src/app/components/favorites/favorites.component.ts b/src/app/components/favorites/favorites.component.ts index cdb5daffd..92ebfdbe8 100644 --- a/src/app/components/favorites/favorites.component.ts +++ b/src/app/components/favorites/favorites.component.ts @@ -20,7 +20,7 @@ import { Router } from '@angular/router'; import { Subscription } from 'rxjs/Rx'; import { MinimalNodeEntryEntity, PathElementEntity, PathInfo } from 'alfresco-js-api'; -import { NodesApiService } from 'ng2-alfresco-core'; +import { AlfrescoContentService, NodesApiService } from 'ng2-alfresco-core'; import { DocumentListComponent } from 'ng2-alfresco-documentlist'; import { ContentManagementService } from '../../common/services/content-management.service'; @@ -41,12 +41,13 @@ export class FavoritesComponent extends PageComponent implements OnInit, OnDestr constructor( private router: Router, private nodesApi: NodesApiService, + private contentService: AlfrescoContentService, private content: ContentManagementService) { super(); } ngOnInit() { - this.onEditFolder = this.content.editFolder.subscribe(() => this.refresh()); + this.onEditFolder = this.contentService.folderEdit.subscribe(() => this.refresh()); this.onMoveNode = this.content.moveNode.subscribe(() => this.refresh()); this.onToggleFavorite = this.content.toggleFavorite .debounceTime(300).subscribe(() => this.refresh()); diff --git a/src/app/components/files/files.component.html b/src/app/components/files/files.component.html index 4fdd83895..2341d840a 100644 --- a/src/app/components/files/files.component.html +++ b/src/app/components/files/files.component.html @@ -27,7 +27,7 @@ mat-icon-button *ngIf="canEditFolder(documentList.selection)" title="{{ 'APP.ACTIONS.EDIT' | translate }}" - [app-edit-folder]="documentList.selection[0]?.entry"> + [adf-edit-folder]="documentList.selection[0]?.entry"> create diff --git a/src/app/components/files/files.component.spec.ts b/src/app/components/files/files.component.spec.ts index 63e87fe0d..622e3352e 100644 --- a/src/app/components/files/files.component.spec.ts +++ b/src/app/components/files/files.component.spec.ts @@ -170,13 +170,13 @@ describe('FilesComponent', () => { }); it('calls refresh onCreateFolder event', () => { - contentManagementService.createFolder.next(); + alfrescoContentService.folderCreate.next(); expect(component.load).toHaveBeenCalled(); }); it('calls refresh editFolder event', () => { - contentManagementService.editFolder.next(); + alfrescoContentService.folderEdit.next(); expect(component.load).toHaveBeenCalled(); }); diff --git a/src/app/components/files/files.component.ts b/src/app/components/files/files.component.ts index 45c2557f6..0a48e3794 100644 --- a/src/app/components/files/files.component.ts +++ b/src/app/components/files/files.component.ts @@ -16,7 +16,7 @@ */ import { Observable, Subscription } from 'rxjs/Rx'; -import { Component, ViewChild, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; +import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import { MinimalNodeEntity, MinimalNodeEntryEntity, PathElementEntity, NodePaging, PathElement } from 'alfresco-js-api'; import { UploadService, FileUploadEvent, NodesApiService, AlfrescoContentService, AlfrescoApiService } from 'ng2-alfresco-core'; @@ -60,7 +60,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy { } ngOnInit() { - const { route, contentManagementService, nodeActionsService, uploadService } = this; + const { route, contentManagementService, contentService, nodeActionsService, uploadService } = this; const { data } = route.snapshot; this.routeData = data; @@ -87,8 +87,8 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy { this.onCopyNode = nodeActionsService.contentCopied .subscribe((nodes) => this.onContentCopied(nodes)); - this.onCreateFolder = contentManagementService.createFolder.subscribe(() => this.load()); - this.onEditFolder = contentManagementService.editFolder.subscribe(() => this.load()); + this.onCreateFolder = contentService.folderCreate.subscribe(() => this.load()); + this.onEditFolder = contentService.folderEdit.subscribe(() => this.load()); this.onDeleteNode = contentManagementService.deleteNode.subscribe(() => this.load()); this.onMoveNode = contentManagementService.moveNode.subscribe(() => this.load()); this.onRestoreNode = contentManagementService.restoreNode.subscribe(() => this.load()); diff --git a/src/app/components/sidenav/sidenav.component.html b/src/app/components/sidenav/sidenav.component.html index 43fdaa621..73973dbfd 100644 --- a/src/app/components/sidenav/sidenav.component.html +++ b/src/app/components/sidenav/sidenav.component.html @@ -8,8 +8,8 @@