Merge pull request #64 from Alfresco/development

Sprint 25
This commit is contained in:
Cilibiu Bogdan 2017-11-20 13:00:21 +02:00 committed by GitHub
commit ecbb57d64f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
63 changed files with 2187 additions and 717 deletions

View File

@ -11,6 +11,7 @@
"assets",
"favicon-96x96.png",
"app.config.json",
"versions.json",
{ "glob": "**/*", "input": "../node_modules/ng2-alfresco-core/bundles/assets", "output": "./assets/" },
{ "glob": "**/*", "input": "../node_modules/ng2-alfresco-datatable/bundles/assets", "output": "./assets/" },

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
/dist
/tmp
/out-tsc
/src/versions.json
# dependencies
/node_modules

View File

@ -1,5 +1,7 @@
# Alfresco Content App
[Public documentation](https://alfresco.github.io/alfresco-content-app/)
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.4.7.
## Development server
@ -23,6 +25,25 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Running documentation locally
For development purposes, you can run and test documentation locally.
That is useful when working in different branches instead of a `master` one.
Run the following command to install the lightweight development server [wsrv](https://denysvuika.gitlab.io/wsrv/#/):
```sh
npm install -g wsrv
```
Now you can use the next command to serve the documentation folder in the browser:
```sh
wsrv docs/ -s -l -o
```
The browser page is going to automatically reload upon changes.
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@ -1,28 +1,15 @@
# Alfresco Content App
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.4.7.
## Prerequisites
## Development server
- Alfresco Content Services (Community) or Alfresco Content Services 5.2.2 (Enterprise)
- [node.js](https://nodejs.org/en/) 8.9.1 or later
Run `ng start` for a dev server. Navigate to `http://localhost:3000/` (opens by default).
The app will automatically reload if you change any of the source files.
## Building and running locally
## Code scaffolding
Please refer to the [developer docs](/build) to get more details on building and running application on your local machine.
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Using with Docker
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
The Content App provides a "Dockerfile" and "docker-compose" files to aid in running application in a container.
Please refer to the "[Using with Docker](/docker)" article for more details.

49
docs/build.md Normal file
View File

@ -0,0 +1,49 @@
# Building from source code
The Content App is based on [Angular CLI](https://cli.angular.io), and you can use all the commands, generators and blueprints supported by the CLI.
Use the following commands to clone a copy of the project, install dependencies and run it.
```sh
git clone https://github.com/Alfresco/alfresco-content-app.git
cd alfresco-content-app
npm install
npm start
```
The application run at port 3000 by default, and should automatically open in the default browser once project compilation finishes.
## Proxy settings
The Content App provides a proxy configuration for local development server
that allows you to address specific scenarios with CORS and native authentication dialogue.
You can find settings in the "proxy.conf.js" file in the project root directory.
<p class="warning">
The proxy settings get automatically applied every time you run the application with "npm start" script.
You must restart the application every time you change the setting values.
</p>
## Running documentation locally
For development purposes, you can run and test documentation locally.
That is useful when working in different branches instead of a `master` one.
Run the following command to install the lightweight development server [wsrv](https://denysvuika.gitlab.io/wsrv/#/):
```sh
npm install -g wsrv
```
Now you can use the next command to serve the documentation folder in the browser:
```sh
wsrv docs/ -s -l -o
```
The browser page is going to automatically reload upon changes.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

111
docs/configuration.md Normal file
View File

@ -0,0 +1,111 @@
# Application Configuration
The Content Application provides support for a global settings file `app.config.json` that you can use to customise the behaviour of ACA and ADF components.
## Server settings
Once the Content Application starts, it needs to know where the Alfresco Content Services (either Community or Enterprise) server is.
The "ecmHost" property allows you to set the address of the server using the dynamic or static format.
### Dynamic address
The example below demonstrates the most common dynamic format for development environment:
```json
{
"ecmHost": "http://{hostname}{:port}",
...
}
```
The configuration above assumes you are running ACS and Content App on the same server and port
and allows deploying to different servers having the same unified configuration file.
For example, a proxy server at `localhost:3000` hosting the Content App as the root application,
and `localhost:3000/alfresco` for the ACS repository.
At runtime, the application is going to automatically substitute the "{hostname}" value with the original hostname.
Optionally it can also use the value of the original port if present, for example, "3000" at local machines, or skip the value for port 80.
### Static address
Alternatively, you can provide a static address for the ACS services if necessary:
```json
{
"ecmHost": "http://localhost:3000",
...
}
```
## Application settings
The are many settings you can change to alter the default behaviour of the application.
### Application Name
The following block allows you to change the name of the application.
```json
{
...,
"application": {
"name": "Alfresco Example Content Application"
}
}
```
The value of the `application.name` key gets appended to every browser tab title at runtime
with the format `[page title] - [application name]`,
for example: "Personal Files - Alfresco Example Content Application".
### Restricted content
You can restrict users from uploading certain types of files and folders by setting or extending the list of rules at the "files.excluded" path.
By default, the application ships with the following rules already predefined:
```json
{
...,
"files": {
"excluded": [
".DS_Store",
"desktop.ini",
"thumbs.db",
".git"
]
},
...
}
```
<p class="tip">
You can get more details on the supported rules in the following article: [Upload Service](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/upload.service.md).
</p>
### Pagination settings
You can change the default settings of the pagination that gets applied to all the document lists in the application.
```json
{
...,
"document-list": {
"supportedPageSizes": [
25,
50,
100
]
},
...
}
```
## Your custom settings
You can store any information in the application configuration file, and access it at runtime by utilising the `AppConfigService` service provided by the ADF framework.
<p class="tip">
Please refer to the [AppConfigService](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/app-config.service.md) documentation to get more details on Application Configuration features and API available.
</p>

21
docs/cors.md Normal file
View File

@ -0,0 +1,21 @@
# Cross Origin Resource Sharing (CORS)
## Chrome Workaround
For the Chrome you can use the following plugin that allows you toggle CORS:
[Allow-Control-Allow-Origin](https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi)
## Firefox Workaround
FireFox users can try the following plugin: [CORS Everywhere](https://addons.mozilla.org/en-Gb/firefox/addon/cors-everywhere/)
## Safari Workaround
If you are developing or testing with Safari then you can use the "Develop" menu to toggle the CORS mode.
Please note that page must be reloaded every time you change CORS settings.
![](images/safari-develop-menu.png)
## See also
- [Using CORS](https://www.html5rocks.com/en/tutorials/cors/)

88
docs/docker.md Normal file
View File

@ -0,0 +1,88 @@
# Using with Docker
<p class="warning">
This article assumes you are familiar with Docker and know how to create images and containers.
</p>
You can create a Docker image to run Alfresco Content App in the container.
## Building from source code
You need to run the following commands to build the project from the source code:
```sh
npm install
npm run build
```
That produces a build in the "dist" folder that you can use with a Docker image.
<p class="tip">
Also, you may need to update the `dist/app.config.json` file with the settings relevant to your scenario.
</p>
## Creating an image
The Content Application provides a "Dockerfile" file in the repository root.
You can build the image with the following command:
```sh
docker image build -t content-app .
```
## Running image in a container
To run the image locally, you can use the following command:
```sh
docker container run -p 80:80 --rm content-app
```
Navigate to "http://localhost" to access the running application.
## Docker Compose file
You can also use the "docker-compose" file for local development and testing.
To build and run container run the following command in the root project folder:
```sh
docker-compose up
```
To perform a cleanup operation, use the next command:
```sh
docker-compose down --rmi all
```
Navigate to "http://localhost:3000" to access the running application.
<p class="warning">
Please keep in mind that you should manually build the project every time you want to publish the image or run it locally with the container.
</p>
## Using with local ACS setup
If you run ACS at port 8080 as a Docker container (typical development configuration), you can use the following command to build the project before creating an image:
```sh
npm run build:dev
```
The command above updates the "dist/app.config.json" file to point the Content App to "http://localhost:8080" upon startup.
Alternatively, you can change the configuration file manually before generating an image.
So the development workflow, in this case, is going to be:
```sh
npm run build:dev
docker-compose up
```
Navigate to "http://localhost:3000" to access the running application.
To perform a cleanup operation, use the next command:
```sh
docker-compose down --rmi all
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

View File

@ -17,6 +17,32 @@
{
title: 'Home',
path: '/'
},
{
title: 'Building',
path: 'build'
},
{
title: 'Docker',
path: 'docker'
},
{
title: 'Guides',
type: 'dropdown',
items: [
{
title: 'Building',
path: 'build'
},
{
title: 'CORS',
path: 'cors'
},
{
title: 'Configuration',
path: 'configuration'
}
]
}
],
icons: [

View File

@ -31,11 +31,23 @@ export class DataTable extends Component {
`,
body: 'table > tbody',
row: 'tr'
row: 'tr',
cell: 'td',
emptyListContainer: 'td.adf-no-content-container',
emptyFolderDragAndDrop: '.adf-empty-list_template .adf-empty-folder',
emptyListTitle: 'div .empty-list__title',
emptyListText: 'div .empty-list__text'
};
private head: ElementFinder = this.component.element(by.css(DataTable.selectors.head));
private body: ElementFinder = this.component.element(by.css(DataTable.selectors.body));
head: ElementFinder = this.component.element(by.css(DataTable.selectors.head));
body: ElementFinder = this.component.element(by.css(DataTable.selectors.body));
cell = by.css(DataTable.selectors.cell);
emptyList: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListContainer));
emptyFolderDragAndDrop: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyFolderDragAndDrop));
emptyListTitle: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListTitle));
emptyListText: ElementArrayFinder = this.component.all(by.css(DataTable.selectors.emptyListText));
constructor(ancestor?: ElementFinder) {
super(DataTable.selectors.root, ancestor);
@ -46,7 +58,9 @@ export class DataTable extends Component {
return browser.wait(EC.presenceOf(this.head), BROWSER_WAIT_TIMEOUT);
}
// waitForEmptyState() {}
waitForEmptyState() {
return browser.wait(EC.presenceOf(this.emptyList), BROWSER_WAIT_TIMEOUT);
}
// Header/Column methods
getColumnHeaders(): ElementArrayFinder {
@ -107,4 +121,37 @@ export class DataTable extends Component {
return click.perform();
}
// empty state methods
isEmptyList(): promise.Promise<boolean> {
return this.emptyList.isPresent();
}
isEmptyWithDragAndDrop(): promise.Promise<boolean> {
return this.emptyFolderDragAndDrop.isDisplayed();
}
getEmptyDragAndDropText(): promise.Promise<string> {
return this.isEmptyWithDragAndDrop()
.then(() => {
return this.emptyFolderDragAndDrop.getText();
})
.catch(() => '');
}
getEmptyStateTitle(): promise.Promise<string> {
return this.isEmptyList()
.then(() => {
return this.emptyListTitle.getText();
})
.catch(() => '');
}
getEmptyStateText(): promise.Promise<string> {
return this.isEmptyList()
.then(() => {
return this.emptyListText.getText();
})
.catch(() => '');
}
}

View File

@ -54,4 +54,8 @@ export class Menu extends Component {
clickMenuItem(label: string): promise.Promise<void> {
return this.getItemByLabel(label).click();
}
isMenuItemPresent(title: string): promise.Promise<boolean> {
return this.component.element(by.cssContainingText(Menu.selectors.item, title)).isPresent();
}
}

View File

@ -36,6 +36,10 @@ export class ToolbarActions extends Component {
return this.buttons.count().then(count => (count === 0));
}
isButtonPresent(title: string): promise.Promise<boolean> {
return this.component.element(by.css(`${ToolbarActions.selectors.button}[title="${title}"]`)).isPresent();
}
getButtonByLabel(label: string): ElementFinder {
return this.component.element(by.cssContainingText(ToolbarActions.selectors.button, label));
}

View File

@ -18,6 +18,7 @@
import { browser, ExpectedConditions as EC, promise } from 'protractor';
import { LoginComponent } from '../components/components';
import { Page } from './page';
import { Utils } from '../utilities/utils';
import {
ADMIN_USERNAME,
@ -38,20 +39,29 @@ export class LoginPage extends Page {
load(): promise.Promise<any> {
return super.load().then(() => {
const { submitButton } = this.login;
const hasSumbitButton = EC.presenceOf(submitButton);
const hasSubmitButton = EC.presenceOf(submitButton);
return browser.wait(hasSumbitButton, BROWSER_WAIT_TIMEOUT)
.then(() => browser.executeScript('window.localStorage.clear();'))
.then(() => browser.executeScript('window.sessionStorage.clear();'))
.then(() => browser.driver.manage().deleteAllCookies());
return browser.wait(hasSubmitButton, BROWSER_WAIT_TIMEOUT)
.then(() => Utils.clearLocalStorage())
.then(() => browser.manage().deleteAllCookies());
});
}
loginWith(username: string, password: string): promise.Promise<void> {
return this.login.enterCredentials(username, password).submit();
loginWith(username: string, password?: string): promise.Promise<any> {
const pass = password || username;
return this.login.enterCredentials(username, pass).submit()
.then(() => super.waitForApp());
}
loginWithAdmin(): promise.Promise<any> {
return this.loginWith(ADMIN_USERNAME, ADMIN_PASSWORD);
}
tryLoginWith(username: string, password?: string): promise.Promise<void> {
const pass = password || username;
return this.login.enterCredentials(username, pass).submit()
.then(() => {
browser.wait(EC.presenceOf(this.login.errorMessage), BROWSER_WAIT_TIMEOUT);
});
}
}

View File

@ -18,6 +18,7 @@
import { promise } from 'protractor';
import { Page } from './page';
import { APP_ROUTES } from '../configs';
import { Utils } from '../utilities/utils';
export class LogoutPage extends Page {
/** @override */
@ -27,6 +28,8 @@ export class LogoutPage extends Page {
/** @override */
load(): promise.Promise<any> {
return super.load();
return Utils.clearLocalStorage()
.then(() => Utils.clearSessionStorage())
.then(() => super.load());
}
}

View File

@ -15,18 +15,21 @@
* limitations under the License.
*/
import { browser, element, by, ElementFinder, promise } from 'protractor';
import { browser, element, by, ElementFinder, promise, ExpectedConditions as EC } from 'protractor';
import { BROWSER_WAIT_TIMEOUT } from './../configs';
export abstract class Page {
private static USE_HASH_STRATEGY = false;
private locators = {
app: by.css('app-root'),
layout: by.css('app-layout'),
overlay: by.css('.cdk-overlay-container'),
snackBar: by.css('simple-snack-bar')
};
public app: ElementFinder = element(this.locators.app);
public layout: ElementFinder = element(this.locators.layout);
public overlay: ElementFinder = element(this.locators.overlay);
public snackBar: ElementFinder = element(this.locators.snackBar);
@ -43,6 +46,10 @@ export abstract class Page {
return browser.get(path);
}
waitForApp() {
return browser.wait(EC.presenceOf(this.layout), BROWSER_WAIT_TIMEOUT);
}
refresh(): promise.Promise<void> {
return browser.refresh();
}

View File

@ -24,21 +24,20 @@ 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 username = `user-${Utils.random()}`;
const parent = 'parent-folder';
const folderName1 = 'my-folder1';
const folderName2 = 'my-folder2';
const parent = `parent-${Utils.random()}`;
const folderName1 = `folder-${Utils.random()}`;
const folderName2 = `folder-${Utils.random()}`;
const folderDescription = 'description of my folder';
const duplicateFolderName = 'duplicate-folder-name';
const nameWithSpaces = ' folder-name ';
const duplicateFolderName = `folder-${Utils.random()}`;
const nameWithSpaces = ` folder-${Utils.random()} `;
const siteName = 'site-private';
const siteName = `site-private-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
user: new RepoClient(username, username)
};
const loginPage = new LoginPage();
@ -57,14 +56,14 @@ describe('Create folder', () => {
}
beforeAll(done => {
apis.admin.people.createUser(username, password)
apis.admin.people.createUser(username)
.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);
.then(() => loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done));
});
beforeEach(done => {
@ -80,9 +79,9 @@ describe('Create folder', () => {
afterAll(done => {
Promise
.all([
apis.admin.sites.deleteSite(siteName, true),
apis.user.nodes.deleteNodes([ parent ]),
logoutPage.load()
.then(() => Utils.clearLocalStorage())
])
.then(done);
});
@ -128,9 +127,7 @@ describe('Create folder', () => {
})
.then(() => {
apis.user.nodes.getNodeDescription(folderName2)
.then((description) => {
expect(description).toEqual(folderDescription, 'Description is not correct');
});
.then((description) => expect(description).toEqual(folderDescription));
})
);
});

View File

@ -23,24 +23,23 @@ import { CreateOrEditFolderDialog } from '../../components/dialog/create-edit-fo
import { Utils } from '../../utilities/utils';
describe('Edit folder', () => {
const username = 'john.doe';
const password = 'john.doe';
const username = `user-${Utils.random()}`;
const parent = 'parent-folder';
const folderName = 'my-folder';
const parent = `parent-${Utils.random()}`;
const folderName = `folder-${Utils.random()}`;
const folderDescription = 'my folder description';
const folderNameToEdit = 'folder-to-be-edited';
const duplicateFolderName = 'duplicate-folder-name';
const folderNameToEdit = `folder-${Utils.random()}`;
const duplicateFolderName = `folder-${Utils.random()}`;
const folderNameEdited = 'edited-folder';
const folderNameEdited = `folder-${Utils.random()}`;
const folderDescriptionEdited = 'my folder description edited';
const siteName = 'site-private';
const siteName = `site-private-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
user: new RepoClient(username, username)
};
const loginPage = new LoginPage();
@ -53,18 +52,18 @@ describe('Edit folder', () => {
beforeAll(done => {
Promise
.all([
apis.admin.people.createUser(username, password),
apis.admin.people.createUser(username),
apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PRIVATE)
.then(() => apis.admin.nodes.createFolders([ folderName ], `Sites/${siteName}/documentLibrary`))
])
.then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_CONSUMER))
.then(() => Promise.all([
apis.user.nodes.createNodeWithProperties( folderName, '', folderDescription, parent ),
apis.user.nodes.createFolders([ folderNameToEdit, duplicateFolderName ], parent),
loginPage.load()
apis.user.nodes.createFolders([ folderNameToEdit, duplicateFolderName ], parent)
]))
.then(() => loginPage.loginWith(username, password))
.then(done);
.then(() => loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done));
});
beforeEach(done => {
@ -83,20 +82,10 @@ describe('Edit folder', () => {
apis.admin.sites.deleteSite(siteName, true),
apis.user.nodes.deleteNodes([ parent ]),
logoutPage.load()
.then(() => Utils.clearLocalStorage())
])
.then(done);
});
it('button is enabled when having permissions', () => {
personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent)
.then(() => dataTable.clickOnRowByContainingText(folderName)
.then(() => {
expect(editButton.isEnabled()).toBe(true);
})
);
});
it('dialog UI defaults', () => {
personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent)
.then(() => dataTable.clickOnRowByContainingText(folderName)
@ -111,7 +100,7 @@ describe('Edit folder', () => {
);
});
it('folder properties are modified when pressing OK', () => {
it('properties are modified when pressing OK', () => {
personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent)
.then(() => dataTable.clickOnRowByContainingText(folderNameToEdit)
.then(() => editButton.click())
@ -136,17 +125,6 @@ describe('Edit folder', () => {
);
});
it('button is not displayed when not enough permissions', () => {
const fileLibrariesPage = new BrowsingPage(APP_ROUTES.FILE_LIBRARIES);
fileLibrariesPage.sidenav.navigateToLinkByLabel('File Libraries')
.then(() => fileLibrariesPage.dataTable.doubleClickOnRowByContainingText(siteName))
.then(() => fileLibrariesPage.dataTable.clickOnRowByContainingText(folderName))
.then(() => {
expect(editButton.isPresent()).not.toBe(true, 'edit button is displayed');
});
});
it('with empty folder name', () => {
personalFilesPage.dataTable.doubleClickOnRowByContainingText(parent)
.then(() => dataTable.clickOnRowByContainingText(folderName)

View File

@ -0,0 +1,540 @@
/*!
* @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 { browser, protractor, promise } from 'protractor';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES, SIDEBAR_LABELS } from '../../configs';
import { RepoClient } from '../../utilities/repo-client/repo-client';
import { Utils } from '../../utilities/utils';
describe('Toolbar actions - single selection : ', () => {
const username = `user-${Utils.random()}`;
const username2 = `user-${Utils.random()}`;
const fileUser = `file-${Utils.random()}.txt`;
let fileUserId;
const folderUser = `folder-${Utils.random()}`;
let folderUserId;
const fileForDelete = `file-${Utils.random()}.txt`;
let fileForDeleteId;
const folderForDelete = `folder-${Utils.random()}`;
let folderForDeleteId;
const siteName = `site-private-${Utils.random()}`;
const fileAdmin = `file-${Utils.random()}.txt`;
const folderAdmin = `folder-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, username)
};
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const page = new BrowsingPage();
const { dataTable } = page;
const { toolbar } = page;
beforeAll(done => {
apis.admin.people.createUser(username)
.then(() => apis.user.nodes.createFiles([ fileUser ]).then(resp => { fileUserId = resp.data.entry.id; }))
.then(() => apis.user.nodes.createFiles([ fileForDelete ]).then(resp => { fileForDeleteId = resp.data.entry.id; }))
.then(() => apis.user.nodes.createFolders([ folderForDelete ]).then((resp) => { folderForDeleteId = resp.data.entry.id; }))
.then(() => apis.user.nodes.createFolders([ folderUser ]).then(resp => { folderUserId = resp.data.entry.id; }))
.then(() => apis.user.shared.shareFileById(fileUserId))
.then(() => apis.user.favorites.addFavoriteById('file', fileUserId))
.then(() => apis.user.favorites.addFavoriteById('folder', folderUserId))
.then(done);
});
afterAll(done => {
Promise.all([
apis.user.nodes.deleteNodeById(fileUserId),
apis.user.nodes.deleteNodeById(folderUserId),
logoutPage.load()
])
.then(done);
});
xit('');
describe('Personal Files', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.PERSONAL_FILES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`);
});
});
it('actions are displayed when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${folderUser}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
});
dataTable.clickOnRowByContainingText(fileUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
})
.then(() => browser.$('body').click());
});
it('correct actions appear when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(false, `View is displayed for ${folderUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`);
});
dataTable.clickOnRowByContainingText(folderUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`);
})
.then(() => browser.$('body').click());
});
});
describe('File Libraries', () => {
beforeAll(done => {
apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC)
.then(() => apis.admin.people.createUser(username2))
.then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_MANAGER))
.then(() => apis.admin.sites.addSiteMember(siteName, username2, SITE_ROLES.SITE_CONSUMER))
.then(() => apis.admin.nodes.createFiles([ fileAdmin ], `Sites/${siteName}/documentLibrary`))
.then(() => apis.admin.nodes.createFolders([ folderAdmin ], `Sites/${siteName}/documentLibrary`))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)
.then(() => dataTable.waitForHeader())
.then(() => dataTable.doubleClickOnRowByContainingText(siteName))
.then(() => dataTable.waitForHeader())
.then(done);
});
xit('');
describe('user is Manager', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileAdmin}`);
});
});
it('actions are displayed when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${folderAdmin}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileAdmin}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileAdmin}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileAdmin}`);
});
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileAdmin}`);
})
.then(() => browser.$('body').click());
});
it('correct actions appear when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(false, `View is displayed for ${folderAdmin}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderAdmin}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderAdmin}`);
});
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderAdmin}`);
})
.then(() => browser.$('body').click());
});
});
describe('user is Consumer', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username2))
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileAdmin}`);
});
});
it('actions are displayed when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${folderAdmin}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileAdmin}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileAdmin}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileAdmin}`);
});
dataTable.clickOnRowByContainingText(fileAdmin)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${fileAdmin}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileAdmin}`);
})
.then(() => browser.$('body').click());
});
it('correct actions appear when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(false, `View is displayed for ${folderAdmin}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderAdmin}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${folderAdmin}`);
});
dataTable.clickOnRowByContainingText(folderAdmin)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${folderAdmin}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderAdmin}`);
})
.then(() => browser.$('body').click());
});
});
});
describe('Shared Files', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.SHARED_FILES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
});
dataTable.clickOnRowByContainingText(fileUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
})
.then(() => browser.$('body').click());
});
});
describe('Recent Files', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.RECENT_FILES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
});
dataTable.clickOnRowByContainingText(fileUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
})
.then(() => browser.$('body').click());
});
});
describe('Favorites', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FAVORITES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`);
});
});
it('actions are displayed when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderUser)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${folderUser}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
});
dataTable.clickOnRowByContainingText(fileUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
})
.then(() => browser.$('body').click());
});
it('correct actions appear when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderUser)
.then(() => {
expect(toolbar.actions.isButtonPresent('View')).toBe(false, `View is displayed for ${folderUser}`);
expect(toolbar.actions.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`);
expect(toolbar.actions.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`);
});
dataTable.clickOnRowByContainingText(folderUser)
.then(() => toolbar.actions.openMoreMenu())
.then(menu => {
expect(menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`);
expect(menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`);
})
.then(() => browser.$('body').click());
});
});
describe('Trash', () => {
beforeAll(done => {
apis.user.nodes.deleteNodeById(fileForDeleteId, false)
.then(() => apis.user.nodes.deleteNodeById(folderForDeleteId, false))
.then(() => loginPage.load())
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.TRASH)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
Promise.all([
apis.user.trashcan.permanentlyDelete(fileForDeleteId),
apis.user.trashcan.permanentlyDelete(folderForDeleteId),
logoutPage.load()
])
.then(done);
});
it('actions are not displayed when no item is selected', () => {
expect(toolbar.actions.isEmpty()).toBe(true, `actions displayed though nothing selected`);
});
it('actions are displayed when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileForDelete)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${fileForDelete}`);
});
});
it('actions are displayed when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderForDelete)
.then(() => {
expect(toolbar.actions.isEmpty()).toBe(false, `actions not displayed for ${folderForDelete}`);
});
});
it('correct actions appear when a file is selected', () => {
dataTable.clickOnRowByContainingText(fileForDelete)
.then(() => {
expect(toolbar.actions.isButtonPresent('Permanently delete'))
.toBe(true, `Permanently delete is not displayed for ${fileForDelete}`);
expect(toolbar.actions.isButtonPresent('Restore')).toBe(true, `Restore is not displayed for ${fileForDelete}`);
});
});
it('correct actions appear when a folder is selected', () => {
dataTable.clickOnRowByContainingText(folderForDelete)
.then(() => {
expect(toolbar.actions.isButtonPresent('Permanently delete'))
.toBe(true, `Permanently delete is displayed for ${folderForDelete}`);
expect(toolbar.actions.isButtonPresent('Restore')).toBe(true, `Restore is not enabled for ${folderForDelete}`);
});
});
});
});

View File

@ -65,7 +65,6 @@ describe('Page titles', () => {
afterAll(done => {
logoutPage.load()
.then(() => Utils.clearLocalStorage())
.then(done);
});

View File

@ -27,19 +27,16 @@ describe('Login', () => {
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const testUser = {
username: 'test.user@alfness',
password: 'test.user'
};
const testUser = `user-${Utils.random()}@alfness`;
const russianUser = {
username: 'пользователь',
username: `пользвате${Utils.random()}`,
password: '密碼中國'
};
const johnDoe = {
username: 'john.doe',
password: 'john.doe',
username: `user-${Utils.random()}`,
get password() { return this.username; },
firstName: 'John',
lastName: 'Doe'
};
@ -47,7 +44,7 @@ describe('Login', () => {
beforeAll(done => {
Promise
.all([
peopleApi.createUser(testUser.username, testUser.password),
peopleApi.createUser(testUser),
peopleApi.createUser(russianUser.username, russianUser.password),
peopleApi.createUser(johnDoe.username, johnDoe.password, {
firstName: johnDoe.firstName,
@ -71,10 +68,9 @@ describe('Login', () => {
describe('with valid credentials', () => {
it('navigate to "Personal Files"', () => {
const { username, password } = johnDoe;
const { username } = johnDoe;
loginPage
.loginWith(username, password)
loginPage.loginWith(username)
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
});
@ -82,20 +78,17 @@ describe('Login', () => {
it(`displays user's name in header`, () => {
const { userInfo } = new BrowsingPage(APP_ROUTES.PERSONAL_FILES).header;
const { username, password, firstName, lastName } = johnDoe;
const { username, firstName, lastName } = johnDoe;
loginPage
.loginWith(username, password)
loginPage.loginWith(username)
.then(() => {
expect(userInfo.name).toEqual(`${firstName} ${lastName}`);
});
});
it(`logs in with user having username containing "@"`, () => {
const { username, password } = testUser;
loginPage
.loginWith(username, password)
.loginWith(testUser)
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
});
@ -112,10 +105,10 @@ describe('Login', () => {
});
it('redirects to Home Page when navigating to the Login page while already logged in', () => {
const { username, password } = johnDoe;
const { username } = johnDoe;
loginPage
.loginWith(username, password)
.loginWith(username)
.then(() => browser.get(APP_ROUTES.LOGIN)
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
@ -124,10 +117,10 @@ describe('Login', () => {
});
it('redirects to Personal Files when pressing browser Back while already logged in ', () => {
const { username, password } = johnDoe;
const { username } = johnDoe;
loginPage
.loginWith(username, password)
.loginWith(username)
.then(() => browser.driver.navigate().back())
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
@ -157,7 +150,7 @@ describe('Login', () => {
it('shows error when entering nonexistent user', () => {
loginPage
.loginWith('nonexistent-user', 'any-password')
.tryLoginWith('nonexistent-user', 'any-password')
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
expect(errorMessage.isDisplayed()).toBe(true);
@ -168,7 +161,7 @@ describe('Login', () => {
const { username } = johnDoe;
loginPage
.loginWith(username, 'incorrect-password')
.tryLoginWith(username, 'incorrect-password')
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
expect(errorMessage.isDisplayed()).toBe(true);

View File

@ -29,20 +29,17 @@ describe('Logout', () => {
const peopleApi = new RepoClient().people;
const johnDoe = {
username: 'john.doe',
password: 'john.doe'
};
const johnDoe = `user-${Utils.random()}`;
beforeAll((done) => {
peopleApi
.createUser(johnDoe.username, johnDoe.password)
.createUser(johnDoe)
.then(done);
});
beforeEach((done) => {
loginPage.load()
.then(() => loginPage.loginWith(johnDoe.username, johnDoe.password))
.then(() => loginPage.loginWith(johnDoe))
.then(done);
});
@ -59,13 +56,6 @@ describe('Logout', () => {
});
});
xit('redirects to Login page when logging out by URL', () => {
browser.get(APP_ROUTES.LOGOUT)
.then(() => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
});
});
it('redirects to Login page when pressing browser Back after logout', () => {
page.signOut()
.then(() => browser.driver.navigate().back())

View File

@ -0,0 +1,103 @@
/*!
* @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 { browser, by } from 'protractor';
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES, SIDEBAR_LABELS } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('Empty list views', () => {
const username = `user-${Utils.random()}`;
const password = username;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
};
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const page = new BrowsingPage();
const { dataTable } = page;
beforeAll(done => {
apis.admin.people.createUser(username)
.then(() => loginPage.load())
.then(() => loginPage.loginWith(username))
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('empty Personal Files', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.PERSONAL_FILES)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyDragAndDropText()).toContain('Drag and drop');
});
});
it('empty File Libraries', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyStateTitle()).toContain(`You aren't a member of any File Libraries yet`);
expect(dataTable.getEmptyStateText()).toContain('Join sites to upload, view, and share files.');
});
});
it('empty Shared Files', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.SHARED_FILES)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyStateTitle()).toContain('No shared files or folders');
expect(dataTable.getEmptyStateText()).toContain('Items you share using the Share option are shown here.');
});
});
it('empty Recent Files', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.RECENT_FILES)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyStateTitle()).toContain('No recent files');
expect(dataTable.getEmptyStateText()).toContain('Items you upload or edit in the last 30 days are shown here.');
});
});
it('empty Favorites', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FAVORITES)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyStateTitle()).toContain('No favorite files or folders');
expect(dataTable.getEmptyStateText()).toContain('Favorite items that you want to easily find later.');
});
});
it('empty Trash', () => {
page.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.TRASH)
.then(() => {
expect(dataTable.isEmptyList()).toBe(true, 'list is not empty');
expect(dataTable.getEmptyStateTitle()).toContain('Trash is empty');
expect(dataTable.getEmptyStateText()).toContain('Items you delete are moved to the Trash.');
expect(dataTable.getEmptyStateText()).toContain('Empty Trash to permanently delete items.');
});
});
});

View File

@ -0,0 +1,116 @@
/*!
* @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 { browser, by } from 'protractor';
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES, SIDEBAR_LABELS } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('Favorites', () => {
const username = `user-${Utils.random()}`;
const password = username;
const siteName = `site-${Utils.random()}`;
const folderName = `folder-${Utils.random()}`;
const fileName1 = `file-${Utils.random()}.txt`;
const fileName2 = `file-${Utils.random()}.txt`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
};
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const favoritesPage = new BrowsingPage();
const { dataTable } = favoritesPage;
beforeAll(done => {
apis.admin.people.createUser(username)
.then(() => apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC))
.then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_MANAGER))
.then(() => apis.admin.nodes.createFiles([ fileName1 ], `Sites/${siteName}/documentLibrary`)
.then(resp => apis.user.favorites.addFavoriteById('file', resp.data.entry.id)))
.then(() => apis.user.nodes.createFolders([ folderName ])
.then(resp => apis.user.favorites.addFavoriteById('folder', resp.data.entry.id)))
.then(() => apis.user.nodes.createFiles([ fileName2 ], folderName)
.then(resp => apis.user.favorites.addFavoriteById('file', resp.data.entry.id)))
.then(() => loginPage.load())
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
favoritesPage.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FAVORITES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
Promise.all([
apis.admin.sites.deleteSite(siteName, true),
apis.user.nodes.deleteNodes([ folderName ]),
logoutPage.load()
])
.then(done);
});
it('has the correct columns', () => {
const labels = [ 'Name', 'Location', 'Size', 'Modified', 'Modified by' ];
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
expect(dataTable.getColumnHeaders().count()).toBe(5 + 1, 'Incorrect number of columns');
elements.forEach((element, index) => {
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
});
});
it('displays the favorite files and folders', () => {
expect(dataTable.countRows()).toEqual(3, 'Incorrect number of items displayed');
expect(dataTable.getRowByContainingText(fileName1).isPresent()).toBe(true, `${fileName1} not displayed`);
expect(dataTable.getRowByContainingText(fileName2).isPresent()).toBe(true, `${fileName2} not displayed`);
expect(dataTable.getRowByContainingText(folderName).isPresent()).toBe(true, `${folderName} not displayed`);
});
it('Location column displays the parent folder of the files', () => {
const itemsLocations = {
[fileName1]: siteName,
[fileName2]: folderName,
[folderName]: 'Personal Files'
};
dataTable.getRows()
.map((row) => {
return row.all(dataTable.cell).map(cell => cell.getText());
})
.then((rowCells) => {
return rowCells.reduce((acc, cell) => {
acc[cell[1]] = cell[2];
return acc;
}, {});
})
.then((favoritesList) => {
Object.keys(itemsLocations).forEach((item) => {
expect(favoritesList[item]).toEqual(itemsLocations[item]);
});
});
});
});

View File

@ -0,0 +1,122 @@
/*!
* @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 { browser, by } from 'protractor';
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES, SIDEBAR_LABELS } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('File Libraries', () => {
const username = `user-${Utils.random()}`;
const password = username;
const sitePrivate = `private-${Utils.random()}`;
const siteModerated = `moderated-${Utils.random()}`;
const sitePublic = `public-${Utils.random()}`;
const adminSite = `admin-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
};
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const fileLibrariesPage = new BrowsingPage(APP_ROUTES.FILE_LIBRARIES);
const { dataTable } = fileLibrariesPage;
beforeAll(done => {
Promise
.all([
apis.admin.people.createUser(username),
apis.admin.sites.createSite(sitePublic, SITE_VISIBILITY.PUBLIC),
apis.admin.sites.createSite(siteModerated, SITE_VISIBILITY.MODERATED),
apis.admin.sites.createSite(sitePrivate, SITE_VISIBILITY.PRIVATE),
apis.admin.sites.createSite(adminSite, SITE_VISIBILITY.PUBLIC)
])
.then(() => apis.admin.sites.addSiteMember(sitePublic, username, SITE_ROLES.SITE_CONSUMER))
.then(() => apis.admin.sites.addSiteMember(siteModerated, username, SITE_ROLES.SITE_MANAGER))
.then(() => apis.admin.sites.addSiteMember(sitePrivate, username, SITE_ROLES.SITE_CONTRIBUTOR))
.then(() => loginPage.load())
.then(() => loginPage.loginWith(username))
.then(done);
});
beforeEach(done => {
fileLibrariesPage.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.FILE_LIBRARIES)
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
Promise.all([
apis.admin.sites.deleteSite(sitePublic, true),
apis.admin.sites.deleteSite(siteModerated, true),
apis.admin.sites.deleteSite(sitePrivate, true),
apis.admin.sites.deleteSite(adminSite, true),
logoutPage.load()
])
.then(done);
});
it('has the correct columns', () => {
const labels = [ 'Title', 'Status' ];
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
expect(dataTable.getColumnHeaders().count()).toBe(2 + 1, 'Incorrect number of columns');
elements.forEach((element, index) => {
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
});
});
it('User can see only the sites he is a member of', () => {
const sitesCount = dataTable.countRows();
const expectedSites = {
[sitePrivate]: SITE_VISIBILITY.PRIVATE,
[siteModerated]: SITE_VISIBILITY.MODERATED,
[sitePublic]: SITE_VISIBILITY.PUBLIC
};
expect(sitesCount).toEqual(3, 'Incorrect number of sites displayed');
expect(dataTable.getRowByContainingText(adminSite).isPresent()).toBe(false, 'Incorrect site appears in list');
dataTable.getRows()
.map((row) => {
return row.all(by.css('td')).map(cell => cell.getText());
})
.then((rowCells) => {
return rowCells.reduce((acc, cell) => {
acc[cell[1]] = cell[2].toUpperCase();
return acc;
}, {});
})
.then((sitesList) => {
Object.keys(expectedSites).forEach((site) => {
expect(sitesList[site]).toEqual(expectedSites[site]);
});
});
});
// it('Site ID is displayed when two sites have the same name', () => {
// // cannot be implemented until ACA-987 is fixed
// });
});

View File

@ -23,8 +23,8 @@ import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('Personal Files', () => {
const username = 'jane.doe';
const password = 'jane.doe';
const username = `user-${Utils.random()}`;
const password = username;
const apis = {
admin: new RepoClient(),
@ -36,30 +36,27 @@ describe('Personal Files', () => {
const personalFilesPage = new BrowsingPage(APP_ROUTES.PERSONAL_FILES);
const dataTable = personalFilesPage.dataTable;
const adminContent: NodeContentTree = {
name: 'admin-folder'
};
const adminFolder = `admin-folder-${Utils.random()}`;
const userContent: NodeContentTree = {
name: 'user-folder',
files: [ 'user-file.txt' ]
};
const userFolder = `user-folder-${Utils.random()}`;
const userFile = `file-${Utils.random()}.txt`;
beforeAll(done => {
Promise
.all([
apis.admin.people.createUser(username, password),
apis.admin.nodes.createContent(adminContent)
apis.admin.nodes.createFolders([ adminFolder ])
])
.then(() => apis.user.nodes.createContent(userContent))
.then(() => apis.user.nodes.createFolders([ userFolder ]))
.then(() => apis.user.nodes.createFiles([ userFile ], userFolder))
.then(done);
});
afterAll(done => {
Promise
.all([
apis.admin.nodes.deleteNodes([ adminContent.name ]),
apis.user.nodes.deleteNodes([ userContent.name ])
apis.admin.nodes.deleteNodes([ adminFolder ]),
apis.user.nodes.deleteNodes([ userFolder ])
])
.then(done);
});
@ -81,7 +78,6 @@ describe('Personal Files', () => {
afterAll(done => {
logoutPage.load()
.then(() => Utils.clearLocalStorage())
.then(done);
});
@ -109,18 +105,15 @@ describe('Personal Files', () => {
afterAll(done => {
logoutPage.load()
.then(() => Utils.clearLocalStorage())
.then(done);
});
it('has the right column count', () => {
expect(dataTable.getColumnHeaders().count()).toBe(5);
});
it('has the right columns', () => {
it('has the correct columns', () => {
const labels = [ 'Name', 'Size', 'Modified', 'Modified by' ];
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
expect(dataTable.getColumnHeaders().count()).toBe(4 + 1, 'Incorrect number of columns');
elements.forEach((element, index) => {
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
});
@ -131,17 +124,17 @@ describe('Personal Files', () => {
});
it('has user created content', () => {
expect(dataTable.getRowByContainingText('user-folder').isPresent())
expect(dataTable.getRowByContainingText(userFolder).isPresent())
.toBe(true);
});
it('navigates to folder', () => {
const getNodeIdPromise = apis.user.nodes
.getNodeByPath('/user-folder')
.getNodeByPath(`/${userFolder}`)
.then(response => response.data.entry.id);
const navigatePromise = dataTable
.doubleClickOnRowByContainingText('user-folder')
.doubleClickOnRowByContainingText(userFolder)
.then(() => dataTable.waitForHeader());
Promise
@ -153,8 +146,8 @@ describe('Personal Files', () => {
expect(browser.getCurrentUrl())
.toContain(nodeId, 'Node ID is not in the URL');
expect(dataTable.getRowByContainingText('user-file.txt').isPresent())
.toBe(true, '"user-file.txt" is missing');
expect(dataTable.getRowByContainingText(userFile).isPresent())
.toBe(true, 'user file is missing');
});
});
@ -165,7 +158,7 @@ describe('Personal Files', () => {
const { actions } = personalFilesPage.toolbar;
dataTable
.clickOnRowByContainingText('user-folder')
.clickOnRowByContainingText(userFolder)
.then(() => {
expect(actions.isEmpty()).toBe(false, 'Toolbar to be present');
})

View File

@ -0,0 +1,142 @@
/*!
* @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 { browser, by } from 'protractor';
import { APP_ROUTES, SITE_VISIBILITY, SITE_ROLES, SIDEBAR_LABELS } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('Trash', () => {
const username = `user-${Utils.random()}`;
const password = username;
const siteName = `site-${Utils.random()}`;
const folderAdmin = `folder-${Utils.random()}`;
const folderUser = `folder-${Utils.random()}`;
const fileAdmin = `file-${Utils.random()}.txt`;
const fileUser = `file-${Utils.random()}.txt`;
const fileSite = `file-${Utils.random()}.txt`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
};
const loginPage = new LoginPage();
const logoutPage = new LogoutPage();
const trashPage = new BrowsingPage();
const { dataTable } = trashPage;
beforeAll(done => {
apis.admin.people.createUser(username)
// admin: create file -> delete file
.then(() => apis.admin.nodes.createFiles([ fileAdmin ])
.then((resp) => apis.admin.nodes.deleteNodeById(resp.data.entry.id, false)))
// admin: create folder -> delete folder
.then(() => apis.admin.nodes.createFolders([ folderAdmin ])
.then((resp) => apis.admin.nodes.deleteNodeById(resp.data.entry.id, false)))
// admin: create site, add user to site, create file
.then(() => apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC))
.then(() => apis.admin.sites.addSiteMember(siteName, username, SITE_ROLES.SITE_MANAGER))
.then(() => apis.admin.nodes.createFiles([ fileSite ], `Sites/${siteName}/documentLibrary`)
// user: delete file from site
.then(resp => apis.user.nodes.deleteNodeById(resp.data.entry.id, false)))
// user: create file -> delete file
.then(() => apis.user.nodes.createFiles([ fileUser ])
.then((resp) => apis.user.nodes.deleteNodeById(resp.data.entry.id, false)))
// user: create folder -> delete folder
.then(() => apis.user.nodes.createFolders([ folderUser ])
.then((resp) => apis.user.nodes.deleteNodeById(resp.data.entry.id, false)))
.then(done);
});
afterAll(done => {
apis.admin.sites.deleteSite(siteName).then(done);
});
xit('');
describe('as admin', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWithAdmin())
.then(() => trashPage.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.TRASH))
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('has the correct columns', () => {
const labels = [ 'Name', 'Location', 'Size', 'Deleted', 'Deleted by' ];
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
expect(dataTable.getColumnHeaders().count()).toBe(5 + 1, 'Incorrect number of columns');
elements.forEach((element, index) => {
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
});
});
it('displays the files and folders deleted by everyone', () => {
expect(dataTable.countRows()).toEqual(5, 'Incorrect number of deleted items displayed');
expect(dataTable.getRowByContainingText(fileAdmin).isPresent()).toBe(true, `${fileAdmin} not displayed`);
expect(dataTable.getRowByContainingText(folderAdmin).isPresent()).toBe(true, `${folderAdmin} not displayed`);
expect(dataTable.getRowByContainingText(fileUser).isPresent()).toBe(true, `${fileUser} not displayed`);
expect(dataTable.getRowByContainingText(folderUser).isPresent()).toBe(true, `${folderUser} not displayed`);
expect(dataTable.getRowByContainingText(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`);
});
});
describe('as user', () => {
beforeAll(done => {
loginPage.load()
.then(() => loginPage.loginWith(username))
.then(() => trashPage.sidenav.navigateToLinkByLabel(SIDEBAR_LABELS.TRASH))
.then(() => dataTable.waitForHeader())
.then(done);
});
afterAll(done => {
logoutPage.load().then(done);
});
it('has the correct columns', () => {
const labels = [ 'Name', 'Location', 'Size', 'Deleted', 'Deleted by' ];
const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label));
expect(dataTable.getColumnHeaders().count()).toBe(5 + 1, 'Incorrect number of columns');
elements.forEach((element, index) => {
expect(element.isPresent()).toBe(true, `"${labels[index]}" is missing`);
});
});
it('displays the files and folders deleted by the user', () => {
expect(dataTable.countRows()).toEqual(3, 'Incorrect number of deleted items displayed');
expect(dataTable.getRowByContainingText(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`);
expect(dataTable.getRowByContainingText(fileUser).isPresent()).toBe(true, `${fileUser} not displayed`);
expect(dataTable.getRowByContainingText(folderUser).isPresent()).toBe(true, `${folderUser} not displayed`);
});
});
});

View File

@ -19,7 +19,6 @@ import { browser } from 'protractor';
import { APP_ROUTES, SIDEBAR_LABELS } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
describe('Side navigation', () => {
const loginPage = new LoginPage();
@ -38,7 +37,6 @@ describe('Side navigation', () => {
afterAll(done => {
logoutPage.load()
.then(() => Utils.clearLocalStorage())
.then(done);
});

View File

@ -23,12 +23,11 @@ import { Utils } from '../../utilities/utils';
import { RepoClient, NodeContentTree } from '../../utilities/repo-client/repo-client';
describe('Pagination', () => {
const username = 'jane.doe';
const password = 'jane.doe';
const username = `user-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, password)
user: new RepoClient(username, username)
};
const loginPage = new LoginPage();
@ -36,7 +35,7 @@ describe('Pagination', () => {
beforeAll(done => {
apis.admin.people
.createUser(username, password)
.createUser(username)
.then(done);
});
@ -48,7 +47,7 @@ describe('Pagination', () => {
// Generate files
const content: NodeContentTree = {
name: 'user-folder',
name: `user-folder-${Utils.random()}`,
files: Array(101)
.fill('file')
.map((name, index): string => `${name}-${index + 1}.txt`)
@ -58,14 +57,13 @@ describe('Pagination', () => {
beforeAll(done => {
nodesApi.createContent(content)
.then(() => loginPage.load())
.then(() => loginPage.loginWith(username, password))
.then(done);
.then(() => loginPage.load()
.then(() => loginPage.loginWith(username))
.then(done));
});
beforeEach(done => {
personalFilesPage
.load()
personalFilesPage.load()
.then(() => dataTable.waitForHeader())
.then(() => dataTable.doubleClickOnRowByContainingText(content.name))
.then(() => dataTable.sortByColumn('Name'))
@ -73,9 +71,7 @@ describe('Pagination', () => {
});
afterAll(done => {
logoutPage
.load()
.then(() => Utils.clearLocalStorage())
logoutPage.load()
.then(() => nodesApi.deleteNodes([ content.name ]))
.then(done);
});

View File

@ -40,6 +40,18 @@ export class FavoritesApi extends RepoApi {
.catch(this.handleError);
}
addFavoriteById(nodeType: string, id: string): Promise<any> {
const data = [{
target: {
[nodeType]: {
guid: id
}
}
}];
return this.post(`/people/-me-/favorites`, { data })
.catch(this.handleError);
}
getFavorite(api: RepoClient, name: string): Promise<any> {
return api.nodes.getNodeByPath(name)
.then((response) => {

View File

@ -33,17 +33,17 @@ export class NodesApi extends RepoApi {
.catch(this.handleError);
}
deleteNodeById(id: string): Promise<any> {
deleteNodeById(id: string, permanent: boolean = true): Promise<any> {
return this
.delete(`/nodes/${id}`)
.delete(`/nodes/${id}?permanent=${permanent}`)
.catch(this.handleError);
}
deleteNodeByPath(path: string): Promise<any> {
deleteNodeByPath(path: string, permanent: boolean = true): Promise<any> {
return this
.getNodeByPath(path)
.then((response: any): string => response.data.entry.id)
.then((id: string): any => this.deleteNodeById(id))
.then((id: string): any => this.deleteNodeById(id, permanent))
.catch(this.handleError);
}
@ -56,10 +56,10 @@ export class NodesApi extends RepoApi {
.catch(this.handleError);
}
deleteNodes(names: string[], relativePath: string = ''): Promise<any> {
deleteNodes(names: string[], relativePath: string = '', permanent: boolean = true): Promise<any> {
const deletions = names
.map((name: string): any => {
return this.deleteNodeByPath(`${relativePath}/${name}`);
return this.deleteNodeByPath(`${relativePath}/${name}`, permanent);
});
return Promise.all(deletions);

View File

@ -35,7 +35,7 @@ export class PeopleApi extends RepoApi {
.catch(this.handleError);
}
createUser(username: string, password: string, details?: Person): Promise<any> {
createUser(username: string, password?: string, details?: Person): Promise<any> {
const person: Person = new Person(username, password, details);
const onSuccess = (response) => response;
const onError = (response) => {

View File

@ -0,0 +1,36 @@
/*!
* @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 { RepoApi } from '../repo-api';
import { NodesApi } from '../nodes/nodes-api';
import { RepoClient } from './../../repo-client';
export class SharedLinksApi extends RepoApi {
shareFileById(id: string): Promise<any> {
const data = [{ nodeId: id }];
return this.post(`/shared-links`, { data })
.catch(this.handleError);
}
getSharedLinks(): Promise<any> {
return this.get(`/shared-links`)
.catch(this.handleError);
}
}

View File

@ -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.
*/
import { RepoApi } from '../repo-api';
export class TrashcanApi extends RepoApi {
permanentlyDelete(id: string): Promise<any> {
return this
.delete(`/deleted-nodes/${id}`)
.catch(this.handleError);
}
}

View File

@ -21,13 +21,16 @@ 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';
import { SharedLinksApi } from './apis/shared-links/shared-links-api';
import { TrashcanApi } from './apis/trashcan/trashcan-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 shared: SharedLinksApi = new SharedLinksApi(this.auth, this.config);
public shared: SharedLinksApi = new SharedLinksApi(this.auth, this.config);
public trashcan: TrashcanApi = new TrashcanApi(this.auth, this.config);
constructor(
private username: string = RepoClientAuth.DEFAULT_USERNAME,

View File

@ -27,4 +27,10 @@ export class Utils {
static clearLocalStorage(): promise.Promise<any> {
return browser.executeScript('window.localStorage.clear();');
}
// session storage
static clearSessionStorage(): promise.Promise<any> {
return browser.executeScript('window.sessionStorage.clear();');
}
}

View File

@ -4,14 +4,14 @@
"license": "Apache-2.0",
"scripts": {
"ng": "ng",
"start": "ng serve --open",
"build": "ng build",
"build:prod": "ng build --prod",
"build:dev": "ng build && node postbuild-dev.js",
"start": "npm run server-versions && ng serve --open",
"build": "npm run server-versions && ng build",
"build:prod": "npm run server-versions && ng build --prod",
"build:dev": "npm run server-versions && ng build && node postbuild-dev.js",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"start:dist": "wsrv"
"server-versions": "rimraf ./src/versions.json && npm list --depth=0 --json=true --prod=true > ./src/versions.json || exit 0"
},
"private": true,
"dependencies": {
@ -39,7 +39,6 @@
"ng2-alfresco-viewer": "1.10.0-beta6",
"pdfjs-dist": "1.8.557",
"rxjs": "5.1.0",
"wsrv": "0.2.2",
"zone.js": "^0.8.14"
},
"devDependencies": {
@ -62,6 +61,7 @@
"karma-jasmine-html-reporter": "^0.2.2",
"node-rest-client": "^3.1.0",
"protractor": "^5.1.2",
"rimraf": "2.6.2",
"ts-node": "~3.2.0",
"tslint": "~5.7.0",
"typescript": "~2.3.3"

View File

@ -1,9 +1,10 @@
{
"ecmHost": "http://{hostname}:{port}",
"ecmHost": "http://{hostname}{:port}",
"application": {
"name": "Alfresco Example Content Application",
"build": "1234"
},
"logo": "alfresco-logo-white.svg",
"languagePicker": false,
"document-list": {
"supportedPageSizes": [
@ -20,6 +21,66 @@
".git"
]
},
"navigation": {
"main": [
{
"icon": "folder",
"label": "APP.BROWSE.PERSONAL.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.PERSONAL.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/personal-files"
}
},
{
"icon": "group_work",
"label": "APP.BROWSE.LIBRARIES.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.LIBRARIES.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/libraries"
}
}
],
"secondary": [
{
"icon": "people",
"label": "APP.BROWSE.SHARED.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.SHARED.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/shared"
}
},
{
"icon": "schedule",
"label": "APP.BROWSE.RECENT.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.RECENT.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/recent-files"
}
},
{
"icon": "star",
"label": "APP.BROWSE.FAVORITES.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.FAVORITES.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/favorites"
}
},
{
"icon": "delete",
"label": "APP.BROWSE.TRASHCAN.SIDENAV_LINK.LABEL",
"title": "APP.BROWSE.TRASHCAN.SIDENAV_LINK.TOOLTIP",
"disabled": false,
"route": {
"url": "/trashcan"
}
}
]
},
"languages": [
{
"key": "de",

View File

@ -41,6 +41,8 @@ import { HeaderComponent } from './components/header/header.component';
import { CurrentUserComponent } from './components/current-user/current-user.component';
import { SearchComponent } from './components/search/search.component';
import { SidenavComponent } from './components/sidenav/sidenav.component';
import { AboutComponent } from './components/about/about.component';
import { LocationLinkComponent } from './components/location-link/location-link.component';
@NgModule({
imports: [
@ -67,7 +69,9 @@ import { SidenavComponent } from './components/sidenav/sidenav.component';
RecentFilesComponent,
SharedFilesComponent,
TrashcanComponent,
PreviewComponent
PreviewComponent,
AboutComponent,
LocationLinkComponent
],
providers: [
{

View File

@ -26,6 +26,7 @@ import { LibrariesComponent } from './components/libraries/libraries.component';
import { RecentFilesComponent } from './components/recent-files/recent-files.component';
import { SharedFilesComponent } from './components/shared-files/shared-files.component';
import { TrashcanComponent } from './components/trashcan/trashcan.component';
import { AboutComponent } from './components/about/about.component';
import { LoginComponent } from './components/login/login.component';
import { PreviewComponent } from './components/preview/preview.component';
@ -34,13 +35,16 @@ import { GenericErrorComponent } from './components/generic-error/generic-error.
export const APP_ROUTES: Routes = [
{
path: 'preview/:nodeId',
component: PreviewComponent
component: PreviewComponent,
data: {
i18nTitle: 'APP.PREVIEW.TITLE'
}
},
{
path: 'login',
component: LoginComponent,
data: {
title: 'Sign in'
i18nTitle: 'APP.SIGN_IN'
}
},
{
@ -113,6 +117,13 @@ export const APP_ROUTES: Routes = [
i18nTitle: 'APP.BROWSE.TRASHCAN.TITLE'
}
},
{
path: 'about',
component: AboutComponent,
data: {
i18nTitle: 'APP.BROWSE.ABOUT.TITLE'
}
},
{
path: '**',
component: GenericErrorComponent

View File

@ -0,0 +1,46 @@
<div class="inner-layout inner-layout--scroll">
<div class="inner-layout__content inner-layout__content--scroll">
<article *ngIf="ecmVersion" class="padding">
<header class="header padding-left">Alfresco Content Services</header>
<p class="padding-left"> version: {{ ecmVersion.edition }} {{ ecmVersion.version.display }} </p>
</article>
<article class="padding-top-bottom">
<header class="header padding-left-right">License</header>
<adf-datatable [data]="license"></adf-datatable>
</article>
<article class="padding-top-bottom">
<header class="header padding-left-right">Status</header>
<adf-datatable [data]="status"></adf-datatable>
</article>
<article class="padding-top-bottom">
<header class="header padding-left-right">Modules</header>
<adf-datatable [data]="modules"></adf-datatable>
</article>
<article class="padding">
<header class="header padding-left">Alfresco Content Application</header>
<p class="padding-left"> version: 1.0 </p>
</article>
<article *ngIf="githubUrlCommitAlpha" class="padding">
<header class="header">Source code</header>
<small>You are running the project based on the following commit:</small>
<p>
<a [href]="githubUrlCommitAlpha" target="blank">{{githubUrlCommitAlpha}}</a>
</p>
</article>
<article>
<header class="header padding-left-right">Packages</header>
<small class="padding-left-right">Current project is using the following ADF libraries:</small>
<adf-datatable [data]="data"></adf-datatable>
</article>
</div>
</div>

View File

@ -0,0 +1,37 @@
@import 'variables';
article {
color: $alfresco-secondary-text-color;
}
article:first-of-type {
padding-bottom: 0;
}
article:last-of-type {
margin-bottom: 50px;
}
header {
line-height: 24px;
font-size: 14px;
font-weight: 800;
letter-spacing: -0.2px;
}
a {
text-decoration: none;
color: $alfresco-primary-text-color;
}
.padding {
padding: 25px;
}
.padding-top-bottom {
padding: 25px 0 25px 0;
}
.padding-left-right {
padding: 0 25px 0 25px;
}

View File

@ -0,0 +1,90 @@
/*!
* @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 { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { DiscoveryApiService, EcmProductVersionModel } from 'ng2-alfresco-core';
import { ObjectDataTableAdapter } from 'ng2-alfresco-datatable';
@Component({
selector: 'app-about',
templateUrl: './about.component.html',
styleUrls: [ './about.component.scss' ]
})
export class AboutComponent implements OnInit {
ecmVersion: EcmProductVersionModel = null;
data: ObjectDataTableAdapter;
status: ObjectDataTableAdapter;
license: ObjectDataTableAdapter;
modules: ObjectDataTableAdapter;
githubUrlCommitAlpha = 'https://github.com/Alfresco/alfresco-content-app/commits';
constructor(
private discovery: DiscoveryApiService,
private http: Http
) {}
ngOnInit() {
this.discovery.getEcmProductInfo().subscribe((ecmVers) => {
this.ecmVersion = ecmVers;
this.modules = new ObjectDataTableAdapter(this.ecmVersion.modules, [
{type: 'text', key: 'id', title: 'ID', sortable: true},
{type: 'text', key: 'title', title: 'Title', sortable: true},
{type: 'text', key: 'version', title: 'Description', sortable: true},
{type: 'text', key: 'installDate', title: 'Install Date', sortable: true},
{type: 'text', key: 'installState', title: 'Install State', sortable: true},
{type: 'text', key: 'versionMin', title: 'Version Minor', sortable: true},
{type: 'text', key: 'versionMax', title: 'Version Max', sortable: true}
]);
this.status = new ObjectDataTableAdapter([this.ecmVersion.status], [
{type: 'text', key: 'isReadOnly', title: 'Read Only', sortable: true},
{type: 'text', key: 'isAuditEnabled', title: 'Audit Enable', sortable: true},
{type: 'text', key: 'isQuickShareEnabled', title: 'Quick Shared Enable', sortable: true},
{type: 'text', key: 'isThumbnailGenerationEnabled', title: 'Thumbnail Generation', sortable: true}
]);
this.license = new ObjectDataTableAdapter([this.ecmVersion.license], [
{type: 'text', key: 'issuedAt', title: 'Issued At', sortable: true},
{type: 'text', key: 'expiresAt', title: 'Expires At', sortable: true},
{type: 'text', key: 'remainingDays', title: 'Remaining Days', sortable: true},
{type: 'text', key: 'holder', title: 'Holder', sortable: true},
{type: 'text', key: 'mode', title: 'Type', sortable: true},
{type: 'text', key: 'isClusterEnabled', title: 'Cluster Enabled', sortable: true},
{type: 'text', key: 'isCryptodocEnabled', title: 'Cryptodoc Enable', sortable: true}
]);
});
this.http.get('/versions.json').subscribe(response => {
const regexp = new RegExp('^(ng2-alfresco|alfresco-)');
const alfrescoPackagesTableRepresentation = Object.keys(response.json().dependencies)
.filter((val) => regexp.test(val))
.map((val) => ({
name: val,
version: response.json().dependencies[val].version
}));
this.data = new ObjectDataTableAdapter(alfrescoPackagesTableRepresentation, [
{type: 'text', key: 'name', title: 'Name', sortable: true},
{type: 'text', key: 'version', title: 'Version', sortable: true}
]);
});
}
}

View File

@ -117,9 +117,10 @@
<data-column
key="path"
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION"
type="location"
format="/personal-files">
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION">
<ng-template let-context>
<app-location-link [context]="context"></app-location-link>
</ng-template>
</data-column>
<data-column

View File

@ -19,10 +19,10 @@ import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { TestBed, async } from '@angular/core/testing';
import { Observable } from 'rxjs/Rx';
import { CoreModule, NodesApiService, AlfrescoApiService, AlfrescoContentService } from 'ng2-alfresco-core';
import { CommonModule } from '../../common/common.module';
import { CommonModule } from '../../common/common.module';
import { LocationLinkComponent } from '../location-link/location-link.component';
import { ContentManagementService } from '../../common/services/content-management.service';
import { FavoritesComponent } from './favorites.component';
@ -72,6 +72,7 @@ describe('Favorites Routed Component', () => {
RouterTestingModule
],
declarations: [
LocationLinkComponent,
FavoritesComponent
]
})

View File

@ -1,9 +1,10 @@
<adf-toolbar class="app-menu">
<adf-toolbar-title>
<a
class="app-menu__title"
<a class="app-menu__title"
title="{{ appName }}"
[routerLink]="[ '/' ]">{{ appName }}</a>
[routerLink]="[ '/' ]">
<img [src]="logo" alt="{{ appName }}" />
</a>
</adf-toolbar-title>
<app-search></app-search>

View File

@ -31,21 +31,14 @@
.app-menu__title {
width: 100px;
height: $app-menu-height;
margin-left: 5px;
display: flex;
justify-content: center;
align-items: stretch;
line-height: 54px;
text-decoration: none;
text-indent: -9999px;
color: inherit;
background: url('/assets/images/alfresco-logo-white.svg') no-repeat 0 50%;
background-size: 100% auto;
display: block;
position: relative;
font-size: 20px;
line-height: 1;
letter-spacing: .02em;
font-weight: 400;
&> img {
width: 100%;
object-fit: contain;
}
}
}

View File

@ -25,10 +25,16 @@ import { AppConfigService } from 'ng2-alfresco-core';
encapsulation: ViewEncapsulation.None
})
export class HeaderComponent {
static ASSETS_PATH = '/assets/images/';
static DEFAULT_LOGO = 'alfresco-logo-white.svg';
constructor(private appConfig: AppConfigService) {}
get appName(): string {
return <string>this.appConfig.get('application.name');
}
get logo() {
return `${HeaderComponent.ASSETS_PATH}${this.appConfig.get('logo', HeaderComponent.DEFAULT_LOGO)}`;
}
}

View File

@ -23,8 +23,8 @@
<ng-template>
<div class="empty-list__block">
<mat-icon>group_work</mat-icon>
<p class="app-no-content_title">{{ 'APP.BROWSE.LIBRARIES.EMPTY_STATE.TITLE' | translate }}</p>
<p class="app-no-content_text">{{ 'APP.BROWSE.LIBRARIES.EMPTY_STATE.TEXT' | translate }}</p>
<p class="empty-list__title">{{ 'APP.BROWSE.LIBRARIES.EMPTY_STATE.TITLE' | translate }}</p>
<p class="empty-list__text">{{ 'APP.BROWSE.LIBRARIES.EMPTY_STATE.TEXT' | translate }}</p>
</div>
</ng-template>
</empty-folder-content>

View File

@ -0,0 +1,146 @@
import { Component, Input, ChangeDetectionStrategy, OnInit, ViewEncapsulation } from '@angular/core';
import { DataColumn, DataRow, DataTableAdapter } from 'ng2-alfresco-datatable';
import { AlfrescoApiService } from 'ng2-alfresco-core';
import { PathInfoEntity, AlfrescoApi } from 'alfresco-js-api';
import { Observable } from 'rxjs/Rx';
@Component({
selector: 'app-location-link',
template: `
<a href="" [title]="tooltip | async" [routerLink]="link">
{{ displayText | async }}
</a>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
// tslint:disable-next-line:use-host-property-decorator
host: {
'class': 'app-location-link'
}
})
export class LocationLinkComponent implements OnInit {
@Input()
context: any;
@Input()
link: any[];
@Input()
displayText: Observable<string>;
@Input()
tooltip: Observable<string>;
constructor(private apiService: AlfrescoApiService) {
}
ngOnInit() {
if (this.context) {
const data: DataTableAdapter = this.context.data;
const col: DataColumn = this.context.col;
const row: DataRow = this.context.row;
const value: PathInfoEntity = data.getValue(row, col);
if (value.name && value.elements) {
const isLibraryPath = this.isLibraryContent(value);
this.displayText = this.getDisplayText(value);
this.tooltip = this.getTooltip(value);
const parent = value.elements[value.elements.length - 1];
const area = isLibraryPath ? '/libraries' : '/personal-files';
this.link = [ area, parent.id ];
}
}
}
private isLibraryContent(path: PathInfoEntity): boolean {
if (path && path.elements.length >= 2 && path.elements[1].name === 'Sites') {
return true;
}
return false;
}
// todo: review once 5.2.3 is out
private getDisplayText(path: PathInfoEntity): Observable<string> {
const elements = path.elements.map(e => e.name);
// for admin users
if (elements.length === 1 && elements[0] === 'Company Home') {
return Observable.of('Personal Files');
}
// for non-admin users
if (elements.length === 3 && elements[0] === 'Company Home' && elements[1] === 'User Homes') {
return Observable.of('Personal Files');
}
const result = elements[elements.length - 1];
if (result === 'documentLibrary') {
const fragment = path.elements[path.elements.length - 2];
return new Observable<string>(observer => {
this.apiService.nodesApi.getNodeInfo(fragment.id).then(
(node) => {
observer.next(node.properties['cm:title'] || node.name || fragment.name);
observer.complete();
},
(err) => {
observer.next(fragment.name);
observer.complete();
}
);
});
}
return Observable.of(result);
}
// todo: review once 5.2.3 is out
private getTooltip(path: PathInfoEntity): Observable<string> {
const elements = path.elements.map(e => Object.assign({}, e));
if (elements[0].name === 'Company Home') {
elements[0].name = 'Personal Files';
if (elements.length > 1) {
if (elements[1].name === 'Sites') {
const fragment = elements[2];
return new Observable<string>(observer => {
this.apiService.nodesApi.getNodeInfo(fragment.id).then(
(node) => {
elements.splice(0, 2);
elements[0].name = node.properties['cm:title'] || node.name || fragment.name;
elements.splice(1, 1);
elements.unshift({ id: null, name: 'File Libraries' });
observer.next(elements.map(e => e.name).join('/'));
observer.complete();
},
(err) => {
elements.splice(0, 2);
elements.unshift({ id: null, name: 'File Libraries' });
elements.splice(2, 1);
observer.next(elements.map(e => e.name).join('/'));
observer.complete();
}
);
});
}
if (elements[1].name === 'User Homes') {
elements.splice(0, 3);
elements.unshift({ id: null, name: 'Personal Files'});
}
}
}
const result = elements.map(e => e.name).join('/');
return Observable.of(result);
}
}

View File

@ -84,8 +84,8 @@
<ng-template>
<div class="empty-list__block">
<mat-icon>access_time</mat-icon>
<p class="app-no-content_title">{{ 'APP.BROWSE.RECENT.EMPTY_STATE.TITLE' | translate }}</p>
<p class="app-no-content_text">{{ 'APP.BROWSE.RECENT.EMPTY_STATE.TEXT' | translate }}</p>
<p class="empty-list__title">{{ 'APP.BROWSE.RECENT.EMPTY_STATE.TITLE' | translate }}</p>
<p class="empty-list__text">{{ 'APP.BROWSE.RECENT.EMPTY_STATE.TEXT' | translate }}</p>
</div>
</ng-template>
</empty-folder-content>
@ -109,9 +109,10 @@
<data-column
key="path"
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION"
type="location"
format="/personal-files">
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION">
<ng-template let-context>
<app-location-link [context]="context"></app-location-link>
</ng-template>
</data-column>
<data-column

View File

@ -24,6 +24,7 @@ import { CoreModule, AlfrescoApiService } from 'ng2-alfresco-core';
import { CommonModule } from '../../common/common.module';
import { ContentManagementService } from '../../common/services/content-management.service';
import { LocationLinkComponent } from '../location-link/location-link.component';
import { RecentFilesComponent } from './recent-files.component';
describe('RecentFiles Routed Component', () => {
@ -54,6 +55,7 @@ describe('RecentFiles Routed Component', () => {
CommonModule
],
declarations: [
LocationLinkComponent,
RecentFilesComponent
]
})

View File

@ -107,11 +107,13 @@
<data-column
key="path"
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION"
type="location"
format="/personal-files">
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION">
<ng-template let-context>
<app-location-link [context]="context"></app-location-link>
</ng-template>
</data-column>
<data-column
key="content.sizeInBytes"
title="APP.DOCUMENT_LIST.COLUMNS.SIZE"

View File

@ -23,6 +23,7 @@ import { AlfrescoApiService } from 'ng2-alfresco-core';
import { CommonModule } from '../../common/common.module';
import { ContentManagementService } from '../../common/services/content-management.service';
import { LocationLinkComponent } from '../location-link/location-link.component';
import { SharedFilesComponent } from './shared-files.component';
describe('SharedFilesComponent', () => {
@ -51,6 +52,7 @@ describe('SharedFilesComponent', () => {
CommonModule
],
declarations: [
LocationLinkComponent,
SharedFilesComponent
]
})

View File

@ -56,7 +56,7 @@
<a
class="sidenav-menu__item-link"
routerLinkActive="sidenav-menu__item-link--active"
[routerLink]="item.route.url"
[routerLink]="item.disabled? null : item.route.url"
[ngClass]="{ 'disabled': item.disabled }"
title="{{ item.title || '' | translate }}">
<mat-icon>{{ item.icon }}</mat-icon>

View File

@ -20,7 +20,7 @@ import { Subscription } from 'rxjs/Rx';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { AlfrescoContentService } from 'ng2-alfresco-core';
import { AlfrescoContentService, AppConfigService } from 'ng2-alfresco-core';
import { BrowsingFilesService } from '../../common/services/browsing-files.service';
@ -32,60 +32,18 @@ import { BrowsingFilesService } from '../../common/services/browsing-files.servi
export class SidenavComponent implements OnInit, OnDestroy {
node: MinimalNodeEntryEntity = null;
onChangeParentSubscription: Subscription;
navigation = [
[
{
icon: 'folder',
label: 'APP.BROWSE.PERSONAL.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.PERSONAL.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/personal-files' }
},
{
icon: 'group_work',
label: 'APP.BROWSE.LIBRARIES.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.LIBRARIES.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/libraries' }
}
],
[
{
icon: 'people',
label: 'APP.BROWSE.SHARED.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.SHARED.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/shared' }
},
{
icon: 'schedule',
label: 'APP.BROWSE.RECENT.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.RECENT.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/recent-files' }
},
{
icon: 'star',
label: 'APP.BROWSE.FAVORITES.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.FAVORITES.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/favorites' }
},
{
icon: 'delete',
label: 'APP.BROWSE.TRASHCAN.SIDENAV_LINK.LABEL',
title: 'APP.BROWSE.TRASHCAN.SIDENAV_LINK.TOOLTIP',
disabled: false,
route: { url: '/trashcan' }
}
]
];
navigation = [];
constructor(
private browsingFilesService: BrowsingFilesService,
private contentService: AlfrescoContentService
) {}
private contentService: AlfrescoContentService,
private appConfig: AppConfigService
) {
this.navigation = this.navigation.concat([
this.appConfig.get('navigation.main'),
this.appConfig.get('navigation.secondary')
]);
}
ngOnInit() {
this.onChangeParentSubscription = this.browsingFilesService.onChangeParent

View File

@ -66,27 +66,24 @@
</data-column>
<data-column
key="path.name"
key="path"
title="APP.DOCUMENT_LIST.COLUMNS.LOCATION">
<ng-template let-value="value">
<span title="{{ value }}">{{ (value || '').split('/').pop() }}</span>
<ng-template let-context>
<app-location-link [context]="context"></app-location-link>
</ng-template>
</data-column>
<data-column
key="content.sizeInBytes"
title="APP.DOCUMENT_LIST.COLUMNS.SIZE">
<ng-template let-value="value">
<span title="{{ value }} bytes">{{ value | adfFileSize }}</span>
</ng-template>
title="APP.DOCUMENT_LIST.COLUMNS.SIZE"
type="fileSize">
</data-column>
<data-column
key="archivedAt"
title="APP.DOCUMENT_LIST.COLUMNS.DELETED_ON">
<ng-template let-value="value">
<span title="{{ value | date:'medium' }}">{{ value | adfTimeAgo }}</span>
</ng-template>
title="APP.DOCUMENT_LIST.COLUMNS.DELETED_ON"
type="date"
format="timeAgo">
</data-column>
<data-column

View File

@ -19,6 +19,7 @@ import { TestBed, async } from '@angular/core/testing';
import { CoreModule, AlfrescoApiService } from 'ng2-alfresco-core';
import { TrashcanComponent } from './trashcan.component';
import { CommonModule } from '../../common/common.module';
import { LocationLinkComponent } from '../location-link/location-link.component';
describe('TrashcanComponent', () => {
let fixture;
@ -42,6 +43,7 @@ describe('TrashcanComponent', () => {
CommonModule
],
declarations: [
LocationLinkComponent,
TrashcanComponent
]
})

View File

@ -44,6 +44,10 @@ $app-inner-layout--footer-height: 48px;
flex: 1;
flex-direction: column;
&--scroll {
overflow: auto;
}
&__header,
&__footer {
display: flex;
@ -65,6 +69,10 @@ $app-inner-layout--footer-height: 48px;
overflow: hidden;
}
&__content--scroll {
overflow: auto;
}
&__footer {
flex-basis: $app-inner-layout--footer-height;
border-top: 1px solid $alfresco-divider-color;

View File

@ -14,14 +14,18 @@ adf-document-list {
}
}
adf-document-list .adf-data-table {
.adf-data-table {
border: none !important;
.sr-only {
display: none;
}
tr, td {
th, td {
color: $alfresco-secondary-text-color;
}
th, tr, td {
&:focus {
outline: none !important;
}
@ -76,10 +80,25 @@ adf-document-list .adf-data-table {
}
}
.adf-data-table__header--sorted-asc,
.adf-data-table__header--sorted-desc {
&:hover {
&:before {
color: inherit !important;
}
}
}
.app-location-link,
.adf-location-cell {
a {
text-decoration: none;
color: $alfresco-primary-text-color;
&:hover {
color: $alfresco-app-color--default;
text-decoration: underline;
}
}
}

View File

@ -3,6 +3,9 @@
"LANGUAGE": "Language",
"SIGN_IN": "Sign in",
"SIGN_OUT": "Sign out",
"PREVIEW": {
"TITLE": "Preview"
},
"NEW_MENU": {
"LABEL": "New",
"MENU_ITEMS": {
@ -82,6 +85,9 @@
"FIRST_TEXT": "Items you delete are moved to the Trash.",
"SECOND_TEXT": "Empty Trash to permanently delete items."
}
},
"ABOUT": {
"TITLE": "About"
}
},
"ACTIONS": {

View File

@ -1,21 +0,0 @@
module.exports = {
"host": "0.0.0.0",
"port": 3000,
"dir": "./dist",
"spa": true,
"proxy": {
"/alfresco/{p*}": {
"options": {
"uri": "http://0.0.0.0:8080/alfresco/{p}"
}
}
},
onResHeaders(headers) {
if (headers) {
const authHeader = headers['www-authenticate'];
if (authHeader) {
headers['www-authenticate'] = `x${authHeader}`;
}
}
}
}

495
yarn.lock
View File

@ -203,11 +203,11 @@
version "2.6.2"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.6.2.tgz#6e6d4cb183cd55c7a1ad6270bced10fdd5367a3c"
"@types/jasmine@~2.5.53":
version "2.5.54"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.54.tgz#a6b5f2ae2afb6e0307774e8c7c608e037d491c63"
"@types/jasmine@^2.5.53":
version "2.8.2"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.2.tgz#6ae4d8740c0da5d5a627df725b4eed71b8e36668"
"@types/jasminewd2@~2.0.2":
"@types/jasminewd2@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.3.tgz#0d2886b0cbdae4c0eeba55e30792f584bf040a95"
dependencies:
@ -229,13 +229,6 @@ abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
accept@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/accept/-/accept-2.1.4.tgz#887af54ceee5c7f4430461971ec400c61d09acbb"
dependencies:
boom "5.x.x"
hoek "4.x.x"
accepts@1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
@ -326,13 +319,6 @@ amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
ammo@2.x.x, ammo@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/ammo/-/ammo-2.0.4.tgz#bf80aab211698ea78f63ef5e7f113dd5d9e8917f"
dependencies:
boom "5.x.x"
hoek "4.x.x"
ansi-html@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
@ -516,10 +502,6 @@ aws4@^1.2.1, aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
b64@3.x.x:
version "3.0.3"
resolved "https://registry.yarnpkg.com/b64/-/b64-3.0.3.tgz#36afeee0d9345f046387ce6de8a6702afe5bb56e"
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@ -678,15 +660,6 @@ body-parser@1.18.2, body-parser@^1.16.1:
raw-body "2.3.2"
type-is "~1.6.15"
body@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069"
dependencies:
continuable-cache "^0.3.1"
error "^7.0.0"
raw-body "~1.1.0"
safe-json-parse "~1.0.1"
bonjour@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
@ -714,7 +687,7 @@ boom@4.x.x:
dependencies:
hoek "4.x.x"
boom@5.x.x, boom@^5.2.0:
boom@5.x.x:
version "5.2.0"
resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02"
dependencies:
@ -828,21 +801,10 @@ builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
bytes@1:
version "1.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-1.0.0.tgz#3569ede8ba34315fab99c3e92cb04c7220de1fa8"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
call@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/call/-/call-4.0.2.tgz#df76f5f51ee8dd48b856ac8400f7e69e6d7399c4"
dependencies:
boom "5.x.x"
hoek "4.x.x"
callsite@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
@ -894,20 +856,6 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
catbox-memory@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/catbox-memory/-/catbox-memory-2.0.4.tgz#433e255902caf54233d1286429c8f4df14e822d5"
dependencies:
hoek "4.x.x"
catbox@^7.1.5:
version "7.1.5"
resolved "https://registry.yarnpkg.com/catbox/-/catbox-7.1.5.tgz#c56f7e8e9555d27c0dc038a96ef73e57d186bb1f"
dependencies:
boom "5.x.x"
hoek "4.x.x"
joi "10.x.x"
center-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
@ -937,7 +885,7 @@ charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
chokidar@1.7.0, chokidar@^1.4.1, chokidar@^1.6.0, chokidar@^1.7.0:
chokidar@^1.4.1, chokidar@^1.6.0, chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
dependencies:
@ -1164,16 +1112,6 @@ content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
content@3.x.x:
version "3.0.6"
resolved "https://registry.yarnpkg.com/content/-/content-3.0.6.tgz#9c2e301e9ae515ed65a4b877d78aa5659bb1b809"
dependencies:
boom "5.x.x"
continuable-cache@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f"
convert-source-map@^1.3.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
@ -1211,6 +1149,10 @@ core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
core-object@^3.1.0:
version "3.1.5"
resolved "https://registry.yarnpkg.com/core-object/-/core-object-3.1.5.tgz#fa627b87502adc98045e44678e9a8ec3b9c0d2a9"
@ -1285,7 +1227,7 @@ cryptiles@2.x.x:
dependencies:
boom "2.x.x"
cryptiles@3.x.x, cryptiles@^3.1.2:
cryptiles@3.x.x:
version "3.1.2"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe"
dependencies:
@ -1447,7 +1389,7 @@ debug@*, debug@^3.1.0:
dependencies:
ms "2.0.0"
debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9, debug@~2.6.7:
debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
@ -1645,15 +1587,6 @@ domutils@1.5.1:
dom-serializer "0"
domelementtype "1"
duplexify@^3.1.2:
version "3.5.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
readable-stream "^2.0.0"
stream-shift "^1.0.0"
ecc-jsbn@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@ -1696,12 +1629,6 @@ encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
dependencies:
once "^1.4.0"
engine.io-client@1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab"
@ -1770,13 +1697,6 @@ error-ex@^1.2.0:
dependencies:
is-arrayish "^0.2.1"
error@^7.0.0:
version "7.0.2"
resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02"
dependencies:
string-template "~0.2.1"
xtend "~4.0.0"
es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.7:
version "0.10.35"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.35.tgz#18ee858ce6a3c45c7d79e91c15fcca9ec568494f"
@ -1803,6 +1723,10 @@ es6-map@^0.1.3:
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
es6-set@~0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
@ -2024,15 +1948,11 @@ fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
fast-safe-stringify@1.1.x:
version "1.1.13"
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-1.1.13.tgz#a01e9cd9c9e491715c98a75a42d5f0bbd107ff76"
fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
faye-websocket@^0.10.0, faye-websocket@~0.10.0:
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
dependencies:
@ -2340,44 +2260,10 @@ globule@^1.0.0:
lodash "~4.17.4"
minimatch "~3.0.2"
good-console@6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/good-console/-/good-console-6.4.0.tgz#7294c9d90c4c9f059a082e180625495966d2ba59"
dependencies:
hoek "4.x.x"
joi "8.1.x"
json-stringify-safe "5.0.x"
moment "2.15.x"
good-squeeze@5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/good-squeeze/-/good-squeeze-5.0.2.tgz#a8e58242b4a0b32cdbdf317b60e73a19a7f0879b"
dependencies:
fast-safe-stringify "1.1.x"
hoek "4.x.x"
good@7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/good/-/good-7.3.0.tgz#25da74d51f336692ec86fe8d6533453585fa85fe"
dependencies:
hoek "4.x.x"
joi "10.x.x"
oppsy "1.x.x"
pumpify "1.3.x"
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
h2o2@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/h2o2/-/h2o2-6.0.1.tgz#7510c93506327099d35b289b7bca1af92b9fb683"
dependencies:
boom "5.x.x"
hoek "4.x.x"
joi "10.x.x"
wreck "12.x.x"
hammerjs@2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1"
@ -2404,29 +2290,6 @@ handlebars@^4.0.3:
optionalDependencies:
uglify-js "^2.6"
hapi@16.6.0:
version "16.6.0"
resolved "https://registry.yarnpkg.com/hapi/-/hapi-16.6.0.tgz#c97cc7119a04314553883868651862fee34318ee"
dependencies:
accept "^2.1.4"
ammo "^2.0.4"
boom "^5.2.0"
call "^4.0.2"
catbox "^7.1.5"
catbox-memory "^2.0.4"
cryptiles "^3.1.2"
heavy "^4.0.4"
hoek "^4.2.0"
iron "^4.0.5"
items "^2.1.1"
joi "^10.6.0"
mimos "^3.0.3"
podium "^1.3.0"
shot "^3.4.2"
statehood "^5.0.3"
subtext "^5.0.0"
topo "^2.0.2"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
@ -2525,14 +2388,6 @@ he@1.1.x:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
heavy@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/heavy/-/heavy-4.0.4.tgz#36c91336c00ccfe852caa4d153086335cd2f00e9"
dependencies:
boom "5.x.x"
hoek "4.x.x"
joi "10.x.x"
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -2545,7 +2400,7 @@ hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoek@4.x.x, hoek@^4.2.0:
hoek@4.x.x:
version "4.2.0"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
@ -2698,6 +2553,10 @@ img-stats@^0.5.2:
dependencies:
xmldom "^0.1.19"
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
in-publish@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
@ -2716,17 +2575,6 @@ indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
inert@4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/inert/-/inert-4.2.1.tgz#da743c478a18a8378032f80ada128a28cd2bba93"
dependencies:
ammo "2.x.x"
boom "5.x.x"
hoek "4.x.x"
items "2.x.x"
joi "10.x.x"
lru-cache "4.1.x"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@ -2774,14 +2622,6 @@ ipaddr.js@1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
iron@4.x.x, iron@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428"
dependencies:
boom "5.x.x"
cryptiles "3.x.x"
hoek "4.x.x"
is-absolute-url@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
@ -2950,10 +2790,6 @@ isbinaryfile@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
isemail@2.x.x:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -3044,32 +2880,24 @@ istanbul-reports@^1.1.3:
dependencies:
handlebars "^4.0.3"
items@2.x.x, items@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198"
jasmine-core@~2.6.2:
version "2.6.4"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.4.tgz#dec926cd0a9fa287fb6db5c755fa487e74cecac5"
jasmine-core@~2.8.0:
jasmine-core@^2.6.2, jasmine-core@~2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e"
jasmine-reporters@2.2.1:
jasmine-reporters@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/jasmine-reporters/-/jasmine-reporters-2.2.1.tgz#de9a9201367846269e7ca8adff5b44221671fcbd"
dependencies:
mkdirp "^0.5.1"
xmldom "^0.1.22"
jasmine-spec-reporter@~4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-4.1.1.tgz#5a6d58ab5d61bea7309fbc279239511756b1b588"
jasmine-spec-reporter@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz#1d632aec0341670ad324f92ba84b4b32b35e9e22"
dependencies:
colors "1.1.2"
jasmine2-protractor-utils@1.3.0:
jasmine2-protractor-utils@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/jasmine2-protractor-utils/-/jasmine2-protractor-utils-1.3.0.tgz#94046aabbc74ad0a4b746bcd4dc30507587b67e3"
dependencies:
@ -3089,24 +2917,6 @@ jasminewd2@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e"
joi@10.x.x, joi@^10.6.0:
version "10.6.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-10.6.0.tgz#52587f02d52b8b75cdb0c74f0b164a191a0e1fc2"
dependencies:
hoek "4.x.x"
isemail "2.x.x"
items "2.x.x"
topo "2.x.x"
joi@8.1.x:
version "8.1.1"
resolved "https://registry.yarnpkg.com/joi/-/joi-8.1.1.tgz#2d8b52a5d909d217ed47248577eefe8b1798f48f"
dependencies:
hoek "4.x.x"
isemail "2.x.x"
moment "2.x.x"
topo "2.x.x"
js-base64@^2.1.5, js-base64@^2.1.8, js-base64@^2.1.9:
version "2.3.2"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf"
@ -3159,7 +2969,7 @@ json-stable-stringify@^1.0.1:
dependencies:
jsonify "~0.0.0"
json-stringify-safe@5.0.x, json-stringify-safe@~5.0.1:
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@ -3196,6 +3006,16 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.10.0"
jszip@^3.1.3:
version "3.1.5"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.1.5.tgz#e3c2a6c6d706ac6e603314036d43cd40beefdf37"
dependencies:
core-js "~2.3.0"
es6-promise "~3.0.2"
lie "~3.1.0"
pako "~1.0.2"
readable-stream "~2.0.6"
karma-chrome-launcher@~2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.1.1.tgz#216879c68ac04d8d5140e99619ba04b59afd46cf"
@ -3329,9 +3149,11 @@ license-webpack-plugin@^1.0.0:
dependencies:
ejs "^2.5.7"
livereload-js@2.2.2, livereload-js@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.2.2.tgz#6c87257e648ab475bc24ea257457edcc1f8d0bc2"
lie@~3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
dependencies:
immediate "~3.0.5"
load-json-file@^1.0.0:
version "1.1.0"
@ -3408,14 +3230,14 @@ lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
lodash@4.17.4, lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
lodash@^3.8.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
log4js@^0.6.31:
version "0.6.38"
resolved "https://registry.yarnpkg.com/log4js/-/log4js-0.6.38.tgz#2c494116695d6fb25480943d3fc872e662a522fd"
@ -3452,7 +3274,7 @@ lru-cache@2.2.x:
version "2.2.4"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
lru-cache@4.1.x, lru-cache@^4.0.1:
lru-cache@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55"
dependencies:
@ -3561,7 +3383,7 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
mime-db@1.x.x, "mime-db@>= 1.30.0 < 2":
"mime-db@>= 1.30.0 < 2":
version "1.31.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.31.0.tgz#a49cd8f3ebf3ed1a482b60561d9105ad40ca74cb"
@ -3583,13 +3405,6 @@ mimic-fn@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
mimos@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/mimos/-/mimos-3.0.3.tgz#b9109072ad378c2b72f6a0101c43ddfb2b36641f"
dependencies:
hoek "4.x.x"
mime-db "1.x.x"
minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
@ -3629,14 +3444,10 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd
dependencies:
minimist "0.0.8"
moment@2.15.2, moment@2.15.x:
moment@2.15.2:
version "2.15.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.15.2.tgz#1bfdedf6a6e345f322fe956d5df5bd08a8ce84dc"
moment@2.x.x:
version "2.19.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167"
ms@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
@ -3856,13 +3667,6 @@ ng2-alfresco-viewer@1.10.0-beta6:
systemjs "0.19.27"
zone.js "0.8.12"
nigel@2.x.x:
version "2.0.2"
resolved "https://registry.yarnpkg.com/nigel/-/nigel-2.0.2.tgz#93a1866fb0c52d87390aa75e2b161f4b5c75e5b1"
dependencies:
hoek "4.x.x"
vise "2.x.x"
no-case@^2.2.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
@ -4091,7 +3895,7 @@ on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0:
once@^1.3.0, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
@ -4104,19 +3908,12 @@ opn@4.0.2:
object-assign "^4.0.1"
pinkie-promise "^2.0.0"
opn@5.1.0, opn@~5.1.0:
opn@~5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519"
dependencies:
is-wsl "^1.1.0"
oppsy@1.x.x:
version "1.0.2"
resolved "https://registry.yarnpkg.com/oppsy/-/oppsy-1.0.2.tgz#98014cd6967653a83cfffa554226dc90050baad4"
dependencies:
hoek "4.x.x"
items "2.x.x"
optimist@^0.6.1, optimist@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@ -4195,6 +3992,10 @@ pako@~0.2.0:
version "0.2.9"
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
pako@~1.0.2:
version "1.0.6"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
param-case@2.1.x:
version "2.1.1"
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
@ -4331,16 +4132,6 @@ performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
pez@2.x.x:
version "2.1.5"
resolved "https://registry.yarnpkg.com/pez/-/pez-2.1.5.tgz#5ec2cc62500cc3eb4236d4a414cf5a17b5eb5007"
dependencies:
b64 "3.x.x"
boom "5.x.x"
content "3.x.x"
hoek "4.x.x"
nigel "2.x.x"
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -4359,14 +4150,6 @@ pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
podium@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/podium/-/podium-1.3.0.tgz#3c490f54d16f10f5260cbe98641f1cb733a8851c"
dependencies:
hoek "4.x.x"
items "2.x.x"
joi "10.x.x"
portfinder@^1.0.9, portfinder@~1.0.12:
version "1.0.13"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
@ -4694,9 +4477,9 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
protractor@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.2.tgz#9b221741709a4c62d5cd53c6aadd54a71137e95f"
protractor@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.2.0.tgz#d3f39b195e85f3539ad9d8cb6560a9d2b63297c4"
dependencies:
"@types/node" "^6.0.46"
"@types/q" "^0.0.32"
@ -4709,7 +4492,7 @@ protractor@~5.1.2:
optimist "~0.6.0"
q "1.4.1"
saucelabs "~1.3.0"
selenium-webdriver "3.0.1"
selenium-webdriver "3.6.0"
source-map-support "~0.4.0"
webdriver-js-extender "^1.0.0"
webdriver-manager "^12.0.6"
@ -4739,21 +4522,6 @@ public-encrypt@^4.0.0:
parse-asn1 "^5.0.0"
randombytes "^2.0.1"
pump@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51"
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
pumpify@1.3.x:
version "1.3.5"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.3.5.tgz#1b671c619940abcaeac0ad0e3a3c164be760993b"
dependencies:
duplexify "^3.1.2"
inherits "^2.0.1"
pump "^1.0.0"
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@ -4774,7 +4542,7 @@ qjobs@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
qs@6.5.1, qs@^6.4.0, qs@^6.5.1, qs@~6.5.1:
qs@6.5.1, qs@^6.5.1, qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
@ -4838,13 +4606,6 @@ raw-body@2.3.2:
iconv-lite "0.4.19"
unpipe "1.0.0"
raw-body@~1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425"
dependencies:
bytes "1"
string_decoder "0.10"
raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
@ -4897,7 +4658,7 @@ readable-stream@1.0, readable-stream@~1.0.2:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.6, readable-stream@^2.2.9:
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.6, readable-stream@^2.2.9:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
@ -4909,6 +4670,17 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
readable-stream@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
readdirp@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
@ -5093,7 +4865,7 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1:
rimraf@2, rimraf@2.6.2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
@ -5122,10 +4894,6 @@ safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
safe-json-parse@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/safe-json-parse/-/safe-json-parse-1.0.1.tgz#3e76723e38dfdda13c9b1d29a1e07ffee4b30b57"
sass-graph@^2.1.1:
version "2.2.4"
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
@ -5180,11 +4948,11 @@ select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
selenium-webdriver@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz#a2dea5da4a97f6672e89e7ca7276cefa365147a7"
selenium-webdriver@3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc"
dependencies:
adm-zip "^0.4.7"
jszip "^3.1.3"
rimraf "^2.5.4"
tmp "0.0.30"
xml2js "^0.4.17"
@ -5312,13 +5080,6 @@ shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shot@^3.4.2:
version "3.4.2"
resolved "https://registry.yarnpkg.com/shot/-/shot-3.4.2.tgz#1e5c3f6f2b26649adc42f7eb350214a5a0291d67"
dependencies:
hoek "4.x.x"
joi "10.x.x"
signal-exit@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@ -5506,17 +5267,6 @@ sshpk@^1.7.0:
jsbn "~0.1.0"
tweetnacl "~0.14.0"
statehood@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/statehood/-/statehood-5.0.3.tgz#c07a75620db5379b60d2edd47f538002a8ac7dd6"
dependencies:
boom "5.x.x"
cryptiles "3.x.x"
hoek "4.x.x"
iron "4.x.x"
items "2.x.x"
joi "10.x.x"
"statuses@>= 1.3.1 < 2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
@ -5548,18 +5298,10 @@ stream-http@^2.3.1:
to-arraybuffer "^1.0.0"
xtend "^4.0.0"
stream-shift@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
string-template@~0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@ -5575,7 +5317,7 @@ string-width@^2.0.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string_decoder@0.10, string_decoder@^0.10.25, string_decoder@~0.10.x:
string_decoder@^0.10.25, string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@ -5650,16 +5392,6 @@ stylus@^0.54.5:
sax "0.5.x"
source-map "0.1.x"
subtext@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/subtext/-/subtext-5.0.0.tgz#9c3f083018bb1586b167ad8cfd87083f5ccdfe0f"
dependencies:
boom "5.x.x"
content "3.x.x"
hoek "4.x.x"
pez "2.x.x"
wreck "12.x.x"
superagent@3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.7.0.tgz#bd58bfde2cbc5305adb9ccbb6dacba18408629d6"
@ -5756,17 +5488,6 @@ timers-browserify@^2.0.2:
dependencies:
setimmediate "^1.0.4"
tiny-lr@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.0.5.tgz#21f40bf84ebd1f853056680375eef1670c334112"
dependencies:
body "^5.1.0"
debug "~2.6.7"
faye-websocket "~0.10.0"
livereload-js "^2.2.2"
object-assign "^4.1.0"
qs "^6.4.0"
tmp@0.0.24:
version "0.0.24"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12"
@ -5801,12 +5522,6 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
topo@2.x.x, topo@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182"
dependencies:
hoek "4.x.x"
toposort@^1.0.0:
version "1.0.6"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec"
@ -6079,12 +5794,6 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vise@2.x.x:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vise/-/vise-2.0.2.tgz#6b08e8fb4cb76e3a50cd6dd0ec37338e811a0d39"
dependencies:
hoek "4.x.x"
vlq@^0.2.1:
version "0.2.3"
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
@ -6294,13 +6003,6 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
wreck@12.x.x:
version "12.5.1"
resolved "https://registry.yarnpkg.com/wreck/-/wreck-12.5.1.tgz#cd2ffce167449e1f0242ed9cf80552e20fb6902a"
dependencies:
boom "5.x.x"
hoek "4.x.x"
ws@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f"
@ -6315,23 +6017,6 @@ ws@^1.0.1:
options ">=0.0.5"
ultron "1.0.x"
wsrv@0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/wsrv/-/wsrv-0.2.2.tgz#16b9623c3802dee21c54978ae882aaea9c721ae0"
dependencies:
chokidar "1.7.0"
good "7.3.0"
good-console "6.4.0"
good-squeeze "5.0.2"
h2o2 "6.0.1"
hapi "16.6.0"
inert "4.2.1"
livereload-js "2.2.2"
lodash "4.17.4"
opn "5.1.0"
tiny-lr "1.0.5"
yargs "9.0.1"
wtf-8@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a"
@ -6366,7 +6051,7 @@ xmlhttprequest-ssl@1.5.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz#185a888c04eca46c3e4070d99f7b49de3528992d"
xtend@^4.0.0, xtend@~4.0.0:
xtend@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
@ -6396,24 +6081,6 @@ yargs-parser@^7.0.0:
dependencies:
camelcase "^4.1.0"
yargs@9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c"
dependencies:
camelcase "^4.1.0"
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
os-locale "^2.0.0"
read-pkg-up "^2.0.0"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^7.0.0"
yargs@^6.0.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"