[ADF-3259] [ADF-3363] e2e login and card metadata (#3612)

* remember me

* add login component e2e test

* add success route test

* add change logo check

* redirect url after logout e2e

* move redirection test in a separate file

* login component tslint

* cardview e2e

* fix login test

* add test case number

* move version test in a separate file

* clean unused elements

* metadata part 1

* tslint fix

* fix metadata test

* remove fit

* fix formatting file viewerPage

* multi propety test

* metadata and login improvements

* fix data automation fix

* metadata permission e2e

* fix tslint problems

* improve selector

* stabilize search component test

* stabilize test step 1

* fix tag test
add config timeout

* tentative

* delay after download

* change meatdata test

* stabilize metadata

* use smaller file for not extension related test

* stabilize test step 2

* exclude failing test

* timeout fix

* split in multiple task e2e

* trick travis

* trigger build

* fix command issue

* fix save screenshot

* fix run subfolder

* test timeout increase
This commit is contained in:
Eugenio Romano
2018-07-23 14:11:54 +01:00
committed by Eugenio Romano
parent 66f534b32c
commit b2cb93468d
116 changed files with 3936 additions and 1519 deletions

View File

@@ -59,7 +59,9 @@ import { NotificationsComponent } from './components/notifications/notifications
import { ReportIssueComponent } from './components/report-issue/report-issue.component';
import { CardViewComponent } from './components/card-view/card-view.component';
import { HeaderDataComponent } from './components/header-data/header-data.component';
import { ConfigEditorComponent } from './components/config-editor/config-editor.component';
import { HeaderDataService } from './components/header-data/header-data.service';
import { MonacoEditorModule } from 'ngx-monaco-editor';
@NgModule({
imports: [
@@ -73,7 +75,8 @@ import { HeaderDataService } from './components/header-data/header-data.service'
FlexLayoutModule,
ChartsModule,
HttpClientModule,
AdfModule
AdfModule,
MonacoEditorModule.forRoot()
],
declarations: [
AppComponent,
@@ -119,7 +122,8 @@ import { HeaderDataService } from './components/header-data/header-data.service'
ReportIssueComponent,
TaskListDemoComponent,
ProcessListDemoComponent,
HeaderDataComponent
HeaderDataComponent,
ConfigEditorComponent
],
providers: [
{ provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production

View File

@@ -56,6 +56,7 @@ import { CardViewComponent } from './components/card-view/card-view.component';
import { ContentNodeSelectorComponent } from './components/content-node-selector/content-node-selector.component';
import { ReportIssueComponent } from './components/report-issue/report-issue.component';
import { HeaderDataComponent } from './components/header-data/header-data.component';
import { ConfigEditorComponent } from './components/config-editor/config-editor.component';
export const appRoutes: Routes = [
{ path: 'login', component: LoginComponent },
@@ -79,6 +80,16 @@ export const appRoutes: Routes = [
}
]
},
{
path: 'config-editor',
component: AppLayoutComponent ,
children: [
{
path: '',
component: ConfigEditorComponent
}
]
},
{
path: 'card-view',
component: AppLayoutComponent ,

View File

@@ -2,7 +2,7 @@
<adf-sidenav-layout-header>
<ng-template let-toggleMenu="toggleMenu">
<adf-layout-header [title]="title | translate" [logo]="logo" [showSidenavToggle]="showMenu" [color]="color" (clicked)=toggleMenu($event) >
<adf-layout-header id="adf-header" [title]="title | translate" [logo]="logo" [showSidenavToggle]="showMenu" [color]="color" (clicked)=toggleMenu($event) >
<div class="adf-app-layout-menu-spacer"></div>

View File

@@ -54,6 +54,7 @@ export class AppLayoutComponent implements OnInit {
{ href: '/tag', icon: 'local_offer', title: 'APP_LAYOUT.TAG' },
{ href: '/social', icon: 'thumb_up', title: 'APP_LAYOUT.SOCIAL' },
{ href: '/settings-layout', icon: 'settings', title: 'APP_LAYOUT.SETTINGS' },
{ href: '/config-editor', icon: 'code', title: 'APP_LAYOUT.CONFIG-EDITOR' },
{ href: '/extendedSearch', icon: 'search', title: 'APP_LAYOUT.SEARCH' },
{ href: '/overlay-viewer', icon: 'pageview', title: 'APP_LAYOUT.OVERLAY_VIEWER' },
{ href: '/about', icon: 'info_outline', title: 'APP_LAYOUT.ABOUT' }

View File

@@ -14,3 +14,17 @@
</div>
</div>
<p class="toggle">
<mat-slide-toggle
id="adf-toogle-editable"
[color]="'primary'"
(change)="toggleEditable()"
[checked]="isEditable">
Editable
</mat-slide-toggle>
</p>
<button mat-button id="adf-reset-card-log" (click)="reset()" color="primary">Reset Log</button>
<br>

View File

@@ -26,6 +26,7 @@ import {
CardViewKeyValuePairsItemModel,
CardViewSelectItemModel,
CardViewUpdateService,
CardViewMapItemModel,
UpdateNotification
} from '@alfresco/adf-core';
import { of } from 'rxjs/observable/of';
@@ -38,78 +39,89 @@ export class CardViewComponent implements OnInit {
@ViewChild('console') console: ElementRef;
isEditable = true;
properties: any;
logs: string[];
constructor(private cardViewUpdateService: CardViewUpdateService) {
this.logs = [];
this.createCard();
}
ngOnInit() {
this.cardViewUpdateService.itemUpdated$.subscribe(this.onItemChange.bind(this));
}
createCard() {
this.properties = [
new CardViewTextItemModel({
label: 'CardView Text Item',
value: 'Spock',
key: 'name',
default: 'default bar' ,
default: 'default bar',
multiline: false,
icon: 'icon',
editable: true
editable: this.isEditable
}),
new CardViewDateItemModel({
label: 'CardView Date Item',
value: new Date(),
key: 'date-of-birth',
default: new Date(),
value: new Date(1983, 11, 24, 10, 0, 30),
key: 'date',
default: new Date(1983, 11, 24, 10, 0, 30),
format: 'DD.MM.YYYY',
editable: true
editable: this.isEditable
}),
new CardViewDatetimeItemModel({
label: 'CardView Datetime Item',
value: new Date(),
key: 'datetime-of-birth',
default: new Date(),
value: new Date(1983, 11, 24, 10, 0, 0),
key: 'datetime',
default: new Date(1983, 11, 24, 10, 0, 0),
format: 'DD.MM.YYYY',
editable: true
editable: this.isEditable
}),
new CardViewBoolItemModel({
label: 'CardView Boolean Item',
value: true,
key: 'vulcanian',
key: 'boolean',
default: false,
editable: true
editable: this.isEditable
}),
new CardViewIntItemModel({
label: 'CardView Int Item',
value: 213,
key: 'intelligence',
key: 'int',
default: 1,
editable: true
editable: this.isEditable
}),
new CardViewFloatItemModel({
label: 'CardView Float Item',
value: 9.9,
key: 'mental-stability',
key: 'float',
default: 0.0,
editable: true
editable: this.isEditable
}),
new CardViewKeyValuePairsItemModel({
label: 'CardView Key-Value Pairs Item',
value: [],
key: 'key-value-pairs',
editable: true
editable: this.isEditable
}),
new CardViewSelectItemModel({
label: 'CardView Select Item',
value: 'one',
options$: of([{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }]),
key: 'select',
editable: true
editable: this.isEditable
}),
new CardViewMapItemModel({
label: 'My map',
value: new Map([['999', 'My Value']]),
key: 'map',
default: 'default map value'
})
];
}
ngOnInit() {
this.cardViewUpdateService.itemUpdated$.subscribe(this.onItemChange.bind(this));
}
onItemChange(notification: UpdateNotification) {
let value = notification.changed[notification.target.key];
@@ -120,4 +132,15 @@ export class CardViewComponent implements OnInit {
this.logs.push(`[${notification.target.label}] - ${value}`);
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
}
toggleEditable() {
this.isEditable = !this.isEditable;
this.createCard();
}
reset() {
this.isEditable = true;
this.createCard();
this.logs = [];
}
}

View File

@@ -0,0 +1,9 @@
<h2>Metadata App config editor</h2>
<ngx-monaco-editor id="adf-metadata-editor" class="adf-metadata-editor" [options]="editorOptions" [(ngModel)]="metadataConf" (onInit)="onInitMetadata($event)" ></ngx-monaco-editor>
<button mat-raised-button id="adf-metadata-save" (click)="onSaveMetadata()" color="primary">Save metadata configuration</button>
<button mat-raised-button id="adf-metadata-clear" (click)="onClearMetadata()" color="primary">Clear metadata configuration</button>
<br>

View File

@@ -0,0 +1,3 @@
.adf-metadata-editor {
height: 300px;
}

View File

@@ -0,0 +1,65 @@
/*!
* @license
* Copyright 2016 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 } from '@angular/core';
import { AppConfigService, NotificationService } from '@alfresco/adf-core';
@Component({
selector: 'app-config-editor',
templateUrl: 'config-editor.component.html',
styleUrls: ['./config-editor.component.scss']
})
export class ConfigEditorComponent {
editor: any;
editorOptions = {
theme: 'vs-dark',
language: 'json',
autoIndent: true,
formatOnPaste: true,
formatOnType: true
};
metadataConf: string;
onInitMetadata(editor) {
this.editor = editor;
setTimeout(() => {
this.editor.getAction('editor.action.formatDocument').run();
}, 1000);
}
constructor(private appConfig: AppConfigService, private notificationService: NotificationService) {
this.metadataConf = JSON.stringify(appConfig.config['content-metadata']);
}
onSaveMetadata() {
try {
this.appConfig.config['content-metadata'] = JSON.parse(this.editor.getValue());
} catch (error) {
this.notificationService.openSnackMessage(
'Wrong metadata configuration',
4000
);
}
}
onClearMetadata() {
this.metadataConf = '';
}
}

View File

@@ -7,7 +7,70 @@
</adf-info-drawer-tab>
<adf-info-drawer-tab [label]="'APP.INFO_DRAWER.PROPERTIES' | translate">
<adf-content-metadata-card [node]="node"></adf-content-metadata-card>
<adf-content-metadata-card *ngIf="isPreset" [node]="node"
[multi]="multi"
[preset]="customPreset"
[readOnly]="isReadOnly"
[displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card>
<adf-content-metadata-card *ngIf="!isPreset" [node]="node"
[multi]="multi"
[readOnly]="isReadOnly"
[displayEmpty]="displayEmptyMetadata"></adf-content-metadata-card>
<p class="toggle">
<mat-slide-toggle
id="adf-metadata-empty"
[color]="'primary'"
(change)="toggleEmptyMetadata()"
[checked]="displayEmptyMetadata">
Display Empty Metadata
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-metadata-multi"
[color]="'primary'"
(change)="toggleMulti()"
[checked]="multi">
multi accordion
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-metadata-readonly"
[color]="'primary'"
(change)="toggleReadOnly()"
[checked]="isReadOnly">
Editable
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-toggle-custom-preset"
[color]="'primary'"
(change)="togglePreset()"
[checked]="isPreset">
Custom preset
</mat-slide-toggle>
</p>
<p class="toggle">
<ng-container *ngIf="isPreset">
<mat-form-field floatPlaceholder="float">
<input matInput
placeholder="Custom Preset"
[(ngModel)]="customPreset"
data-automation-id="adf-text-custom-preset">
</mat-form-field>
<button mat-raised-button id="adf-metadata-aplly" (click)="applyCustomPreset()" color="primary">Apply</button>
</ng-container>
</p>
</adf-info-drawer-tab>
<adf-info-drawer-tab [label]="'APP.INFO_DRAWER.VERSIONS' | translate">

View File

@@ -29,6 +29,11 @@ import { MatSnackBar } from '@angular/material';
export class FileViewComponent implements OnInit {
nodeId: string = null;
displayEmptyMetadata = false;
multi = false;
isReadOnly = false;
isPreset = false;
customPreset: string = null;
constructor(private router: Router,
private route: ActivatedRoute,
@@ -58,4 +63,30 @@ export class FileViewComponent implements OnInit {
onUploadError(errorMessage: string) {
this.snackBar.open(errorMessage, '', { duration: 4000 });
}
toggleEmptyMetadata() {
this.displayEmptyMetadata = !this.displayEmptyMetadata;
}
toggleMulti() {
this.multi = !this.multi;
}
toggleReadOnly() {
this.isReadOnly = !this.isReadOnly;
}
togglePreset() {
this.isPreset = !this.isPreset;
if (!this.isPreset) {
this.customPreset = null;
}
}
applyCustomPreset() {
this.isPreset = false;
setTimeout(() => {
this.isPreset = true;
}, 100);
}
}

View File

@@ -33,7 +33,7 @@
</adf-sites-dropdown>
</div>
<div class="document-list-container" fxLayout="row" fxLayoutAlign="start stretch" fxLayoutGap="16px">
<div id="document-list-container" class="document-list-container" fxLayout="row" fxLayoutAlign="start stretch" fxLayoutGap="16px">
<adf-upload-drag-area fxFlex="1 1 auto"
[disabled]="disableDragArea"
[acceptedFilesType]="getFileFiltering()"
@@ -338,6 +338,13 @@
title="DOCUMENT_LIST.ACTIONS.METADATA"
(execute)="onManageMetadata($event)">
</content-action>
<content-action
icon="settings_input_component"
title="DOCUMENT_LIST.ACTIONS.PERMISSION"
permission="copy"
(error)="onContentActionError($event)"
(execute)="onPermissionRequested($event)">
</content-action>
<!-- document actions -->
<content-action
icon="storage"
@@ -346,6 +353,7 @@
(execute)="onManageVersions($event)">
</content-action>
<content-action
target="document"
*ngIf="authenticationService.isBpmLoggedIn()"
icon="play_arrow"
target="document"
@@ -353,13 +361,7 @@
(execute)="startProcesAction($event)">
</content-action>
<content-action
icon="settings_input_component"
title="DOCUMENT_LIST.ACTIONS.PERMISSION"
permission="copy"
(error)="onContentActionError($event)"
(execute)="onPermissionRequested($event)">
</content-action>
<content-action
target="document"
icon="lock"
permission="lock"
handler="lock"

View File

@@ -25,13 +25,18 @@ import { MatDialog } from '@angular/material';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { MinimalNodeEntity, NodePaging, Pagination, MinimalNodeEntryEntity, SiteEntry } from 'alfresco-js-api';
import {
AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService,
AlfrescoApiService, AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService,
FileUploadEvent, FolderCreatedEvent, LogService, NotificationService,
UploadService, DataColumn, DataRow, UserPreferencesService,
PaginationComponent, FormValues, DisplayMode, UserPreferenceValues, InfinitePaginationComponent
} from '@alfresco/adf-core';
import { DocumentListComponent, PermissionStyleModel, UploadFilesEvent, ConfirmDialogComponent } from '@alfresco/adf-content-services';
import {
DocumentListComponent,
PermissionStyleModel,
UploadFilesEvent,
ConfirmDialogComponent
} from '@alfresco/adf-content-services';
import { SelectAppsDialogComponent } from '@alfresco/adf-process-services';
@@ -192,11 +197,16 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
private preference: UserPreferencesService,
private preview: PreviewService,
@Optional() private route: ActivatedRoute,
public authenticationService: AuthenticationService) {
public authenticationService: AuthenticationService,
public alfrescoApiService: AlfrescoApiService) {
this.preference.select(UserPreferenceValues.SupportedPageSizes)
.subscribe((pages) => {
this.supportedPages = pages;
});
this.alfrescoApiService.nodeUpdated.subscribe(() => {
this.documentList.reload();
});
}
showFile(event) {

View File

@@ -19,6 +19,55 @@
{{ 'LOGIN.LOGIN_FOOTER'| translate }}
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-toogle-show-rememberme"
[color]="'primary'"
(change)="toggleRemamberme()"
[checked]="showRememberMe">
{{ 'LOGIN.SHOW_REMEMBERME'| translate }}
</mat-slide-toggle>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-toogle-show-successRoute"
[color]="'primary'"
(change)="toggleSuccessRoute()"
[checked]="customSuccessRoute">
{{ 'LOGIN.SHOW_SUCCESS_ROUTE'| translate }}
</mat-slide-toggle>
</p>
<p class="toggle">
<ng-container *ngIf="customSuccessRoute">
<mat-form-field floatPlaceholder="float">
<input matInput
placeholder="Custom success route"
[(ngModel)]="customSuccessRouteURI"
data-automation-id="adf-success-route">
</mat-form-field>
</ng-container>
</p>
<p class="toggle">
<mat-slide-toggle
id="adf-toogle-logo"
[color]="'primary'"
(change)="toggleLogo()"
[checked]="customLogoImage">
{{ 'LOGIN.CUSTOM_LOGO'| translate }}
</mat-slide-toggle>
</p>
<p class="toggle">
<ng-container *ngIf="customLogoImage">
<mat-form-field floatPlaceholder="float">
<input matInput
placeholder="Custom success Logo URL"
[(ngModel)]="customLogoImageURL"
data-automation-id="adf-url-logo">
</mat-form-field>
</ng-container>
</p>
</div>
<!--SETTING BUTTON-->
@@ -29,10 +78,12 @@
<adf-login
#alfrescologin
[successRoute]="customSuccessRouteURI"
[logoImageUrl]="customLogoImageURL"
[fieldsValidation]="customValidation"
[disableCsrf]="disableCsrf"
[showLoginActions]="showFooter"
[showRememberMe]="showFooter"
[showRememberMe]="showFooter && showRememberMe"
(executeSubmit)="checkForm($event)"
copyrightText="{{ 'application.copyright' | adfAppConfig }}"
(success)="onLogin($event)"
@@ -56,7 +107,9 @@
{{ 'LOGIN.LOGIN_FOOTER'| translate }}
</mat-slide-toggle>
</p>
<button type="button" mat-raised-button color="accent" class="mobile-setting-button" routerLink="/settings" data-automation-id="settings">{{ 'APP_LAYOUT.SETTINGS'| translate }}</button>
<button type="button" mat-raised-button color="accent" class="mobile-setting-button" routerLink="/settings"
data-automation-id="settings">{{ 'APP_LAYOUT.SETTINGS'| translate }}
</button>
</div>
</adf-login>

View File

@@ -31,9 +31,14 @@ export class LoginComponent implements OnInit {
alfrescologin: any;
customValidation: any;
customSuccessRouteURI = '';
customLogoImageURL = './assets/images/alfresco-logo.svg';
disableCsrf = false;
showFooter = true;
showRememberMe = true;
customSuccessRoute = false;
customLogoImage = false;
customMinLength = 2;
constructor(private router: Router,
@@ -46,7 +51,7 @@ export class LoginComponent implements OnInit {
ngOnInit() {
this.alfrescologin.addCustomValidationError('username', 'required', 'LOGIN.MESSAGES.USERNAME-REQUIRED');
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN', {minLength: this.customMinLength});
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN', { minLength: this.customMinLength });
this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED');
}
@@ -66,6 +71,24 @@ export class LoginComponent implements OnInit {
this.showFooter = !this.showFooter;
}
toggleRemamberme() {
this.showRememberMe = !this.showRememberMe;
}
toggleSuccessRoute() {
this.customSuccessRoute = !this.customSuccessRoute;
if (!this.customSuccessRoute) {
this.customSuccessRouteURI = null;
}
}
toggleLogo() {
this.customLogoImage = !this.customLogoImage;
if (!this.customLogoImage) {
this.customLogoImageURL = null;
}
}
checkForm(event: any) {
const values = event.values;
this.logService.log(values);