diff --git a/.editorconfig b/.editorconfig index 9b7352176..4a874ce23 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,6 @@ trim_trailing_whitespace = true [*.md] max_line_length = off trim_trailing_whitespace = false + +[*.yml] +indent_size = 2 diff --git a/.travis.yml b/.travis.yml index 9b68812ed..f9a1b2411 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ dist: trusty -sudo: false +sudo: required language: node_js node_js: @@ -9,15 +9,24 @@ cache: directories: - ./node_modules - -before_install: - - export CHROME_BIN=chromium-browser - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" +services: + - docker install: - npm install script: - - xvfb-run -a npm run test -- --single-run --no-progress --browser=ChromeNoSandbox - #- xvfb-run -a npm run e2e -- --no-progress --config=protractor-ci.conf.js + - npm run build + - npm run test -- --single-run --no-progress + +# Send coverage data to codecov +after_success: + - bash <(curl -s https://codecov.io/bash) -X gcov + - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH" + - export TAG=`if [ "$BRANCH" == "master" ]; then echo "latest"; else echo $BRANCH ; fi` + - docker build -t $DOCKER_REPO:$TAG . + # Publish extra image based on Travis build number + - docker tag $DOCKER_REPO:$TAG $DOCKER_REPO:travis-$TRAVIS_BUILD_NUMBER + - docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" + - docker push $DOCKER_REPO diff --git a/README.md b/README.md index e1e1bdc9b..769f9c32c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,24 @@ -# Alfresco Content App +# Alfresco Example Content Application + +

+ Alfresco +

+ +## Introduction + +The Alfresco Content Application is an example application built using +[Alfresco Application Development Framework (ADF)](https://github.com/Alfresco/alfresco-ng2-components) components and was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.4.7. + +### Who is this example application for + +This example application demonstrates to Angular software engineers +how to construct a content application using the Alfresco ADF. + +This example application represents a meaningful composition of ADF components that provide end users +with a simple and easy to use interface for working with files stored in the Alfresco Content Services repository. [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 Run `npm start` for a dev server. Navigate to `http://localhost:3000/` (opens by default). diff --git a/alfresco.png b/alfresco.png new file mode 100644 index 000000000..7f6326b0b Binary files /dev/null and b/alfresco.png differ diff --git a/docs/docker.md b/docs/docker.md index ac19fb4fe..fcddc4aca 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -35,10 +35,10 @@ docker image build -t content-app . To run the image locally, you can use the following command: ```sh -docker container run -p 80:80 --rm content-app +docker container run -p 8888:80 --rm content-app ``` -Navigate to "http://localhost" to access the running application. +Navigate to "http://localhost:8888" to access the running application. ## Docker Compose file diff --git a/karma.conf.js b/karma.conf.js index 410aaa975..abe47fde7 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -38,11 +38,16 @@ module.exports = function (config) { colors: true, logLevel: config.LOG_INFO, autoWatch: true, - browsers: ['Chrome'], + browsers: ['ChromeHeadless'], customLaunchers: { - ChromeNoSandbox: { + ChromeHeadless: { base: 'Chrome', - flags: ['--no-sandbox'] + flags: [ + '--no-sandbox', + '--headless', + '--disable-gpu', + '--remote-debugging-port=9222' + ] } }, singleRun: false, diff --git a/package.json b/package.json index 3e582ae2a..9f4fd5f20 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build:prod": "npm run server-versions && ng build --prod", "build:dev": "npm run server-versions && ng build && node postbuild-dev.js", "build:tomcat": "npm run server-versions && ng build --base-href ./", - "test": "ng test", + "test": "ng test --code-coverage", "lint": "ng lint", "e2e": "ng e2e", "server-versions": "rimraf ./src/versions.json && npm list --depth=0 --json=true --prod=true > ./src/versions.json || exit 0" diff --git a/src/app/components/files/files.component.spec.ts b/src/app/components/files/files.component.spec.ts index 266be3433..884ee1a83 100644 --- a/src/app/components/files/files.component.spec.ts +++ b/src/app/components/files/files.component.spec.ts @@ -77,7 +77,7 @@ describe('FilesComponent', () => { })); beforeEach(() => { - node = { id: 'node-id' }; + node = { id: 'node-id', isFolder: true }; page = { list: { entries: ['a', 'b', 'c'], @@ -134,6 +134,17 @@ describe('FilesComponent', () => { expect(component.onFetchError).toHaveBeenCalled(); }); + + it('if should navigate to parent if node is not a folder', () => { + node.isFolder = false; + node.parentId = 'parent-id'; + spyOn(component, 'fetchNode').and.returnValue(Observable.of(node)); + spyOn(router, 'navigate'); + + fixture.detectChanges(); + + expect(router.navigate).toHaveBeenCalledWith([ '/personal-files', 'parent-id' ]); + }); }); describe('refresh on events', () => { diff --git a/src/app/components/files/files.component.ts b/src/app/components/files/files.component.ts index 8d3d7e729..96926da40 100644 --- a/src/app/components/files/files.component.ts +++ b/src/app/components/files/files.component.ts @@ -76,7 +76,13 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy { this.isLoading = true; this.fetchNode(nodeId) - .do((node) => this.updateCurrentNode(node)) + .do((node) => { + if (node.isFolder) { + this.updateCurrentNode(node); + } else { + this.router.navigate(['/personal-files', node.parentId]); + } + }) .flatMap((node) => this.fetchNodes(node.id)) .subscribe( (page) => { diff --git a/src/app/components/layout/layout.component.spec.ts b/src/app/components/layout/layout.component.spec.ts index f4fc2930c..5bd92c25e 100644 --- a/src/app/components/layout/layout.component.spec.ts +++ b/src/app/components/layout/layout.component.spec.ts @@ -26,7 +26,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { TestBed, ComponentFixture } from '@angular/core/testing'; import { MinimalNodeEntryEntity } from 'alfresco-js-api'; -import { CoreModule, ContentService, PeopleContentService } from '@alfresco/adf-core'; +import { CoreModule, ContentService, PeopleContentService, AppConfigService } from '@alfresco/adf-core'; import { Observable } from 'rxjs/Observable'; import { BrowsingFilesService } from '../../common/services/browsing-files.service'; @@ -43,6 +43,12 @@ describe('LayoutComponent', () => { let browsingFilesService: BrowsingFilesService; let contentService: ContentService; let node; + const navItem = { + label: 'some-label', + route: { + url: '/some-url' + } + }; beforeEach(() => { node = { id: 'node-id' }; @@ -61,6 +67,7 @@ describe('LayoutComponent', () => { CurrentUserComponent ], providers: [ + AppConfigService, { provide: PeopleContentService, useValue: { @@ -75,6 +82,9 @@ describe('LayoutComponent', () => { browsingFilesService = TestBed.get(BrowsingFilesService); contentService = TestBed.get(ContentService); + const appConfig = TestBed.get(AppConfigService); + spyOn(appConfig, 'get').and.returnValue([navItem]); + fixture.detectChanges(); }); diff --git a/src/app/ui/overrides/_alfresco-document-list.scss b/src/app/ui/overrides/_alfresco-document-list.scss index a73705b0d..c0acf6fe9 100644 --- a/src/app/ui/overrides/_alfresco-document-list.scss +++ b/src/app/ui/overrides/_alfresco-document-list.scss @@ -32,6 +32,11 @@ adf-document-list { } } + td, th { + width: 100%; + text-align: left; + } + .adf-data-table__header--sorted-asc, .adf-data-table__header--sorted-desc { &:hover { @@ -58,13 +63,11 @@ adf-document-list { border: none !important; } - - .adf-data-table-cell--ellipsis { - width: 100%; - } - - .adf-data-table-cell--ellipsis__name { - width: 85%; + th:first-of-type, th.adf-data-table-cell--image, + td:first-of-type, td.adf-data-table-cell--image { + padding-left: 24px; + padding-right: 0; + width: 10px; } .adf-data-table-cell--ellipsis .cell-value, @@ -77,11 +80,18 @@ adf-document-list { .adf-data-table-cell--ellipsis__name .adf-datatable-cell { white-space: nowrap; display: block; - position: absolute; - max-width: calc(100% - 2em); overflow: hidden; text-overflow: ellipsis; } + + .adf-data-table-cell--ellipsis .adf-datatable-cell { + max-width: 7vw; + } + + .adf-data-table-cell--ellipsis__name .adf-datatable-cell { + position: absolute; + max-width: calc(100% - 2em); + } } .empty-list { diff --git a/src/app/ui/overrides/_breadcrumb.scss b/src/app/ui/overrides/_breadcrumb.scss index 035d66e23..010468714 100644 --- a/src/app/ui/overrides/_breadcrumb.scss +++ b/src/app/ui/overrides/_breadcrumb.scss @@ -3,4 +3,8 @@ .adf-breadcrumb { color: $alfresco-secondary-text-color; width: 0; + + &-item:first-child:nth-last-child(1) { + opacity: 1; + } }