mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-16 18:13:06 +00:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
502837ca5c | ||
|
|
19bb9dac8b | ||
|
|
602e5330c0 | ||
|
|
5be8f40ca0 | ||
|
|
9cae48e984 | ||
|
|
487392085f | ||
|
|
3603cb1e67 | ||
|
|
73937d9c67 | ||
|
|
c83f2a57de | ||
|
|
a0f94aa5dc | ||
|
|
bb3d351e63 | ||
|
|
9d468bce56 | ||
|
|
e865782333 | ||
|
|
15409d8fef | ||
|
|
e1ad75f829 | ||
|
|
9c8b058858 | ||
|
|
c542cbca6d | ||
|
|
c8fccccb81 | ||
|
|
d7d838624e | ||
|
|
e5ea283332 | ||
|
|
eeb3b9abe3 | ||
|
|
68735cb88a | ||
|
|
a2afb730fa | ||
|
|
cb8bd6f814 | ||
|
|
8300e9461b | ||
|
|
1bf346c5de | ||
|
|
ffef7688d7 | ||
|
|
f6a300850c | ||
|
|
aad162399b | ||
|
|
546928fe86 | ||
|
|
8a8dfffa90 | ||
|
|
570a75478d | ||
|
|
4697a8fc58 | ||
|
|
a680b47cf5 | ||
|
|
6610a326a7 | ||
|
|
de216d86f0 | ||
|
|
5710749e9d | ||
|
|
9275f22553 | ||
|
|
8f7383d9d0 | ||
|
|
c3db1c2ff8 | ||
|
|
afa298060a |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Alfresco-ADF-Angular-Demo",
|
||||
"description": "Demo shell for Alfresco Angular components",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.5.0-beta1",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -52,8 +52,10 @@
|
||||
"APP_LAYOUT": {
|
||||
"APP_NAME": "ADF Demo Application",
|
||||
"HOME": "Home",
|
||||
"NODE-SELECTOR": "Node Selector",
|
||||
"CONTENT_SERVICES": "Content Services",
|
||||
"BREADCRUMB": "Breadcrumb",
|
||||
"CARD_VIEW": "CardView",
|
||||
"PROCESS_SERVICES": "Process Services",
|
||||
"LOGIN": "Login",
|
||||
"CUSTOM_SOURCES": "Custom Sources",
|
||||
|
||||
@@ -198,7 +198,10 @@
|
||||
"supportedPageSizes": [ 5, 10, 15, 20 ]
|
||||
},
|
||||
"files": {
|
||||
"excluded": [".DS_Store", "desktop.ini", ".git"]
|
||||
"excluded": [".DS_Store", "desktop.ini", ".git"],
|
||||
"match-options": {
|
||||
"nocase": true
|
||||
}
|
||||
},
|
||||
"logLevel": "trace",
|
||||
"activiti": {
|
||||
|
||||
@@ -52,7 +52,10 @@ import { SharedLinkViewComponent } from './components/shared-link-view/shared-li
|
||||
import { DemoPermissionComponent } from './components/permissions/demo-permissions.component';
|
||||
import { PreviewService } from './services/preview.service';
|
||||
import { BreadcrumbDemoComponent } from './components/breadcrumb-demo/breadcrumb-demo.component';
|
||||
import { ContentNodeSelectorComponent } from './components/content-node-selector/content-node-selector.component';
|
||||
import { NotificationsComponent } from './components/notifications/notifications.component';
|
||||
import { ReportIssueComponent } from './components/report-issue/report-issue.component';
|
||||
import { CardViewComponent } from './components/card-view/card-view.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -106,7 +109,10 @@ import { NotificationsComponent } from './components/notifications/notifications
|
||||
FormLoadingComponent,
|
||||
BlobPreviewComponent,
|
||||
BreadcrumbDemoComponent,
|
||||
NotificationsComponent
|
||||
NotificationsComponent,
|
||||
CardViewComponent,
|
||||
ContentNodeSelectorComponent,
|
||||
ReportIssueComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production
|
||||
@@ -128,7 +134,10 @@ import { NotificationsComponent } from './components/notifications/notifications
|
||||
},
|
||||
PreviewService
|
||||
],
|
||||
entryComponents: [VersionManagerDialogAdapterComponent, MetadataDialogAdapterComponent],
|
||||
entryComponents: [
|
||||
VersionManagerDialogAdapterComponent,
|
||||
MetadataDialogAdapterComponent
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -50,6 +50,9 @@ import { DemoPermissionComponent } from './components/permissions/demo-permissio
|
||||
import { BlobPreviewComponent } from './components/blob-preview/blob-preview.component';
|
||||
import { BreadcrumbDemoComponent } from './components/breadcrumb-demo/breadcrumb-demo.component';
|
||||
import { NotificationsComponent } from './components/notifications/notifications.component';
|
||||
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';
|
||||
|
||||
export const appRoutes: Routes = [
|
||||
{ path: 'login', component: LoginComponent },
|
||||
@@ -73,6 +76,16 @@ export const appRoutes: Routes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'card-view',
|
||||
component: AppLayoutComponent ,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: CardViewComponent
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: AppLayoutComponent,
|
||||
@@ -86,6 +99,10 @@ export const appRoutes: Routes = [
|
||||
path: 'home',
|
||||
component: HomeComponent
|
||||
},
|
||||
{
|
||||
path: 'node-selector',
|
||||
component: ContentNodeSelectorComponent
|
||||
},
|
||||
{
|
||||
path: 'settings-layout',
|
||||
component: SettingsComponent
|
||||
@@ -216,6 +233,10 @@ export const appRoutes: Routes = [
|
||||
component: OverlayViewerComponent,
|
||||
canActivate: [AuthGuardEcm]
|
||||
},
|
||||
{
|
||||
path: 'report-issue',
|
||||
component: ReportIssueComponent
|
||||
},
|
||||
{
|
||||
path: 'datatable-lazy',
|
||||
loadChildren: 'app/components/lazy-loading/lazy-loading.module#LazyLoadingModule'
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="false"[expandedSidenav]= "expandedSidenav" (expanded)="setState($event)">
|
||||
<adf-sidenav-layout [sidenavMin]="70" [sidenavMax]="220" [stepOver]="780" [hideSidenav]="hideSidenav" [expandedSidenav]= "expandedSidenav" (expanded)="setState($event)">
|
||||
|
||||
<adf-sidenav-layout-header>
|
||||
<ng-template let-toggleMenu="toggleMenu">
|
||||
<mat-toolbar color="primary" class="adf-app-layout-toolbar mat-elevation-z6">
|
||||
<button mat-icon-button (click)="toggleMenu()">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<adf-layout-header title="{{ 'APP_LAYOUT.APP_NAME' | translate}}" color="primary" (clicked)=toggleMenu($event)>
|
||||
|
||||
<span fxFlex="1 1 auto" fxShow fxHide.lt-sm="true">{{'APP_LAYOUT.APP_NAME' | translate }}</span>
|
||||
<div class="adf-app-layout-menu-spacer"></div>
|
||||
|
||||
<div class="adf-app-layout-menu-spacer"></div>
|
||||
<app-search-bar fxFlex="0 1 auto"></app-search-bar>
|
||||
|
||||
<app-search-bar fxFlex="0 1 auto"></app-search-bar>
|
||||
<div class="adf-header-delimiter"></div>
|
||||
|
||||
<adf-userinfo
|
||||
class="adf-app-layout-user-profile"
|
||||
[menuPositionX]="'before'"
|
||||
[menuPositionY]="'above'">
|
||||
</adf-userinfo>
|
||||
<adf-userinfo
|
||||
class="adf-app-layout-user-profile"
|
||||
[menuPositionX]="'before'"
|
||||
[menuPositionY]="'above'">
|
||||
</adf-userinfo>
|
||||
|
||||
<app-theme-picker></app-theme-picker>
|
||||
<button mat-icon-button [matMenuTriggerFor]="langMenu">
|
||||
<mat-icon>language</mat-icon>
|
||||
</button>
|
||||
<mat-menu #langMenu="matMenu" class="adf-menu">
|
||||
<adf-language-menu></adf-language-menu>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
<app-theme-picker></app-theme-picker>
|
||||
<button mat-icon-button [matMenuTriggerFor]="langMenu">
|
||||
<mat-icon>language</mat-icon>
|
||||
</button>
|
||||
<mat-menu #langMenu="matMenu" class="adf-menu">
|
||||
<adf-language-menu></adf-language-menu>
|
||||
</mat-menu>
|
||||
|
||||
</adf-layout-header>
|
||||
</ng-template>
|
||||
</adf-sidenav-layout-header>
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ export class AppLayoutComponent implements OnInit {
|
||||
{ href: '/files', icon: 'folder_open', title: 'APP_LAYOUT.CONTENT_SERVICES' },
|
||||
{ href: '/breadcrumb', icon: 'label', title: 'APP_LAYOUT.BREADCRUMB' },
|
||||
{ href: '/notifications', icon: 'alarm', title: 'APP_LAYOUT.NOTIFICATIONS'},
|
||||
{ href: '/card-view', icon: 'view_headline', title: 'APP_LAYOUT.CARD_VIEW'},
|
||||
{ href: '/node-selector', icon: 'attachment', title: 'APP_LAYOUT.NODE-SELECTOR' },
|
||||
{ href: '/activiti', icon: 'device_hub', title: 'APP_LAYOUT.PROCESS_SERVICES' },
|
||||
{ href: '/login', icon: 'vpn_key', title: 'APP_LAYOUT.LOGIN' },
|
||||
{ href: '/trashcan', icon: 'delete', title: 'APP_LAYOUT.TRASHCAN' },
|
||||
@@ -54,6 +56,8 @@ export class AppLayoutComponent implements OnInit {
|
||||
|
||||
expandedSidenav = false;
|
||||
|
||||
hideSidenav = false;
|
||||
|
||||
enabelRedirect = true;
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
templateUrl: './breadcrumb-demo.component.html',
|
||||
styleUrls: [`./breadcrumb-demo.component.scss`],
|
||||
styleUrls: [`./breadcrumb-demo.component.scss`]
|
||||
})
|
||||
export class BreadcrumbDemoComponent {
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="main-content">
|
||||
<h1>CardView Component</h1>
|
||||
|
||||
<mat-card class="card-view">
|
||||
<adf-card-view
|
||||
[properties]="properties"
|
||||
[editable]="true">
|
||||
</adf-card-view>
|
||||
</mat-card>
|
||||
|
||||
<div class="console" #console>
|
||||
<h3>Changes log:</h3>
|
||||
<p *ngFor="let log of logs">{{ log }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,28 @@
|
||||
.main-content {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.card-view {
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.console {
|
||||
width: 60%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
padding-bottom: 30px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
font-family: monospace, monospace;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*!
|
||||
* @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, OnInit, ElementRef, ViewChild } from '@angular/core';
|
||||
import {
|
||||
CardViewTextItemModel,
|
||||
CardViewDateItemModel,
|
||||
CardViewDatetimeItemModel,
|
||||
CardViewBoolItemModel,
|
||||
CardViewIntItemModel,
|
||||
CardViewFloatItemModel,
|
||||
CardViewKeyValuePairsItemModel,
|
||||
CardViewSelectItemModel,
|
||||
CardViewUpdateService,
|
||||
UpdateNotification
|
||||
} from '@alfresco/adf-core';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
|
||||
@Component({
|
||||
templateUrl: './card-view.component.html',
|
||||
styleUrls: ['./card-view.component.scss']
|
||||
})
|
||||
export class CardViewComponent implements OnInit {
|
||||
|
||||
@ViewChild('console') console: ElementRef;
|
||||
|
||||
properties: any;
|
||||
logs: string[];
|
||||
|
||||
constructor(private cardViewUpdateService: CardViewUpdateService) {
|
||||
this.logs = [];
|
||||
this.properties = [
|
||||
new CardViewTextItemModel({
|
||||
label: 'CardView Text Item',
|
||||
value: 'Spock',
|
||||
key: 'name',
|
||||
default: 'default bar' ,
|
||||
multiline: false,
|
||||
icon: 'icon',
|
||||
editable: true
|
||||
}),
|
||||
new CardViewDateItemModel({
|
||||
label: 'CardView Date Item',
|
||||
value: new Date(),
|
||||
key: 'date-of-birth',
|
||||
default: new Date(),
|
||||
format: 'DD.MM.YYYY',
|
||||
editable: true
|
||||
}),
|
||||
new CardViewDatetimeItemModel({
|
||||
label: 'CardView Datetime Item',
|
||||
value: new Date(),
|
||||
key: 'datetime-of-birth',
|
||||
default: new Date(),
|
||||
format: 'DD.MM.YYYY',
|
||||
editable: true
|
||||
}),
|
||||
new CardViewBoolItemModel({
|
||||
label: 'CardView Boolean Item',
|
||||
value: true,
|
||||
key: 'vulcanian',
|
||||
default: false,
|
||||
editable: true
|
||||
}),
|
||||
new CardViewIntItemModel({
|
||||
label: 'CardView Int Item',
|
||||
value: 213,
|
||||
key: 'intelligence',
|
||||
default: 1,
|
||||
editable: true
|
||||
}),
|
||||
new CardViewFloatItemModel({
|
||||
label: 'CardView Float Item',
|
||||
value: 9.9,
|
||||
key: 'mental-stability',
|
||||
default: 0.0,
|
||||
editable: true
|
||||
}),
|
||||
new CardViewKeyValuePairsItemModel({
|
||||
label: 'CardView Key-Value Pairs Item',
|
||||
value: [],
|
||||
key: 'key-value-pairs',
|
||||
editable: true
|
||||
}),
|
||||
new CardViewSelectItemModel({
|
||||
label: 'CardView Select Item',
|
||||
value: 'one',
|
||||
options$: of([{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }]),
|
||||
key: 'select',
|
||||
editable: true
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.cardViewUpdateService.itemUpdated$.subscribe(this.onItemChange.bind(this));
|
||||
}
|
||||
|
||||
onItemChange(notification: UpdateNotification) {
|
||||
let value = notification.changed[notification.target.key];
|
||||
|
||||
if (notification.target.type === 'keyvaluepairs') {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
this.logs.push(`[${notification.target.label}] - ${value}`);
|
||||
this.console.nativeElement.scrollTop = this.console.nativeElement.scrollHeight;
|
||||
}
|
||||
}
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
<main>
|
||||
<h1>Object picker</h1>
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Plain picker</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
dropdownHideMyFiles: {{dropdownHideMyFiles}}
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[currentFolderId]="'-root-'">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Hide My files</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
My Files site will be hided from dropdown
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[currentFolderId]="'-root-'"
|
||||
[dropdownHideMyFiles]="true">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Custom Site List</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
Adding a custom site list
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div>
|
||||
<mat-list>
|
||||
<h3 mat-subheader>Add Site</h3>
|
||||
<form class="content-node-selector-demo-example-form">
|
||||
<mat-form-field>
|
||||
<label>Site Guid</label>
|
||||
<input matInput [(ngModel)]="customSideGuid" [ngModelOptions]="{standalone: true}">
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<label>Site Title</label>
|
||||
<input matInput [(ngModel)]="customSideTitle" [ngModelOptions]="{standalone: true}">
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<button mat-button color="primary" (click)="onClickAddSite()">Add</button>
|
||||
<button mat-button color="primary" (click)="onClickResetSite()">Reset</button>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
<h3 mat-subheader>Custom Sites Added</h3>
|
||||
<mat-list-item *ngFor="let customSite of customSites.list.entries">
|
||||
<mat-icon mat-list-icon>shopping_basket</mat-icon>
|
||||
<h4 mat-line>{{customSite.entry.title}}</h4>
|
||||
<p mat-line> {{customSite.entry.guid}} </p>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[currentFolderId]="'-root-'"
|
||||
[dropdownSiteList]="customSites">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Row Filtering</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
Will automatically filter the row on the list
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-slide-toggle color="primary" [(ngModel)]="showFiles" (click)="recreateRowFilterFunction()">
|
||||
Show Files
|
||||
</mat-slide-toggle>
|
||||
<mat-slide-toggle color="primary" [(ngModel)]="showFolders" (click)="recreateRowFilterFunction()">
|
||||
Slide Folders
|
||||
</mat-slide-toggle>
|
||||
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[rowFilter]="rowFilterFunction"
|
||||
[currentFolderId]="'-root-'">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Custom Image Resolving</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
A function to manage the way folder/file icons and thumbnails are resolved
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<mat-slide-toggle color="primary" (click)="recreateImageResolverFunction()">
|
||||
Add Custom Images Resolver
|
||||
</mat-slide-toggle>
|
||||
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[imageResolver]="customImageResolver"
|
||||
[currentFolderId]="'-root-'">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Set Page Size</h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
Number of items shown per page in the list. actual page {{actualPageSize}}
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[currentFolderId]="'-root-'"
|
||||
[pageSize]="actualPageSize"
|
||||
>
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>Is Valid Selection Function </h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
Function used to decide if the selected node has permission to be selected
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<label>Only folder starting with the letter 'a' or 'A' are valid selections</label>
|
||||
<label>Actual Selection is : {{validSelection}}</label>
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
(select)="onNodeSelect($event)"
|
||||
[isSelectionValid]="customIsValidFunction"
|
||||
[currentFolderId]="'-root-'">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<h2>BreadCrumb Transform Function </h2>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<label class="content-node-selector-demo-basic-label">
|
||||
Transformation to be performed on the chosen/folder node before building the breadcrumb UI
|
||||
</label>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<label>Folder starting with letter 'd' or 'D' won't be displayed in the breadcrumb dropdown</label>
|
||||
<div class="content-node-selector-demo-basic-table">
|
||||
<adf-content-node-selector-panel
|
||||
[breadcrumbTransform]="customBreadcrumbFunction"
|
||||
[currentFolderId]="'-root-'">
|
||||
</adf-content-node-selector-panel>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</main>
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
.content-node-selector-demo {
|
||||
|
||||
&-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-content: center;
|
||||
align-self: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-basic-table {
|
||||
height:400px;
|
||||
width:700px
|
||||
}
|
||||
|
||||
&-basic-label {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&-example-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*!
|
||||
* @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, ViewEncapsulation } from '@angular/core';
|
||||
import { SitePaging, SiteEntry, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { ShareDataRow } from '@alfresco/adf-content-services';
|
||||
import { DataRow, DataColumn, ThumbnailService } from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
templateUrl: './content-node-selector.component.html',
|
||||
styleUrls: [`./content-node-selector.component.scss`],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ContentNodeSelectorComponent {
|
||||
|
||||
constructor(private thumbnailService: ThumbnailService) {
|
||||
}
|
||||
|
||||
dropdownHideMyFiles = false;
|
||||
showFiles = false;
|
||||
showFolders = false;
|
||||
enableImageResolver = false;
|
||||
validSelection = false;
|
||||
|
||||
customSideGuid = '';
|
||||
customSideTitle = '';
|
||||
actualPageSize = 2;
|
||||
|
||||
rowFilterFunction: any = null;
|
||||
customImageResolver: any = null;
|
||||
|
||||
defaultSites: SiteEntry[] = [
|
||||
{ entry: { title: 'MINE', guid: '-my-' } },
|
||||
{ entry: { title: 'ROOTY', guid: '-root-' } }];
|
||||
|
||||
customSites: SitePaging = {
|
||||
list: {
|
||||
entries: [
|
||||
{ entry: { title: 'MINE', guid: '-my-' } },
|
||||
{ entry: { title: 'ROOTY', guid: '-root-' } }],
|
||||
pagination: {}
|
||||
}
|
||||
};
|
||||
|
||||
onClickAddSite() {
|
||||
const newSiteEntry: SiteEntry = { entry: { title: this.customSideTitle, guid: this.customSideGuid } };
|
||||
this.customSites.list.entries.push(newSiteEntry);
|
||||
this.customSideGuid = '';
|
||||
this.customSideTitle = '';
|
||||
}
|
||||
|
||||
onClickResetSite() {
|
||||
this.customSites.list.entries = this.defaultSites;
|
||||
this.customSideGuid = '';
|
||||
this.customSideTitle = '';
|
||||
}
|
||||
|
||||
recreateRowFilterFunction() {
|
||||
this.rowFilterFunction = this.rowFilteringExample.bind(this);
|
||||
}
|
||||
|
||||
recreateImageResolverFunction() {
|
||||
this.enableImageResolver = !this.enableImageResolver;
|
||||
if (this.enableImageResolver) {
|
||||
this.customImageResolver = this.customImageResolverExample.bind(this);
|
||||
} else {
|
||||
this.customImageResolver = null;
|
||||
}
|
||||
}
|
||||
|
||||
rowFilteringExample(row: ShareDataRow) {
|
||||
let showNode = true;
|
||||
const node: MinimalNodeEntryEntity = row.node.entry;
|
||||
if (this.showFiles) {
|
||||
showNode = node.isFile;
|
||||
}
|
||||
if (this.showFolders) {
|
||||
showNode = node.isFolder;
|
||||
}
|
||||
return showNode;
|
||||
}
|
||||
|
||||
customImageResolverExample(row: DataRow, col: DataColumn) {
|
||||
return this.thumbnailService.getMimeTypeIcon('video/quicktime');
|
||||
}
|
||||
|
||||
onNodeSelect(node: MinimalNodeEntryEntity) {
|
||||
this.validSelection = !!node;
|
||||
}
|
||||
|
||||
customIsValidFunction(entry: MinimalNodeEntryEntity): boolean {
|
||||
return entry.name.startsWith('a') || entry.name.startsWith('A');
|
||||
}
|
||||
|
||||
customBreadcrumbFunction(node: MinimalNodeEntryEntity) {
|
||||
if (node && node.path && node.path.elements) {
|
||||
node.path.elements = node.path.elements.filter((element) => !element.name.toLocaleLowerCase().startsWith('d') ? element : null );
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@
|
||||
</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button
|
||||
[disabled]="!documentList.selection.length"
|
||||
disabled
|
||||
[baseShareUrl]="baseShareUrl"
|
||||
[adf-share]="documentList.selection[0]"
|
||||
matTooltip="{{ 'DOCUMENT_LIST.TOOLBAR.SHARE' | translate }}">
|
||||
@@ -428,7 +428,9 @@
|
||||
<div *ngIf="processId">
|
||||
<adf-start-process
|
||||
[values]="formValues"
|
||||
[appId]="processId">
|
||||
[appId]="processId"
|
||||
(start)="closeStartProcess()"
|
||||
(cancel)="closeStartProcess()">
|
||||
</adf-start-process>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -474,6 +474,10 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
||||
|
||||
}
|
||||
|
||||
closeStartProcess() {
|
||||
this.processId = null;
|
||||
}
|
||||
|
||||
onChangePageSize(event: Pagination): void {
|
||||
this.preference.paginationSize = event.maxItems;
|
||||
this.changedPageSize.emit(event);
|
||||
|
||||
@@ -67,7 +67,7 @@ export class DemoPermissionComponent implements OnInit {
|
||||
this.displayPermissionComponent.reload();
|
||||
},
|
||||
(error) => {
|
||||
this.showErrorMessage(error);
|
||||
this.showErrorMessage(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="adf-report-issue">
|
||||
<h1>Report Issue</h1>
|
||||
<form class="adf-report-issue-form">
|
||||
<mat-form-field>
|
||||
<textarea matInput placeholder="Leave a comment" class="adf-report-issue-form-textarea"></textarea>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<button mat-raised-button>Submit</button>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
.adf-report-issue {
|
||||
margin: 50px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&-form {
|
||||
|
||||
width: 50%;
|
||||
min-width: 250px;
|
||||
margin-bottom: 50px;
|
||||
|
||||
& mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-textarea {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* @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';
|
||||
|
||||
@Component({
|
||||
templateUrl: './report-issue.component.html',
|
||||
styleUrls: [`./report-issue.component.scss`],
|
||||
})
|
||||
export class ReportIssueComponent {
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
@@ -74,6 +74,17 @@ Defining properties from Typescript:
|
||||
key: 'mental-stability',
|
||||
default: 0.0
|
||||
}),
|
||||
new CardViewKeyValuePairsItemModel({
|
||||
label: 'Variables',
|
||||
value: [],
|
||||
key: 'key-value-pairs'
|
||||
}),
|
||||
new CardViewSelectItemModel({
|
||||
label: 'Select box',
|
||||
value: 'one',
|
||||
options$: of([{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }]),
|
||||
key: 'select'
|
||||
}),
|
||||
...
|
||||
]
|
||||
```
|
||||
@@ -99,6 +110,8 @@ You define the property list, the [`CardViewComponent`](../core/card-view.compon
|
||||
- [**CardViewBoolItemModel**](#card-bool-item) - _for bool items (checkbox)_
|
||||
- [**CardViewIntItemModel**](#card-int-item) - _for integer items_
|
||||
- [**CardViewFloatItemModel**](#card-float-item) - _for float items_
|
||||
- [**CardViewKeyValuePairsItemModel**](#card-key-values-pairs-item) - _for key-value-pairs items_
|
||||
- [**CardViewSelectItemModel**](#card-select-item) - _for select items_
|
||||
|
||||
Each of these types implements the [Card View Item interface](card-view-item.interface.md):
|
||||
|
||||
@@ -287,6 +300,40 @@ const floatItemProperty = new CardViewFloatItemModel(options);
|
||||
| displayValue\* | float | | The value to display |
|
||||
| editable | boolean | false | Toggles whether the item is editable |
|
||||
|
||||
#### Card Key Value Pairs Item
|
||||
|
||||
[`CardViewKeyValuePairsItemModel`](../../lib/core/card-view/models/card-view-keyvaluepairs.model.ts) is a property type for key-value properties.
|
||||
|
||||
```ts
|
||||
const keyValuePairsItemProperty = new CardViewKeyValuePairsItemModel(options);
|
||||
```
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ---- | ---- | ------- | ----------- |
|
||||
| label\* | string | | Item label |
|
||||
| key\* | string | | Identifying key (important when editing the item) |
|
||||
| editable | boolean | false | Toggles whether the item is editable |
|
||||
| value\* | `[{ name: '', value: '' }, ...]` | | The original data value for the item |
|
||||
|
||||
|
||||
#### Card Select Item
|
||||
|
||||
[`CardViewSelectItemModel`](../../lib/core/card-view/models/card-view-selectitem.model.ts) is a property type for select properties.
|
||||
|
||||
```ts
|
||||
const selectItemProperty = new CardViewSelectItemModel(options);
|
||||
```
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ---- | ---- | ------- | ----------- |
|
||||
| label\* | string | | Item label |
|
||||
| key\* | string | | Identifying key (important when editing the item) |
|
||||
| editable | boolean | false | Toggles whether the item is editable |
|
||||
| value | string | | The original data value for the item |
|
||||
| options$\* | Observable<CardViewSelectItemOption[]> | | The original data value for the item |
|
||||
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
- [Card View Update service](card-view-update.service.md)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
Added: v2.4.0
|
||||
Status: Experimental
|
||||
---
|
||||
|
||||
## Header component
|
||||
|
||||
Reuseble header for Alfresco applications
|
||||
|
||||
## Basic usage
|
||||
|
||||
```html
|
||||
<adf-layout-header
|
||||
title="title"
|
||||
logo="logo.png"
|
||||
color="primary"
|
||||
(toggled)=toggleMenu($event)>
|
||||
|
||||
<app-search-bar fxFlex="0 1 auto"></app-search-bar>
|
||||
<app-theme-picker></app-theme-picker>
|
||||
<adf-layout>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
| Name | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| title | string | Title of the application
|
||||
| logo | string| Path to an image file for the application logo.
|
||||
| color | string | Primary color for the header
|
||||
| showSidenavToggle | boolean | Signals if the sidenav button will be displayed in the header or not. By default is true.
|
||||
|
||||
### Events
|
||||
| Name | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| clicked | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<boolean>` | Emitted when click on sidenav button
|
||||
|
||||
## Details
|
||||
This component displays a customizable header which can be reused. The left side of the header (title, button) and the primary color for the header can be configured via input parameters.
|
||||
|
||||
The right part of the header are existing components which are transcluded in the header component.
|
||||
@@ -61,6 +61,9 @@ The configuration of this service is saved in the `app.config.json` file
|
||||
The example below shows how to filter out the : '.git', '.DS_Store' and 'desktop.ini' files.
|
||||
Each element of the ignore list is a glob pattern string, so you could exclude all the `.txt`
|
||||
files, for example, by adding a `*.txt` pattern to the list.
|
||||
There is also the possibility to add some more option to how perform the check via the `match-options` parameter.
|
||||
For example in this case we have added the ignore case so `*.TXT` will match all the txt files ignoring the case for the extension.
|
||||
For more information about the options available please check [minimatch](https://www.npmjs.com/package/minimatch#options) documentation.
|
||||
|
||||
**app.config.json**
|
||||
|
||||
@@ -72,7 +75,10 @@ files, for example, by adding a `*.txt` pattern to the list.
|
||||
"name": "Alfresco"
|
||||
},
|
||||
"files": {
|
||||
"excluded": [".DS_Store", "desktop.ini", ".git", "*.txt"]
|
||||
"excluded": [".DS_Store", "desktop.ini", ".git", "*.txt"],
|
||||
"match-options": {
|
||||
"nocase": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
Added: v2.0.0
|
||||
Status: Active
|
||||
---
|
||||
|
||||
# Attach Form component
|
||||
|
||||
This component can be used when there is no form attached to a task and we want to add one.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```html
|
||||
<adf-attach-form
|
||||
[taskId]="taskid">
|
||||
</adf-attach-form>
|
||||
```
|
||||
|
||||
## Class members
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| -- | -- | -- | -- |
|
||||
| taskId | `string` | | Id of the task. |
|
||||
|
||||
### Events
|
||||
|
||||
| Name | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| cancelAttachForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the "Cancel" button is clicked. |
|
||||
| completeAttachForm | [`EventEmitter`](https://angular.io/api/core/EventEmitter)`<void>` | Emitted when the form associated with the task is completed. |
|
||||
@@ -25,6 +25,7 @@ This component can be used when there is no form attached to a task.
|
||||
| hideCancelButton | `boolean` | true | Toggles rendering of the `Cancel` button. |
|
||||
| isCompleted | `boolean` | false | If true then Task completed message is shown and `Complete` and `Cancel` buttons are hidden. |
|
||||
| taskName | `string` | | Name of the task. |
|
||||
| taskId | `number` | | Id of the task. |
|
||||
|
||||
### Events
|
||||
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@
|
||||
}
|
||||
|
||||
& .adf-name-location-cell-name {
|
||||
padding: 18px 0 2px 0;
|
||||
padding: 5px 0 2px 0;
|
||||
}
|
||||
|
||||
&.adf-content-selector-modified-cell {
|
||||
|
||||
@@ -45,7 +45,6 @@ export class NodeSharedDirective implements OnChanges {
|
||||
|
||||
shareNode(node: MinimalNodeEntity) {
|
||||
if (node.entry && node.entry.isFile) {
|
||||
this.setDisableAttribute(true);
|
||||
this.dialog.open(ShareDialogComponent, {
|
||||
width: '600px',
|
||||
disableClose: true,
|
||||
|
||||
@@ -416,7 +416,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
if (changes.node && changes.node.currentValue) {
|
||||
this.data.loadPage(changes.node.currentValue);
|
||||
this.onDataReady(changes.node.currentValue);
|
||||
} else if (changes.rowFilter) {
|
||||
} else if (changes.rowFilter && changes.rowFilter.currentValue !== changes.rowFilter.previousValue) {
|
||||
this.data.setFilter(changes.rowFilter.currentValue);
|
||||
if (this.currentFolderId) {
|
||||
this.loadFolderNodesByFolderNodeId(this.currentFolderId, this.pagination.getValue()).catch(err => this.error.emit(err));
|
||||
@@ -562,7 +562,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
|
||||
handlerSub = Observable.of(true);
|
||||
}
|
||||
|
||||
if (typeof action.execute === 'function') {
|
||||
if (typeof action.execute === 'function' && handlerSub) {
|
||||
handlerSub.subscribe(() => {
|
||||
action.execute(node);
|
||||
});
|
||||
|
||||
@@ -283,7 +283,8 @@
|
||||
"EVERYONE" : "EVERYONE"
|
||||
},
|
||||
"ERROR": {
|
||||
"DUPLICATE-PERMISSION": "One or more of the permissions you have set is already present : {{list}}"
|
||||
"DUPLICATE-PERMISSION": "One or more of the permissions you have set is already present : {{list}}",
|
||||
"NOT-ALLOWED": "You are not allowed to change permissions"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-content-services",
|
||||
"description": "Alfresco ADF content services",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.5.0-beta1",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "bundles/adf-content-services.js",
|
||||
"repository": {
|
||||
@@ -26,8 +26,8 @@
|
||||
"@angular/platform-browser-dynamic": "5.1.1",
|
||||
"@angular/router": "5.1.1",
|
||||
"@ngx-translate/core": "9.1.1",
|
||||
"alfresco-js-api": "2.4.0-beta14",
|
||||
"@alfresco/adf-core": "2.4.0-beta14",
|
||||
"alfresco-js-api": "2.5.0-beta1",
|
||||
"@alfresco/adf-core": "2.5.0-beta1",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<button mat-button
|
||||
id="adf-add-permission-action-button"
|
||||
class="adf-permission-action"
|
||||
[disabled]="selectedItems?.length === 0"
|
||||
[disabled]="!isAddEnabled()"
|
||||
(click)="applySelection()">
|
||||
{{'PERMISSION_MANAGER.ADD-PERMISSION.ADD-ACTION' | translate}}
|
||||
</button>
|
||||
|
||||
+31
-5
@@ -19,7 +19,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AddPermissionComponent } from './add-permission.component';
|
||||
import { AddPermissionPanelComponent } from './add-permission-panel.component';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { setupTestBed, NodesApiService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { fakeAuthorityResults } from '../../../mock/add-permission.component.mock';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
@@ -30,6 +30,7 @@ describe('AddPermissionComponent', () => {
|
||||
let fixture: ComponentFixture<AddPermissionComponent>;
|
||||
let element: HTMLElement;
|
||||
let nodePermissionService: NodePermissionService;
|
||||
let nodeApiService: NodesApiService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
@@ -38,6 +39,8 @@ describe('AddPermissionComponent', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
nodeApiService = TestBed.get(NodesApiService);
|
||||
spyOn(nodeApiService, 'getNode').and.returnValue(Observable.of({ id: 'fake-node', allowableOperations: ['updatePermissions']}));
|
||||
fixture = TestBed.createComponent(AddPermissionComponent);
|
||||
element = fixture.nativeElement;
|
||||
nodePermissionService = TestBed.get(NodePermissionService);
|
||||
@@ -67,12 +70,24 @@ describe('AddPermissionComponent', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit a success event when the node is updated', async(() => {
|
||||
it('should NOT enable the ADD button when a selection is sent but the user does not have the permissions', async(() => {
|
||||
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
|
||||
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
|
||||
fixture.componentInstance.currentNode = {id: 'fake-node-id'};
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
expect(addButton.disabled).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit a success event when the node is updated', (done) => {
|
||||
fixture.componentInstance.selectedItems = fakeAuthorityResults;
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({ id: 'fake-node-id'}));
|
||||
|
||||
fixture.componentInstance.success.subscribe((node) => {
|
||||
expect(node.id).toBe('fake-node-id');
|
||||
done();
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
@@ -81,14 +96,25 @@ describe('AddPermissionComponent', () => {
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
addButton.click();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should emit an error event when the node update fail', async(() => {
|
||||
it('should NOT emit a success event when the user does not have permission to update the node', () => {
|
||||
fixture.componentInstance.selectedItems = fakeAuthorityResults;
|
||||
fixture.componentInstance.currentNode = { id: 'fake-node-id' };
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({ id: 'fake-node-id' }));
|
||||
|
||||
let spySuccess = spyOn(fixture.componentInstance, 'success');
|
||||
fixture.componentInstance.applySelection();
|
||||
expect(spySuccess).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should emit an error event when the node update fail', (done) => {
|
||||
fixture.componentInstance.selectedItems = fakeAuthorityResults;
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.throw({ error: 'errored'}));
|
||||
|
||||
fixture.componentInstance.error.subscribe((error) => {
|
||||
expect(error.error).toBe('errored');
|
||||
done();
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
@@ -97,6 +123,6 @@ describe('AddPermissionComponent', () => {
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
addButton.click();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+20
-9
@@ -18,6 +18,7 @@
|
||||
import { Component, ViewEncapsulation, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { NodePermissionService } from '../../services/node-permission.service';
|
||||
import { NodesApiService, ContentService, PermissionsEnum } from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-add-permission',
|
||||
@@ -43,22 +44,32 @@ export class AddPermissionComponent {
|
||||
currentNode: MinimalNodeEntryEntity;
|
||||
currentNodeRoles: string[];
|
||||
|
||||
constructor(private nodePermissionService: NodePermissionService) {
|
||||
constructor(private nodePermissionService: NodePermissionService,
|
||||
private nodeApiService: NodesApiService,
|
||||
private contentService: ContentService) {
|
||||
this.nodeApiService.getNode(this.nodeId).subscribe((node) => this.currentNode = node);
|
||||
}
|
||||
|
||||
onSelect(selection: MinimalNodeEntity[]) {
|
||||
this.selectedItems = selection;
|
||||
}
|
||||
|
||||
isAddEnabled(): boolean {
|
||||
return this.contentService.hasPermission(this.currentNode, PermissionsEnum.UPDATEPERMISSIONS) &&
|
||||
this.selectedItems.length !== 0;
|
||||
}
|
||||
|
||||
applySelection() {
|
||||
this.nodePermissionService.updateNodePermissions(this.nodeId, this.selectedItems)
|
||||
.subscribe(
|
||||
(node) => {
|
||||
this.success.emit(node);
|
||||
},
|
||||
(error) => {
|
||||
this.error.emit(error);
|
||||
});
|
||||
if (this.contentService.hasPermission(this.currentNode, PermissionsEnum.UPDATEPERMISSIONS)) {
|
||||
this.nodePermissionService.updateNodePermissions(this.nodeId, this.selectedItems)
|
||||
.subscribe(
|
||||
(node) => {
|
||||
this.success.emit(node);
|
||||
},
|
||||
(error) => {
|
||||
this.error.emit(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-2
@@ -21,8 +21,9 @@ import { InheritPermissionDirective } from './inherited-button.directive';
|
||||
import { NodesApiService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
const fakeNodeWithInherit: any = { id: 'fake-id', permissions : {isInheritanceEnabled : true}};
|
||||
const fakeNodeNoInherit: any = { id: 'fake-id', permissions : {isInheritanceEnabled : false}};
|
||||
const fakeNodeWithInherit: any = { id: 'fake-id', permissions : {isInheritanceEnabled : true}, allowableOperations: ['updatePermissions']};
|
||||
const fakeNodeNoInherit: any = { id: 'fake-id', permissions : {isInheritanceEnabled : false}, allowableOperations: ['updatePermissions']};
|
||||
const fakeNodeWithInheritNoPermission: any = { id: 'fake-id', permissions : {isInheritanceEnabled : true}};
|
||||
|
||||
describe('InheritPermissionDirective', () => {
|
||||
|
||||
@@ -95,4 +96,19 @@ describe('InheritPermissionDirective', () => {
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not update the node when node has no permission', async(() => {
|
||||
spyOn(nodeService, 'getNode').and.returnValue(Observable.of(fakeNodeWithInheritNoPermission));
|
||||
let spyUpdateNode = spyOn(nodeService, 'updateNode');
|
||||
component.updatedNode = true;
|
||||
fixture.detectChanges();
|
||||
const buttonPermission: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#sample-button-permission');
|
||||
expect(buttonPermission).not.toBeNull();
|
||||
expect(element.querySelector('#update-notification')).not.toBeNull();
|
||||
buttonPermission.click();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(spyUpdateNode).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/* tslint:disable:no-input-rename */
|
||||
import { Directive, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { NodesApiService } from '@alfresco/adf-core';
|
||||
import { NodesApiService, ContentService, PermissionsEnum } from '@alfresco/adf-core';
|
||||
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
|
||||
@Directive({
|
||||
@@ -38,15 +38,20 @@ export class InheritPermissionDirective {
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
constructor(private nodeService: NodesApiService) {
|
||||
constructor(private nodeService: NodesApiService,
|
||||
private contentService: ContentService) {
|
||||
}
|
||||
|
||||
onInheritPermissionClicked() {
|
||||
this.nodeService.getNode(this.nodeId).subscribe((node: MinimalNodeEntryEntity) => {
|
||||
const nodeBody = { permissions: { isInheritanceEnabled: !node.permissions.isInheritanceEnabled } };
|
||||
this.nodeService.updateNode(this.nodeId, nodeBody, { include: ['permissions'] }).subscribe((nodeUpdated: MinimalNodeEntryEntity) => {
|
||||
this.updated.emit(nodeUpdated);
|
||||
}, (error) => this.error.emit(error));
|
||||
if (this.contentService.hasPermission(node, PermissionsEnum.UPDATEPERMISSIONS)) {
|
||||
const nodeBody = { permissions: { isInheritanceEnabled: !node.permissions.isInheritanceEnabled } };
|
||||
this.nodeService.updateNode(this.nodeId, nodeBody, { include: ['permissions'] }).subscribe((nodeUpdated: MinimalNodeEntryEntity) => {
|
||||
this.updated.emit(nodeUpdated);
|
||||
}, (error) => this.error.emit(error));
|
||||
} else {
|
||||
this.error.emit('PERMISSION_MANAGER.ERROR.NOT-ALLOWED');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+61
-20
@@ -16,13 +16,14 @@
|
||||
*/
|
||||
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppConfigService, setupTestBed } from '@alfresco/adf-core';
|
||||
import { AppConfigService, setupTestBed, ContentService } from '@alfresco/adf-core';
|
||||
import { NodePermissionDialogService } from './node-permission-dialog.service';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||
import { NodePermissionService } from './node-permission.service';
|
||||
import { Node } from 'alfresco-js-api';
|
||||
|
||||
describe('NodePermissionDialogService', () => {
|
||||
|
||||
@@ -31,6 +32,7 @@ describe('NodePermissionDialogService', () => {
|
||||
let spyOnDialogOpen: jasmine.Spy;
|
||||
let afterOpenObservable: Subject<any>;
|
||||
let nodePermissionService: NodePermissionService;
|
||||
let contentService: ContentService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ContentTestingModule],
|
||||
@@ -44,6 +46,7 @@ describe('NodePermissionDialogService', () => {
|
||||
materialDialog = TestBed.get(MatDialog);
|
||||
afterOpenObservable = new Subject<any>();
|
||||
nodePermissionService = TestBed.get(NodePermissionService);
|
||||
contentService = TestBed.get(ContentService);
|
||||
spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({
|
||||
afterOpen: () => afterOpenObservable,
|
||||
afterClosed: () => Observable.of({}),
|
||||
@@ -57,27 +60,65 @@ describe('NodePermissionDialogService', () => {
|
||||
expect(service).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should be able to open the dialog showing node permissions', () => {
|
||||
service.openAddPermissionDialog('fake-node-id', 'fake-title');
|
||||
expect(spyOnDialogOpen).toHaveBeenCalled();
|
||||
describe('when node has permission to update permissions', () => {
|
||||
|
||||
let fakePermissionNode = {};
|
||||
|
||||
beforeEach(() => {
|
||||
fakePermissionNode = <Node> { id: 'fake-permission-node', allowableOperations: ['updatePermissions']};
|
||||
});
|
||||
|
||||
it('should be able to open the dialog showing node permissions', () => {
|
||||
service.openAddPermissionDialog(fakePermissionNode, 'fake-title');
|
||||
expect(spyOnDialogOpen).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return the updated node', (done) => {
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({id : 'fake-node-updated'}));
|
||||
spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
|
||||
spyOn(contentService, 'getNode').and.returnValue(Observable.of(fakePermissionNode));
|
||||
service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe((node) => {
|
||||
expect(node.id).toBe('fake-node-updated');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if the update of the node fails', (done) => {
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.throw({error : 'error'}));
|
||||
spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
|
||||
spyOn(contentService, 'getNode').and.returnValue(Observable.of(fakePermissionNode));
|
||||
service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe(() => {
|
||||
Observable.throw('This call should fail');
|
||||
}, (error) => {
|
||||
expect(error.error).toBe('error');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if the update of the node fails', async(() => {
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.throw({error : 'error'}));
|
||||
spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
|
||||
service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe(() => {
|
||||
Observable.throw('This call should fail');
|
||||
}, (error) => {
|
||||
expect(error.error).toBe('error');
|
||||
});
|
||||
}));
|
||||
describe('when node does not have permission to update permissions', () => {
|
||||
|
||||
it('should return the updated node', async(() => {
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({id : 'fake-node'}));
|
||||
spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
|
||||
service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe((node) => {
|
||||
expect(node.id).toBe('fake-node');
|
||||
});
|
||||
}));
|
||||
let fakeForbiddenNode = {};
|
||||
|
||||
beforeEach(() => {
|
||||
fakeForbiddenNode = <Node> { id: 'fake-permission-node', allowableOperations: ['update']};
|
||||
});
|
||||
|
||||
it('should not be able to open the dialog showing node permissions', () => {
|
||||
service.openAddPermissionDialog(fakeForbiddenNode, 'fake-title');
|
||||
expect(spyOnDialogOpen).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return the updated node', (done) => {
|
||||
spyOn(contentService, 'getNode').and.returnValue(Observable.of(fakeForbiddenNode));
|
||||
service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe((node) => {
|
||||
Observable.throw('This call should fail');
|
||||
},
|
||||
(error) => {
|
||||
expect(error.message).toBe('PERMISSION_MANAGER.ERROR.NOT-ALLOWED');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
+26
-16
@@ -21,14 +21,16 @@ import { Subject } from 'rxjs/Subject';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { AddPermissionDialogComponent } from '../components/add-permission/add-permission-dialog.component';
|
||||
import { AddPermissionDialogData } from '../components/add-permission/add-permission-dialog-data.interface';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, Node } from 'alfresco-js-api';
|
||||
import { NodePermissionService } from './node-permission.service';
|
||||
import { ContentService, PermissionsEnum } from '@alfresco/adf-core';
|
||||
|
||||
@Injectable()
|
||||
export class NodePermissionDialogService {
|
||||
|
||||
constructor(private dialog: MatDialog,
|
||||
private nodePermissionService: NodePermissionService) {
|
||||
private nodePermissionService: NodePermissionService,
|
||||
private contentService: ContentService) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,21 +39,27 @@ export class NodePermissionDialogService {
|
||||
* @param title Dialog title
|
||||
* @returns Node with updated permissions
|
||||
*/
|
||||
openAddPermissionDialog(nodeId: string, title?: string): Observable<MinimalNodeEntity[]> {
|
||||
const confirm = new Subject<MinimalNodeEntity[]>();
|
||||
openAddPermissionDialog(node: Node, title?: string): Observable<MinimalNodeEntity[]> {
|
||||
if (this.contentService.hasPermission(node, PermissionsEnum.UPDATEPERMISSIONS)) {
|
||||
const confirm = new Subject<MinimalNodeEntity[]>();
|
||||
|
||||
confirm.subscribe({
|
||||
complete: this.close.bind(this)
|
||||
});
|
||||
confirm.subscribe({
|
||||
complete: this.close.bind(this)
|
||||
});
|
||||
|
||||
const data: AddPermissionDialogData = {
|
||||
nodeId: nodeId,
|
||||
title: title,
|
||||
confirm : confirm
|
||||
};
|
||||
const data: AddPermissionDialogData = {
|
||||
nodeId: node.id,
|
||||
title: title,
|
||||
confirm: confirm
|
||||
};
|
||||
|
||||
this.openDialog(data, 'adf-add-permission-dialog', '630px');
|
||||
return confirm;
|
||||
this.openDialog(data, 'adf-add-permission-dialog', '630px');
|
||||
return confirm;
|
||||
} else {
|
||||
let errors = new Error(JSON.stringify({ error: { statusCode: 403 } }));
|
||||
errors.message = 'PERMISSION_MANAGER.ERROR.NOT-ALLOWED';
|
||||
return Observable.throw(errors);
|
||||
}
|
||||
}
|
||||
|
||||
private openDialog(data: any, currentPanelClass: string, chosenWidth: string) {
|
||||
@@ -72,8 +80,10 @@ export class NodePermissionDialogService {
|
||||
* @returns Node with updated permissions
|
||||
*/
|
||||
updateNodePermissionByDialog(nodeId?: string, title?: string): Observable<MinimalNodeEntryEntity> {
|
||||
return this.openAddPermissionDialog(nodeId, title).switchMap((selection) => {
|
||||
return this.nodePermissionService.updateNodePermissions(nodeId, selection);
|
||||
return this.contentService.getNode(nodeId, { include: ['allowableOperations'] }).switchMap((node) => {
|
||||
return this.openAddPermissionDialog(node.entry, title).switchMap((selection) => {
|
||||
return this.nodePermissionService.updateNodePermissions(nodeId, selection);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
matInput [formControl]="from" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.FROM' | translate }}"
|
||||
autocomplete="off">
|
||||
<mat-error *ngIf="from.hasError('pattern')">
|
||||
<mat-error *ngIf="from.hasError('pattern') || from.hasError('min')">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.INVALID-FORMAT' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="from.hasError('required')">
|
||||
@@ -18,7 +18,7 @@
|
||||
matInput [formControl]="to" [errorStateMatcher]="matcher"
|
||||
placeholder="{{ 'SEARCH.FILTER.RANGE.TO' | translate }}"
|
||||
autocomplete="off">
|
||||
<mat-error *ngIf="to.hasError('pattern')">
|
||||
<mat-error *ngIf="to.hasError('pattern') || to.hasError('min')">
|
||||
{{ 'SEARCH.FILTER.VALIDATION.INVALID-FORMAT' | translate }}
|
||||
</mat-error>
|
||||
<mat-error *ngIf="to.hasError('required')">
|
||||
|
||||
+6
@@ -160,4 +160,10 @@ describe('SearchNumberRangeComponent', () => {
|
||||
component.from = new FormControl(123, component.validators);
|
||||
expect(component.from.hasError('required')).toBe(false);
|
||||
});
|
||||
|
||||
it('should throw error if "from" value is a negative value', () => {
|
||||
component.ngOnInit();
|
||||
component.from = new FormControl(-100, component.validators);
|
||||
expect(component.from.hasError('min')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
+3
-3
@@ -55,7 +55,8 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||
|
||||
this.validators = Validators.compose([
|
||||
Validators.required,
|
||||
Validators.pattern(/^-?(0|[1-9]\d*)?$/)
|
||||
Validators.pattern(/^-?(0|[1-9]\d*)?$/),
|
||||
Validators.min(0)
|
||||
]);
|
||||
|
||||
this.from = new FormControl('', this.validators);
|
||||
@@ -78,9 +79,8 @@ export class SearchNumberRangeComponent implements SearchWidget, OnInit {
|
||||
map.set('TO', model.to);
|
||||
|
||||
const value = this.formatString(this.format, map);
|
||||
const query = `${this.field}:${value}`;
|
||||
|
||||
this.context.queryFragments[this.id] = query;
|
||||
this.context.queryFragments[this.id] = `${this.field}:${value}`;
|
||||
this.context.update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,26 +55,18 @@ export class SearchQueryBuilderService {
|
||||
// TODO: to be supported in future iterations
|
||||
ranges: { [id: string]: SearchRange } = {};
|
||||
|
||||
constructor(appConfig: AppConfigService, private alfrescoApiService: AlfrescoApiService) {
|
||||
this.config = appConfig.get<SearchConfiguration>('search');
|
||||
constructor(private appConfig: AppConfigService, private alfrescoApiService: AlfrescoApiService) {
|
||||
this.resetToDefaults();
|
||||
}
|
||||
|
||||
resetToDefaults() {
|
||||
if (this.config) {
|
||||
this.categories =
|
||||
(this.config.categories || [])
|
||||
.filter(category => category.enabled)
|
||||
.map(category => { return { ...category }; });
|
||||
|
||||
this.filterQueries =
|
||||
(this.config.filterQueries || [])
|
||||
.map(query => { return {...query}; });
|
||||
|
||||
const template = this.appConfig.get<SearchConfiguration>('search');
|
||||
if (template) {
|
||||
this.config = JSON.parse(JSON.stringify(template));
|
||||
this.categories = (this.config.categories || []).filter(category => category.enabled);
|
||||
this.filterQueries = this.config.filterQueries || [];
|
||||
if (this.config.sorting) {
|
||||
this.sorting =
|
||||
(this.config.sorting.defaults || [])
|
||||
.map(sorting => { return { ...sorting }; });
|
||||
this.sorting = this.config.sorting.defaults || [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +367,36 @@ describe('UploadDragAreaComponent', () => {
|
||||
|
||||
addToQueueSpy.and.callFake((fileList) => {
|
||||
expect(fileList.name).toBe('file');
|
||||
expect(fileList.options.path).toBe('/pippo');
|
||||
expect(fileList.options.path).toBe('pippo/');
|
||||
});
|
||||
|
||||
let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
|
||||
detail: {
|
||||
data: getFakeShareDataRow(),
|
||||
files: [fakeItem]
|
||||
}
|
||||
});
|
||||
|
||||
component.onUploadFiles(fakeCustomEvent);
|
||||
}));
|
||||
|
||||
it('should upload a folder to a specific target folder when dropped onto one', async(() => {
|
||||
|
||||
let fakeItem = {
|
||||
fullPath: '/folder-fake/file-fake.png',
|
||||
isDirectory: false,
|
||||
isFile: true,
|
||||
name: 'file-fake.png',
|
||||
relativeFolder: '/super',
|
||||
file: (callbackFile) => {
|
||||
let fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' });
|
||||
callbackFile(fileFake);
|
||||
}
|
||||
};
|
||||
|
||||
addToQueueSpy.and.callFake((fileList) => {
|
||||
expect(fileList.name).toBe('file');
|
||||
expect(fileList.options.path).toBe('pippo/super');
|
||||
});
|
||||
|
||||
let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
|
||||
|
||||
@@ -121,7 +121,7 @@ export class UploadDragAreaComponent extends UploadBase implements NodePermissio
|
||||
let fileInfo: FileInfo[] = event.detail.files;
|
||||
if (this.isTargetNodeFolder(event)) {
|
||||
const destinationFolderName = event.detail.data.obj.entry.name;
|
||||
fileInfo.map((file) => file.relativeFolder = file.relativeFolder.concat(destinationFolderName));
|
||||
fileInfo.map((file) => file.relativeFolder = destinationFolderName ? destinationFolderName.concat(file.relativeFolder) : file.relativeFolder);
|
||||
}
|
||||
if (fileInfo && fileInfo.length > 0) {
|
||||
this.uploadFilesInfo(fileInfo);
|
||||
|
||||
@@ -318,6 +318,56 @@
|
||||
"description": "File exclusions",
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"match-options": {
|
||||
"description": "Minimatch plugin option that will be applied for the check. By default all the options are false",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"debug": {
|
||||
"description": "Dump a ton of stuff to stderr",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"nobrace": {
|
||||
"description": "Do not expand {a,b} and {1..3} brace sets.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"noglobstar": {
|
||||
"description": "Disable ** matching against multiple folder names.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"dot": {
|
||||
"description": "Allow patterns to match filenames starting with a period, even if the pattern does not explicitly have a period in that spot.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"noext": {
|
||||
"description": "Disable 'extglob' style patterns like +(a|b).",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"nocase": {
|
||||
"description": "Perform a case-insensitive match.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"nonull": {
|
||||
"description": "When a match is not found by minimatch.match, return a list containing the pattern itself if this option is set. When not set, an empty list is returned if there are no matches.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"matchBase": {
|
||||
"description": "If set, then patterns without slashes will be matched against the basename of the path if it contains slashes.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"nocomment": {
|
||||
"description": "Suppress the behavior of treating # at the start of a pattern as a comment.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"nonegate": {
|
||||
"description": "Suppress the behavior of treating a leading ! character as negation.",
|
||||
"type": ["boolean", "null"]
|
||||
},
|
||||
"flipNegate": {
|
||||
"description": "Returns from negate expressions the same as if they were not negated.",
|
||||
"type": ["boolean", "null"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
@@ -21,10 +21,12 @@ import { FormsModule } from '@angular/forms';
|
||||
import {
|
||||
MatButtonModule,
|
||||
MatDatepickerModule,
|
||||
MatTableModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
MatNativeDateModule
|
||||
MatNativeDateModule,
|
||||
MatSelectModule
|
||||
} from '@angular/material';
|
||||
import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
@@ -37,6 +39,8 @@ import { CardViewDateItemComponent } from './components/card-view-dateitem/card-
|
||||
import { CardViewItemDispatcherComponent } from './components/card-view-item-dispatcher/card-view-item-dispatcher.component';
|
||||
import { CardViewMapItemComponent } from './components/card-view-mapitem/card-view-mapitem.component';
|
||||
import { CardViewTextItemComponent } from './components/card-view-textitem/card-view-textitem.component';
|
||||
import { CardViewKeyValuePairsItemComponent } from './components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
|
||||
import { CardViewSelectItemComponent } from './components/card-view-selectitem/card-view-selectitem.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -48,7 +52,9 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
|
||||
MatNativeDateModule,
|
||||
MatCheckboxModule,
|
||||
MatInputModule,
|
||||
MatTableModule,
|
||||
MatIconModule,
|
||||
MatSelectModule,
|
||||
MatButtonModule,
|
||||
MatDatetimepickerModule,
|
||||
MatNativeDatetimeModule
|
||||
@@ -59,6 +65,8 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
|
||||
CardViewDateItemComponent,
|
||||
CardViewMapItemComponent,
|
||||
CardViewTextItemComponent,
|
||||
CardViewKeyValuePairsItemComponent,
|
||||
CardViewSelectItemComponent,
|
||||
CardViewItemDispatcherComponent,
|
||||
CardViewContentProxyDirective
|
||||
],
|
||||
@@ -66,14 +74,18 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
|
||||
CardViewBoolItemComponent,
|
||||
CardViewDateItemComponent,
|
||||
CardViewMapItemComponent,
|
||||
CardViewTextItemComponent
|
||||
CardViewTextItemComponent,
|
||||
CardViewSelectItemComponent,
|
||||
CardViewKeyValuePairsItemComponent
|
||||
],
|
||||
exports: [
|
||||
CardViewComponent,
|
||||
CardViewBoolItemComponent,
|
||||
CardViewDateItemComponent,
|
||||
CardViewMapItemComponent,
|
||||
CardViewTextItemComponent
|
||||
CardViewTextItemComponent,
|
||||
CardViewSelectItemComponent,
|
||||
CardViewKeyValuePairsItemComponent
|
||||
]
|
||||
})
|
||||
export class CardViewModule {}
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<div class="adf-property-label">{{ property.label | translate }}</div>
|
||||
<div class="adf-property-value">
|
||||
|
||||
<div *ngIf="isEditable()">
|
||||
{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.ADD' | translate }}
|
||||
<button (click)="add()" mat-icon-button class="card-view__key-value-pairs__add-btn">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isEditable()" class="card-view__key-value-pairs__read-only">
|
||||
<mat-table #table [dataSource]="matTableValues" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.name}}</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="value">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let item">{{item.value}}</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="['name', 'value']"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: ['name', 'value'];"></mat-row>
|
||||
</mat-table>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-view__key-value-pairs" *ngIf="isEditable() && values && values.length">
|
||||
<div class="card-view__key-value-pairs__row">
|
||||
<div class="card-view__key-value-pairs__col">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}</div>
|
||||
<div class="card-view__key-value-pairs__col">{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}</div>
|
||||
</div>
|
||||
|
||||
<div class="card-view__key-value-pairs__row" *ngFor="let item of values; let i = index">
|
||||
<div class="card-view__key-value-pairs__col">
|
||||
<mat-form-field class="example-full-width">
|
||||
<input matInput
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-name-input-' + i"
|
||||
[(ngModel)]="values[i].name">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="card-view__key-value-pairs__col">
|
||||
<mat-form-field class="example-full-width">
|
||||
<input matInput
|
||||
placeholder="{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}"
|
||||
(blur)="onBlur(item.value)"
|
||||
[attr.data-automation-id]="'card-'+ property.key +'-value-input-' + i"
|
||||
[(ngModel)]="values[i].value">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<button mat-icon-button (click)="remove(i)" class="card-view__key-value-pairs__remove-btn">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
.card-view {
|
||||
&__key-value-pairs {
|
||||
&__col {
|
||||
display: inline-block;
|
||||
width: 39%;
|
||||
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__read-only {
|
||||
.mat-table {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.mat-header-row, .mat-row {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/*!
|
||||
* @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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { CardViewKeyValuePairsItemModel } from '../../models/card-view-keyvaluepairs.model';
|
||||
import { CardViewKeyValuePairsItemComponent } from './card-view-keyvaluepairsitem.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||
|
||||
describe('CardViewKeyValuePairsItemComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<CardViewKeyValuePairsItemComponent>;
|
||||
let component: CardViewKeyValuePairsItemComponent;
|
||||
let cardViewUpdateService;
|
||||
const mockEmptyData = [{ name: '', value: '' }];
|
||||
const mockData = [{ name: 'test-name', value: 'test-value' }];
|
||||
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CardViewKeyValuePairsItemComponent);
|
||||
cardViewUpdateService = TestBed.get(CardViewUpdateService);
|
||||
component = fixture.componentInstance;
|
||||
component.property = new CardViewKeyValuePairsItemModel({
|
||||
label: 'Key Value Pairs',
|
||||
value: [],
|
||||
key: 'key-value-pairs',
|
||||
editable: true
|
||||
});
|
||||
component.editable = true;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
describe('Component', () => {
|
||||
|
||||
it('should render the label', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
const labelValue = fixture.debugElement.query(By.css('.adf-property-label'));
|
||||
expect(labelValue).not.toBeNull();
|
||||
expect(labelValue.nativeElement.innerText).toBe('Key Value Pairs');
|
||||
});
|
||||
|
||||
it('should render readOnly table is editable property is FALSE', () => {
|
||||
component.property = new CardViewKeyValuePairsItemModel({
|
||||
label: 'Key Value Pairs',
|
||||
value: mockData,
|
||||
key: 'key-value-pairs'
|
||||
});
|
||||
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const table = fixture.debugElement.query(By.css('.card-view__key-value-pairs__read-only'));
|
||||
const form = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
|
||||
|
||||
expect(table).not.toBeNull();
|
||||
expect(form).toBeNull();
|
||||
});
|
||||
|
||||
it('should add new item on ADD button click', () => {
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
|
||||
addButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(JSON.stringify(component.values)).toBe(JSON.stringify(mockEmptyData));
|
||||
|
||||
const content = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
|
||||
expect(content).not.toBeNull();
|
||||
|
||||
let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`));
|
||||
let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
|
||||
expect(nameInput).not.toBeNull();
|
||||
expect(valueInput).not.toBeNull();
|
||||
|
||||
});
|
||||
|
||||
it('should remove an item from list on REMOVE button click', () => {
|
||||
spyOn(cardViewUpdateService, 'update');
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
|
||||
addButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
const removeButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__remove-btn'));
|
||||
removeButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.values.length).toBe(0);
|
||||
const content = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
|
||||
expect(content).toBeNull();
|
||||
|
||||
expect(cardViewUpdateService.update).toHaveBeenCalled();
|
||||
expect(component.property.value.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should update property on input blur', async(() => {
|
||||
spyOn(cardViewUpdateService, 'update');
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
|
||||
addButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`));
|
||||
let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
|
||||
|
||||
nameInput.nativeElement.value = mockData[0].name;
|
||||
nameInput.nativeElement.dispatchEvent(new Event('input'));
|
||||
valueInput.nativeElement.value = mockData[0].value;
|
||||
valueInput.nativeElement.dispatchEvent(new Event('input'));
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
valueInput.triggerEventHandler('blur', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(cardViewUpdateService.update).toHaveBeenCalled();
|
||||
expect(JSON.stringify(component.property.value)).toBe(JSON.stringify(mockData));
|
||||
});
|
||||
}));
|
||||
|
||||
it('should not update property if at least one input is empty on blur', async(() => {
|
||||
spyOn(cardViewUpdateService, 'update');
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
|
||||
addButton.triggerEventHandler('click', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
|
||||
|
||||
valueInput.nativeElement.value = mockData[0].value;
|
||||
valueInput.nativeElement.dispatchEvent(new Event('input'));
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
valueInput.triggerEventHandler('blur', null);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(cardViewUpdateService.update).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*!
|
||||
* @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, Input, OnChanges } from '@angular/core';
|
||||
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||
import { CardViewKeyValuePairsItemModel } from '../../models/card-view.models';
|
||||
import { CardViewKeyValuePairsItemType } from '../../interfaces/card-view.interfaces';
|
||||
import { MatTableDataSource } from '@angular/material';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view-boolitem',
|
||||
templateUrl: './card-view-keyvaluepairsitem.component.html',
|
||||
styleUrls: ['./card-view-keyvaluepairsitem.component.scss']
|
||||
})
|
||||
|
||||
export class CardViewKeyValuePairsItemComponent implements OnChanges {
|
||||
|
||||
@Input()
|
||||
property: CardViewKeyValuePairsItemModel;
|
||||
|
||||
@Input()
|
||||
editable: boolean = false;
|
||||
|
||||
values: CardViewKeyValuePairsItemType[];
|
||||
matTableValues: MatTableDataSource<CardViewKeyValuePairsItemType>;
|
||||
|
||||
constructor(private cardViewUpdateService: CardViewUpdateService) {}
|
||||
|
||||
ngOnChanges() {
|
||||
this.values = this.property.value || [];
|
||||
this.matTableValues = new MatTableDataSource(this.values);
|
||||
}
|
||||
|
||||
isEditable(): boolean {
|
||||
return this.editable && this.property.editable;
|
||||
}
|
||||
|
||||
add(): void {
|
||||
this.values.push({ name: '', value: '' });
|
||||
}
|
||||
|
||||
remove(index: number): void {
|
||||
this.values.splice(index, 1);
|
||||
this.save(true);
|
||||
}
|
||||
|
||||
onBlur(value): void {
|
||||
if (value.length) {
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
save(remove?: boolean): void {
|
||||
const validValues = this.values.filter(i => i.name.length && i.value.length);
|
||||
|
||||
if (remove || validValues.length) {
|
||||
this.cardViewUpdateService.update(this.property, validValues);
|
||||
this.property.value = validValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<div class="adf-property-label">{{ property.label | translate }}</div>
|
||||
<div class="adf-property-value">
|
||||
<div *ngIf="!isEditable()" data-automation-class="read-only-value">{{ property.displayValue | async }}</div>
|
||||
<div *ngIf="isEditable()">
|
||||
<mat-form-field>
|
||||
<mat-select [(value)]="value" (change)="onChange($event)" data-automation-class="select-box">
|
||||
<mat-option *ngFor="let option of getOptions() | async" [value]="option.key">
|
||||
{{ option.label | translate }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
.mat-form-field-type-mat-select {
|
||||
width: 100%;
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*!
|
||||
* @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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { CardViewSelectItemModel } from '../../models/card-view-selectitem.model';
|
||||
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||
import { CardViewSelectItemComponent } from './card-view-selectitem.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
|
||||
describe('CardViewSelectItemComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<CardViewSelectItemComponent>;
|
||||
let component: CardViewSelectItemComponent;
|
||||
let cardViewUpdateService;
|
||||
const mockData = [{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }, { key: 'three', label: 'Three' }];
|
||||
const mockDefaultProps = {
|
||||
label: 'Select box label',
|
||||
value: 'two',
|
||||
options$: of(mockData),
|
||||
key: 'key',
|
||||
editable: true
|
||||
};
|
||||
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CardViewSelectItemComponent);
|
||||
cardViewUpdateService = TestBed.get(CardViewUpdateService);
|
||||
component = fixture.componentInstance;
|
||||
component.property = new CardViewSelectItemModel(mockDefaultProps);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should render the label', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
const labelValue = fixture.debugElement.query(By.css('.adf-property-label'));
|
||||
expect(labelValue).not.toBeNull();
|
||||
expect(labelValue.nativeElement.innerText).toBe('Select box label');
|
||||
});
|
||||
|
||||
it('should render readOnly value is editable property is FALSE', () => {
|
||||
component.property = new CardViewSelectItemModel({
|
||||
...mockDefaultProps,
|
||||
editable: false
|
||||
});
|
||||
|
||||
component.ngOnChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
const readOnly = fixture.debugElement.query(By.css('[data-automation-class="read-only-value"]'));
|
||||
const selectBox = fixture.debugElement.query(By.css('[data-automation-class="select-box"]'));
|
||||
|
||||
expect(readOnly).not.toBeNull();
|
||||
expect(selectBox).toBeNull();
|
||||
});
|
||||
|
||||
it('should render select box if editable property is TRUE', () => {
|
||||
component.ngOnChanges();
|
||||
component.editable = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const selectBox = fixture.debugElement.query(By.css('[data-automation-class="select-box"]'));
|
||||
expect(selectBox).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should not have label twice', () => {
|
||||
component.ngOnChanges();
|
||||
component.editable = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.debugElement.query(By.css('[data-automation-class="select-box"] .mat-form-field-label'));
|
||||
expect(label).toBeNull();
|
||||
});
|
||||
|
||||
it('should update property on input blur', async(() => {
|
||||
spyOn(cardViewUpdateService, 'update');
|
||||
|
||||
component.ngOnChanges();
|
||||
component.editable = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
const selectBox = fixture.debugElement.query(By.css('[data-automation-class="select-box"]'));
|
||||
selectBox.nativeElement.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
const option = fixture.debugElement.query(By.css(`mat-option[ng-reflect-value="${mockData[2].key}"]`));
|
||||
option.nativeElement.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(cardViewUpdateService.update).toHaveBeenCalled();
|
||||
expect(component.property.value).toBe(mockData[2].key);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
/*!
|
||||
* @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, Input, OnChanges } from '@angular/core';
|
||||
import { CardViewSelectItemModel } from '../../models/card-view-selectitem.model';
|
||||
import { CardViewUpdateService } from '../../services/card-view-update.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { CardViewSelectItemOption } from '../../interfaces/card-view.interfaces';
|
||||
import { MatSelectChange } from '@angular/material';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-card-view-selectitem',
|
||||
templateUrl: './card-view-selectitem.component.html',
|
||||
styleUrls: ['./card-view-selectitem.component.scss']
|
||||
})
|
||||
export class CardViewSelectItemComponent implements OnChanges {
|
||||
@Input() property: CardViewSelectItemModel<string>;
|
||||
|
||||
@Input() editable: boolean = false;
|
||||
|
||||
@Input() options$: Observable<CardViewSelectItemOption<string>[]>;
|
||||
|
||||
value: string;
|
||||
|
||||
constructor(private cardViewUpdateService: CardViewUpdateService) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.value = this.property.value;
|
||||
}
|
||||
|
||||
isEditable(): boolean {
|
||||
return this.editable && this.property.editable;
|
||||
}
|
||||
|
||||
getOptions(): Observable<CardViewSelectItemOption<string>[]> {
|
||||
return this.options$ || this.property.options$;
|
||||
}
|
||||
|
||||
onChange(event: MatSelectChange): void {
|
||||
this.cardViewUpdateService.update(this.property, event.value);
|
||||
this.property.value = event.value;
|
||||
}
|
||||
}
|
||||
@@ -21,3 +21,5 @@ export * from './card-view-dateitem/card-view-dateitem.component';
|
||||
export * from './card-view-item-dispatcher/card-view-item-dispatcher.component';
|
||||
export * from './card-view-mapitem/card-view-mapitem.component';
|
||||
export * from './card-view-textitem/card-view-textitem.component';
|
||||
export * from './card-view-selectitem/card-view-selectitem.component';
|
||||
export * from './card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*!
|
||||
* @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 { CardViewItemProperties } from './card-view-item-properties.interface';
|
||||
|
||||
export interface CardViewKeyValuePairsItemType {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface CardViewKeyValuePairsItemProperties extends CardViewItemProperties {
|
||||
value: CardViewKeyValuePairsItemType[];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*!
|
||||
* @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 { CardViewItemProperties } from './card-view-item-properties.interface';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export interface CardViewSelectItemOption<T> {
|
||||
label: string;
|
||||
key: T;
|
||||
}
|
||||
|
||||
export interface CardViewSelectItemProperties<T> extends CardViewItemProperties {
|
||||
value: string;
|
||||
options$: Observable<CardViewSelectItemOption<T>[]>;
|
||||
}
|
||||
@@ -22,3 +22,5 @@ export * from './card-view-textitem-properties.interface';
|
||||
export * from './card-view-dateitem-properties.interface';
|
||||
export * from './card-view-boolitem-properties.interface';
|
||||
export * from './card-view-textitem-pipe-property.interface';
|
||||
export * from './card-view-keyvaluepairsitem-properties.interface';
|
||||
export * from './card-view-selectitem-properties.interface';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*!
|
||||
* @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 { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewKeyValuePairsItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
export class CardViewKeyValuePairsItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
type: string = 'keyvaluepairs';
|
||||
|
||||
constructor(obj: CardViewKeyValuePairsItemProperties) {
|
||||
super(obj);
|
||||
}
|
||||
|
||||
get displayValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* @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 { async } from '@angular/core/testing';
|
||||
import { CardViewSelectItemModel } from './card-view-selectitem.model';
|
||||
import { CardViewSelectItemProperties } from '../interfaces/card-view.interfaces';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
|
||||
describe('CardViewSelectItemModel', () => {
|
||||
let properties: CardViewSelectItemProperties<string>;
|
||||
const mockData = [{ key: 'one', label: 'One' }, { key: 'two', label: 'Two' }, { key: 'three', label: 'Three' }];
|
||||
|
||||
beforeEach(() => {
|
||||
properties = {
|
||||
label: 'Select box label',
|
||||
value: 'two',
|
||||
options$: of(mockData),
|
||||
key: 'key',
|
||||
editable: true
|
||||
};
|
||||
});
|
||||
|
||||
describe('displayValue', () => {
|
||||
it('should return the value if it is present', async(() => {
|
||||
const itemModel = new CardViewSelectItemModel(properties);
|
||||
|
||||
itemModel.displayValue.subscribe(value => {
|
||||
expect(value).toBe(mockData[1].label);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @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 { CardViewItem } from '../interfaces/card-view-item.interface';
|
||||
import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
|
||||
import { CardViewBaseItemModel } from './card-view-baseitem.model';
|
||||
import { CardViewSelectItemProperties, CardViewSelectItemOption } from '../interfaces/card-view.interfaces';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { of } from 'rxjs/observable/of';
|
||||
|
||||
export class CardViewSelectItemModel<T> extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
type: string = 'select';
|
||||
options$: Observable<CardViewSelectItemOption<T>[]>;
|
||||
|
||||
constructor(obj: CardViewSelectItemProperties<T>) {
|
||||
super(obj);
|
||||
|
||||
this.options$ = obj.options$;
|
||||
}
|
||||
|
||||
get displayValue() {
|
||||
return this.options$.pipe(
|
||||
switchMap(options => {
|
||||
const option = options.find(o => o.key === this.value);
|
||||
return of(option ? option.label : '');
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -23,3 +23,5 @@ export * from './card-view-floatitem.model';
|
||||
export * from './card-view-intitem.model';
|
||||
export * from './card-view-mapitem.model';
|
||||
export * from './card-view-textitem.model';
|
||||
export * from './card-view-keyvaluepairs.model';
|
||||
export * from './card-view-selectitem.model';
|
||||
|
||||
@@ -20,7 +20,9 @@ export {
|
||||
CardViewBoolItemComponent,
|
||||
CardViewDateItemComponent,
|
||||
CardViewMapItemComponent,
|
||||
CardViewTextItemComponent
|
||||
CardViewTextItemComponent,
|
||||
CardViewSelectItemComponent,
|
||||
CardViewKeyValuePairsItemComponent
|
||||
} from './components/card-view.components';
|
||||
|
||||
export * from './interfaces/card-view.interfaces';
|
||||
|
||||
@@ -19,7 +19,9 @@ import { Injectable, Type } from '@angular/core';
|
||||
import { CardViewDateItemComponent } from '../components/card-view-dateitem/card-view-dateitem.component';
|
||||
import { CardViewMapItemComponent } from '../components/card-view-mapitem/card-view-mapitem.component';
|
||||
import { CardViewTextItemComponent } from '../components/card-view-textitem/card-view-textitem.component';
|
||||
import { CardViewSelectItemComponent } from '../components/card-view-selectitem/card-view-selectitem.component';
|
||||
import { CardViewBoolItemComponent } from '../components/card-view-boolitem/card-view-boolitem.component';
|
||||
import { CardViewKeyValuePairsItemComponent } from '../components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../services/dynamic-component-mapper.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -29,11 +31,13 @@ export class CardItemTypeService extends DynamicComponentMapper {
|
||||
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {
|
||||
'text': DynamicComponentResolver.fromType(CardViewTextItemComponent),
|
||||
'select': DynamicComponentResolver.fromType(CardViewSelectItemComponent),
|
||||
'int': DynamicComponentResolver.fromType(CardViewTextItemComponent),
|
||||
'float': DynamicComponentResolver.fromType(CardViewTextItemComponent),
|
||||
'date': DynamicComponentResolver.fromType(CardViewDateItemComponent),
|
||||
'datetime': DynamicComponentResolver.fromType(CardViewDateItemComponent),
|
||||
'bool': DynamicComponentResolver.fromType(CardViewBoolItemComponent),
|
||||
'map': DynamicComponentResolver.fromType(CardViewMapItemComponent)
|
||||
'map': DynamicComponentResolver.fromType(CardViewMapItemComponent),
|
||||
'keyvaluepairs': DynamicComponentResolver.fromType(CardViewKeyValuePairsItemComponent)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ import { ToolbarModule } from './toolbar/toolbar.module';
|
||||
import { UserInfoModule } from './userinfo/userinfo.module';
|
||||
import { ViewerModule } from './viewer/viewer.module';
|
||||
import { FormModule } from './form/form.module';
|
||||
import { SidenavLayoutModule } from './sidenav-layout/sidenav-layout.module';
|
||||
import { SidenavLayoutModule } from './layout/layout.module';
|
||||
import { CommentsModule } from './comments/comments.module';
|
||||
import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module';
|
||||
import { TemplateModule } from './templates/template.module';
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="adf-datatable-body">
|
||||
@@ -191,6 +190,9 @@
|
||||
<ng-content select="adf-empty-list"></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let row of fakeRows"
|
||||
class="adf-datatable-row adf-datatable-row-empty-card">
|
||||
</div>
|
||||
</ng-container>
|
||||
<div *ngIf="!loading && noPermission"
|
||||
[class.adf-datatable-row]="display === 'list'"
|
||||
|
||||
@@ -29,13 +29,10 @@
|
||||
display: flex;
|
||||
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
}
|
||||
justify-content: space-evenly;
|
||||
align-content: flex-start;
|
||||
align-items: flex-start;
|
||||
|
||||
.adf-datatable-row {
|
||||
transition: all 0.3s ease;
|
||||
@@ -58,6 +55,14 @@
|
||||
@include mat-overridable-elevation(2);
|
||||
}
|
||||
|
||||
.adf-datatable-row-empty-card {
|
||||
height: 0 !important;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.is-selected {
|
||||
background: mat-color($primary, 100);
|
||||
padding-bottom: 31px;
|
||||
@@ -390,8 +395,6 @@
|
||||
.ellipsis-cell {
|
||||
.cell-container {
|
||||
height: 100%;
|
||||
display: inline-grid;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cell-container > * {
|
||||
@@ -407,7 +410,7 @@
|
||||
/* visible content */
|
||||
.cell-value {
|
||||
display: block;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
max-width: calc(100% - 2em);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -161,6 +161,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
isSelectAllChecked: boolean = false;
|
||||
selection = new Array<DataRow>();
|
||||
|
||||
/** This array of fake rows fix the flex layout for the gallery view */
|
||||
fakeRows = [];
|
||||
|
||||
private clickObserver: Observer<DataRowEvent>;
|
||||
private click$: Observable<DataRowEvent>;
|
||||
|
||||
@@ -188,6 +191,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
})
|
||||
);
|
||||
}
|
||||
this.datatableLayoutFix();
|
||||
this.setTableSchema();
|
||||
}
|
||||
|
||||
@@ -220,6 +224,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
if (this.isPropertyChanged(changes['sorting'])) {
|
||||
this.setTableSorting(changes['sorting'].currentValue);
|
||||
}
|
||||
|
||||
if (this.isPropertyChanged(changes['display'])) {
|
||||
this.datatableLayoutFix();
|
||||
}
|
||||
}
|
||||
|
||||
ngDoCheck() {
|
||||
@@ -654,4 +662,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck,
|
||||
this.dataRowsChanged = null;
|
||||
}
|
||||
}
|
||||
|
||||
datatableLayoutFix() {
|
||||
const maxGalleryRows = 25;
|
||||
|
||||
if (this.display === 'gallery') {
|
||||
for (let i = 0; i < maxGalleryRows; i++) {
|
||||
this.fakeRows.push('');
|
||||
}
|
||||
} else {
|
||||
this.fakeRows = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="adf-amount-widget__container adf-amount-widget {{field.className}}" [class.adf-invalid]="!field.isValid" [class.adf-readonly]="field.readOnly">
|
||||
<mat-form-field floatPlaceholder="never" class="adf-amount-widget__input">
|
||||
<mat-form-field class="adf-amount-widget__input">
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label>
|
||||
<span matPrefix class="adf-amount-widget__prefix-spacing"> {{currency }}</span>
|
||||
<input matInput
|
||||
@@ -7,13 +7,12 @@
|
||||
type="text"
|
||||
[id]="field.id"
|
||||
[required]="isRequired()"
|
||||
[placeholder]="field.placeholder"
|
||||
[value]="field.value"
|
||||
[(ngModel)]="field.value"
|
||||
(ngModelChange)="onFieldChanged(field)"
|
||||
[disabled]="field.readOnly"
|
||||
placeholder="{{field.placeholder}}">
|
||||
[disabled]="field.readOnly">
|
||||
</mat-form-field>
|
||||
<error-widget [error]="field.validationSummary" ></error-widget>
|
||||
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,20 +5,27 @@
|
||||
width: 100%;
|
||||
vertical-align: baseline !important;
|
||||
|
||||
.mat-input-element {
|
||||
margin-left: 11px;
|
||||
}
|
||||
|
||||
.mat-input-prefix {
|
||||
position: absolute;
|
||||
margin-top: 58px;
|
||||
}
|
||||
|
||||
.mat-input-placeholder {
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mat-form-field-flex{
|
||||
position: relative;
|
||||
padding-top: 18.5px;
|
||||
}
|
||||
|
||||
.mat-form-field-infix{
|
||||
position: static;
|
||||
padding-top: 19px;
|
||||
}
|
||||
|
||||
.adf-label{
|
||||
position: absolute;
|
||||
top: 18.5px;
|
||||
left:0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&-amount-widget__container {
|
||||
|
||||
@@ -8,32 +8,29 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.adf {
|
||||
&-field-list {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.container-widget__header-text {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.87);
|
||||
padding-bottom: 10px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
/* Chrome/Safari/Opera */
|
||||
-moz-user-select: none;
|
||||
/* Firefox */
|
||||
-ms-user-select: none;
|
||||
/* IE/Edge */
|
||||
-webkit-touch-callout: none;
|
||||
/* iOS Safari */
|
||||
&.collapsible {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.container-widget__header-text {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.87);
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
/* Chrome/Safari/Opera */
|
||||
-moz-user-select: none;
|
||||
/* Firefox */
|
||||
-ms-user-select: none;
|
||||
/* IE/Edge */
|
||||
-webkit-touch-callout: none;
|
||||
/* iOS Safari */
|
||||
&.collapsible {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.adf-field-list {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
container-widget {
|
||||
@@ -50,7 +47,7 @@
|
||||
padding-left: 1%;
|
||||
padding-right: 1%;
|
||||
}
|
||||
|
||||
|
||||
@media screen and ($mat-small) {
|
||||
.grid-list-item {
|
||||
flex: 1 0 100%;
|
||||
|
||||
@@ -17,7 +17,13 @@
|
||||
[class.adf-dynamic-table-widget__row-selected]="row.selected" (keyup)="onKeyPressed($event, row)">
|
||||
<td *ngFor="let column of content.visibleColumns"
|
||||
(click)="onRowClicked(row)">
|
||||
{{ getCellValue(row, column) }}
|
||||
<span *ngIf="column.type !== 'Boolean' else checkbox">
|
||||
{{ getCellValue(row, column) }}
|
||||
</span>
|
||||
<ng-template #checkbox>
|
||||
<mat-checkbox disabled [checked]="getCellValue(row, column)">
|
||||
</mat-checkbox>
|
||||
</ng-template>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<div>
|
||||
<mat-form-field class="adf-date-editor">
|
||||
<label [attr.for]="column.id">{{column.name}} {{DATE_FORMAT}}</label>
|
||||
<input matInput
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[(ngModel)]="value"
|
||||
[id]="column.id"
|
||||
[required]="column.required"
|
||||
[disabled]="!column.editable"
|
||||
(focusout)="onDateChanged($event.srcElement.value)"
|
||||
(dateChange)="onDateChanged($event)">
|
||||
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker"
|
||||
*ngIf="column.editable"
|
||||
class="adf-date-editor-button"></mat-datetimepicker-toggle>
|
||||
</mat-form-field>
|
||||
<mat-datetimepicker #datetimePicker
|
||||
type="datetime"
|
||||
openOnFocus="true"
|
||||
timeInterval="5"></mat-datetimepicker>
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
.adf {
|
||||
&-date-editor {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-date-editor-button {
|
||||
position: relative;
|
||||
top: 25px;
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*!
|
||||
* @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 { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import moment from 'moment-es6';
|
||||
import { FormFieldModel, FormModel } from '../../../index';
|
||||
import { DynamicTableColumn } from './../../dynamic-table-column.model';
|
||||
import { DynamicTableRow } from './../../dynamic-table-row.model';
|
||||
import { DynamicTableModel } from './../../dynamic-table.widget.model';
|
||||
import { DateTimeEditorComponent } from './datetime.editor';
|
||||
import { setupTestBed } from '../../../../../../testing/setupTestBed';
|
||||
import { CoreModule } from '../../../../../../core.module';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
describe('DateTimeEditorComponent', () => {
|
||||
let component: DateTimeEditorComponent;
|
||||
let fixture: ComponentFixture<DateTimeEditorComponent>;
|
||||
let row: DynamicTableRow;
|
||||
let column: DynamicTableColumn;
|
||||
let table: DynamicTableModel;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
NoopAnimationsModule,
|
||||
CoreModule.forRoot()
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DateTimeEditorComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
row = <DynamicTableRow> { value: { date: '1879-03-14T00:00:00.000Z' } };
|
||||
column = <DynamicTableColumn> { id: 'datetime', type: 'Datetime' };
|
||||
const field = new FormFieldModel(new FormModel());
|
||||
table = new DynamicTableModel(field, null);
|
||||
table.rows.push(row);
|
||||
table.columns.push(column);
|
||||
component.table = table;
|
||||
component.row = row;
|
||||
component.column = column;
|
||||
});
|
||||
|
||||
it('should create instance of DateTimeEditorComponent', () => {
|
||||
expect(fixture.componentInstance instanceof DateTimeEditorComponent).toBe(true, 'should create DateTimeEditorComponent');
|
||||
});
|
||||
|
||||
it('should update fow value on change', () => {
|
||||
component.ngOnInit();
|
||||
let newDate = moment('22-6-2018 04:20 AM', 'D-M-YYYY hh:mm A');
|
||||
component.onDateChanged(newDate);
|
||||
expect(moment(row.value[column.id]).isSame(newDate)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should update row value upon user input', () => {
|
||||
const input = '22-6-2018 04:20 AM';
|
||||
|
||||
component.ngOnInit();
|
||||
component.onDateChanged(input);
|
||||
|
||||
let actual = row.value[column.id];
|
||||
expect(actual).toBe('22-6-2018 04:20 AM');
|
||||
});
|
||||
|
||||
it('should flush value on user input', () => {
|
||||
spyOn(table, 'flushValue').and.callThrough();
|
||||
const input = '22-6-2018 04:20 AM';
|
||||
|
||||
component.ngOnInit();
|
||||
component.onDateChanged(input);
|
||||
|
||||
expect(table.flushValue).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
/*!
|
||||
* @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.
|
||||
*/
|
||||
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { UserPreferencesService } from '../../../../../../services/user-preferences.service';
|
||||
import { MomentDateAdapter } from '../../../../../../utils/momentDateAdapter';
|
||||
import { MOMENT_DATE_FORMATS } from '../../../../../../utils/moment-date-formats.model';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
import { DynamicTableColumn } from './../../dynamic-table-column.model';
|
||||
import { DynamicTableRow } from './../../dynamic-table-row.model';
|
||||
import { DynamicTableModel } from './../../dynamic-table.widget.model';
|
||||
import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
|
||||
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-datetime-editor',
|
||||
templateUrl: './datetime.editor.html',
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS },
|
||||
{ provide: DatetimeAdapter, useClass: MomentDatetimeAdapter },
|
||||
{ provide: MAT_DATETIME_FORMATS, useValue: MAT_MOMENT_DATETIME_FORMATS }
|
||||
],
|
||||
styleUrls: ['./datetime.editor.scss']
|
||||
})
|
||||
export class DateTimeEditorComponent implements OnInit {
|
||||
|
||||
DATE_FORMAT: string = 'D-M-YYYY hh:mm A';
|
||||
|
||||
value: any;
|
||||
|
||||
@Input()
|
||||
table: DynamicTableModel;
|
||||
|
||||
@Input()
|
||||
row: DynamicTableRow;
|
||||
|
||||
@Input()
|
||||
column: DynamicTableColumn;
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
|
||||
constructor(private dateAdapter: DateAdapter<Moment>,
|
||||
private preferences: UserPreferencesService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.preferences.locale$.subscribe((locale) => {
|
||||
this.dateAdapter.setLocale(locale);
|
||||
});
|
||||
let momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
|
||||
momentDateAdapter.overrideDisplyaFormat = this.DATE_FORMAT;
|
||||
|
||||
this.value = moment(this.table.getCellValue(this.row, this.column), this.DATE_FORMAT);
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
if (newDateValue && newDateValue.value) {
|
||||
const newValue = moment(newDateValue.value, this.DATE_FORMAT);
|
||||
this.row.value[this.column.id] = newDateValue.value.format(this.DATE_FORMAT);
|
||||
this.value = newValue;
|
||||
this.table.flushValue();
|
||||
} else if (newDateValue) {
|
||||
const newValue = moment(newDateValue, this.DATE_FORMAT);
|
||||
this.value = newValue;
|
||||
this.row.value[this.column.id] = newDateValue;
|
||||
this.table.flushValue();
|
||||
} else {
|
||||
this.row.value[this.column.id] = '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,13 @@
|
||||
[column]="column">
|
||||
</adf-date-editor>
|
||||
</div>
|
||||
|
||||
<div *ngSwitchCase="'Datetime'">
|
||||
<adf-datetime-editor
|
||||
[table]="table"
|
||||
[row]="row"
|
||||
[column]="column">
|
||||
</adf-datetime-editor>
|
||||
</div>
|
||||
<div *ngSwitchCase="'Boolean'">
|
||||
<adf-boolean-editor
|
||||
[table]="table"
|
||||
|
||||
@@ -28,6 +28,7 @@ import { DropdownWidgetComponent } from './dropdown/dropdown.widget';
|
||||
import { DynamicTableWidgetComponent } from './dynamic-table/dynamic-table.widget';
|
||||
import { BooleanEditorComponent } from './dynamic-table/editors/boolean/boolean.editor';
|
||||
import { DateEditorComponent } from './dynamic-table/editors/date/date.editor';
|
||||
import { DateTimeEditorComponent } from './dynamic-table/editors/datetime/datetime.editor';
|
||||
import { DropdownEditorComponent } from './dynamic-table/editors/dropdown/dropdown.editor';
|
||||
import { RowEditorComponent } from './dynamic-table/editors/row.editor';
|
||||
import { TextEditorComponent } from './dynamic-table/editors/text/text.editor';
|
||||
@@ -80,6 +81,7 @@ export * from './dynamic-table/editors/date/date.editor';
|
||||
export * from './dynamic-table/editors/dropdown/dropdown.editor';
|
||||
export * from './dynamic-table/editors/boolean/boolean.editor';
|
||||
export * from './dynamic-table/editors/text/text.editor';
|
||||
export * from './dynamic-table/editors/datetime/datetime.editor';
|
||||
export * from './text/text-mask.component';
|
||||
|
||||
export const WIDGET_DIRECTIVES: any[] = [
|
||||
@@ -108,7 +110,8 @@ export const WIDGET_DIRECTIVES: any[] = [
|
||||
RowEditorComponent,
|
||||
ErrorWidgetComponent,
|
||||
DocumentWidgetComponent,
|
||||
DateTimeWidgetComponent
|
||||
DateTimeWidgetComponent,
|
||||
DateTimeEditorComponent
|
||||
];
|
||||
|
||||
export const MASK_DIRECTIVE: any[] = [
|
||||
|
||||
@@ -133,11 +133,17 @@
|
||||
"APPLY": "APPLY",
|
||||
"NOT_VALID": "http(s)://host|ip:port(/path) not recognized, try a different URL.",
|
||||
"REDIRECT": "Redirect Uri",
|
||||
"REDIRECT_LOGOUT": "Redirect Uri Logout",
|
||||
"SILENT": "Silent Login",
|
||||
"SCOPE": "Scope",
|
||||
"CLIENT": "ClientId"
|
||||
},
|
||||
"CARDVIEW": {
|
||||
"KEYVALUEPAIRS": {
|
||||
"ADD": "Add new",
|
||||
"NAME": "Name",
|
||||
"VALUE": "Value"
|
||||
},
|
||||
"VALIDATORS": {
|
||||
"FLOAT_VALIDATION_ERROR": "Use a number format",
|
||||
"INT_VALIDATION_ERROR": "Use an integer format"
|
||||
@@ -301,7 +307,7 @@
|
||||
"DESCRIPTION": "You're not allowed access to this resource on the server.",
|
||||
"SECONDARY_BUTTON": {
|
||||
"TEXT": "Report issue",
|
||||
"URL": ""
|
||||
"URL": "report-issue"
|
||||
},
|
||||
"RETURN_BUTTON": {
|
||||
"TEXT": "Back to home",
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export * from './collapsable/index';
|
||||
export * from './card-view/index';
|
||||
export * from './app-config/index';
|
||||
export * from './form/index';
|
||||
export * from './sidenav-layout/index';
|
||||
export * from './layout/index';
|
||||
export * from './comments/index';
|
||||
export * from './buttons-menu/index';
|
||||
export * from './sorting-picker/index';
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<mat-toolbar color="{{color}}">
|
||||
<button *ngIf="showSidenavToggle" class="mat-icon-button adf-menu-icon" mat-icon-button (click)="toggleMenu()">
|
||||
<mat-icon class="mat-icon material-icon" role="img" aria-hidden="true">menu</mat-icon>
|
||||
</button>
|
||||
|
||||
<img src="{{logo}}" class="adf-app-logo">
|
||||
|
||||
<span fxFlex="1 1 auto" fxShow fxHide.lt-sm="true" class="adf-app-title">{{title}}</span>
|
||||
<ng-content></ng-content>
|
||||
</mat-toolbar>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
@mixin adf-header-layout-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$accent: map-get($theme, accent);
|
||||
$background: map-get($theme, background);
|
||||
|
||||
adf-layout-header .mat-toolbar-single-row {
|
||||
|
||||
color: mat-color($primary, default-contrast) !important;
|
||||
position: relative;
|
||||
padding: 0 24px 0 0;
|
||||
|
||||
.adf-menu-icon {
|
||||
position: relative;
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.adf-app-logo {
|
||||
position: relative;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
margin-right: 6px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.adf-header-delimiter {
|
||||
height: 24px;
|
||||
width: 2px;
|
||||
background-color: mat-color($primary, default-contrast);
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.adf-app-layout-user-profile {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.adf-userinfo-container {
|
||||
flex-direction: row;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.adf-userinfo-name{
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
@media screen and ($mat-xsmall) {
|
||||
.adf-app-logo,
|
||||
.adf-app-title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*!
|
||||
* @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 { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { HeaderLayoutComponent } from './header.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { LayoutModule } from '../..';
|
||||
import { Component } from '@angular/core';
|
||||
import { MaterialModule } from './../../../material.module';
|
||||
|
||||
describe('HeaderLayoutComponent', () => {
|
||||
let fixture: ComponentFixture<HeaderLayoutComponent>;
|
||||
let component: HeaderLayoutComponent;
|
||||
|
||||
describe('Input parameters', () => {
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderLayoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should create instance of HeaderLayoutComponent', () => {
|
||||
expect(fixture.componentInstance instanceof HeaderLayoutComponent).toBe(true, 'should create HeaderLayoutComponent');
|
||||
});
|
||||
|
||||
it('title element should been displayed', () => {
|
||||
const titleElement = fixture.debugElement.query(By.css('.adf-app-title'));
|
||||
expect(titleElement === null).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should show TEST TITLE', () => {
|
||||
component.title = 'TEST TITLE';
|
||||
fixture.detectChanges();
|
||||
|
||||
const titleElement = fixture.nativeElement.querySelector('.adf-app-title');
|
||||
expect(titleElement.innerText).toEqual('TEST TITLE');
|
||||
});
|
||||
|
||||
it('color attribute should be present on mat-toolbar', () => {
|
||||
component.color = 'primary';
|
||||
fixture.detectChanges();
|
||||
|
||||
const toolbar = fixture.nativeElement.querySelector('mat-toolbar');
|
||||
expect(toolbar.getAttribute('ng-reflect-color') === null).toBeFalsy();
|
||||
expect(toolbar.getAttribute('ng-reflect-color')).toEqual('primary');
|
||||
});
|
||||
|
||||
it('should display the img element with the expected src if a logo path is set', () => {
|
||||
component.logo = 'logo.png';
|
||||
fixture.detectChanges();
|
||||
|
||||
const logo = fixture.nativeElement.querySelector('.adf-app-logo');
|
||||
const src = logo.getAttribute('src');
|
||||
expect(logo === null).toBeFalsy();
|
||||
expect(src).toEqual('logo.png');
|
||||
});
|
||||
|
||||
it('test click on sidenav button', () => {
|
||||
component.showSidenavToggle = true;
|
||||
fixture.detectChanges();
|
||||
spyOn(component.clicked, 'emit');
|
||||
const button = fixture.nativeElement.querySelector('.adf-menu-icon');
|
||||
|
||||
button.dispatchEvent(new Event('click'));
|
||||
fixture.detectChanges();
|
||||
expect(component.clicked.emit).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('if showSidenavToggle is false the button menu should not be displayed', () => {
|
||||
component.showSidenavToggle = false;
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.nativeElement.querySelector('.adf-menu-icon');
|
||||
expect(button === null).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Template tranclusion', () => {
|
||||
|
||||
@Component({
|
||||
selector: 'adf-test-layout-header',
|
||||
template: `<adf-layout-header title="test" color="primary"><p>Test text<p></adf-layout-header>`
|
||||
})
|
||||
class HeaderLayoutTesterComponent {}
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [HeaderLayoutTesterComponent],
|
||||
imports: [ LayoutModule, MaterialModule ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should transclude the provided nodes into the component', () => {
|
||||
const hostFixture = TestBed.createComponent(HeaderLayoutTesterComponent);
|
||||
hostFixture.detectChanges();
|
||||
const innerText = hostFixture.nativeElement.querySelector('mat-toolbar>p').innerText;
|
||||
expect(innerText).toEqual('Test text');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* @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, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-layout-header',
|
||||
templateUrl: './header.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { class: 'adf-layout-header' }
|
||||
})
|
||||
export class HeaderLayoutComponent {
|
||||
@Input() title: string;
|
||||
@Input() logo: string = './assets/images/logo.png';
|
||||
@Input() color: string;
|
||||
@Input() showSidenavToggle: boolean = true;
|
||||
@Output() clicked = new EventEmitter<any>();
|
||||
|
||||
toggleMenu() {
|
||||
this.clicked.emit(true);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user