mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-16 18:13:06 +00:00
Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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.4.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"APP_LAYOUT": {
|
||||
"APP_NAME": "ADF Demo Application",
|
||||
"HOME": "Home",
|
||||
"NODE-SELECTOR": "Node Selector",
|
||||
"CONTENT_SERVICES": "Content Services",
|
||||
"BREADCRUMB": "Breadcrumb",
|
||||
"PROCESS_SERVICES": "Process Services",
|
||||
|
||||
@@ -52,7 +52,9 @@ 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';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -106,7 +108,9 @@ import { NotificationsComponent } from './components/notifications/notifications
|
||||
FormLoadingComponent,
|
||||
BlobPreviewComponent,
|
||||
BreadcrumbDemoComponent,
|
||||
NotificationsComponent
|
||||
NotificationsComponent,
|
||||
ContentNodeSelectorComponent,
|
||||
ReportIssueComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production
|
||||
@@ -128,7 +132,10 @@ import { NotificationsComponent } from './components/notifications/notifications
|
||||
},
|
||||
PreviewService
|
||||
],
|
||||
entryComponents: [VersionManagerDialogAdapterComponent, MetadataDialogAdapterComponent],
|
||||
entryComponents: [
|
||||
VersionManagerDialogAdapterComponent,
|
||||
MetadataDialogAdapterComponent
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -50,6 +50,8 @@ 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 { 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 },
|
||||
@@ -86,6 +88,10 @@ export const appRoutes: Routes = [
|
||||
path: 'home',
|
||||
component: HomeComponent
|
||||
},
|
||||
{
|
||||
path: 'node-selector',
|
||||
component: ContentNodeSelectorComponent
|
||||
},
|
||||
{
|
||||
path: 'settings-layout',
|
||||
component: SettingsComponent
|
||||
@@ -216,6 +222,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,9 +1,9 @@
|
||||
<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()">
|
||||
<button mat-icon-button (click)="toggleMenu()" *ngIf="!hideSidenav">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ 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: '/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 +55,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 {
|
||||
|
||||
|
||||
+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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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.4.0",
|
||||
"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.4.0",
|
||||
"@alfresco/adf-core": "2.4.0",
|
||||
"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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 placeholder="{{ property.label | translate }}" [(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>
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*!
|
||||
* @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 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,56 @@
|
||||
/*!
|
||||
* @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'
|
||||
})
|
||||
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;
|
||||
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)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -390,8 +390,6 @@
|
||||
.ellipsis-cell {
|
||||
.cell-container {
|
||||
height: 100%;
|
||||
display: inline-grid;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cell-container > * {
|
||||
@@ -407,7 +405,7 @@
|
||||
/* visible content */
|
||||
.cell-value {
|
||||
display: block;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
max-width: calc(100% - 2em);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -61,11 +61,11 @@
|
||||
data-automation-id="password"
|
||||
tabindex="2">
|
||||
<mat-icon *ngIf="isPasswordShow" matSuffix class="adf-login-password-icon"
|
||||
data-automation-id="hide_password" (click)="toggleShowPassword()">
|
||||
data-automation-id="hide_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="3">
|
||||
visibility
|
||||
</mat-icon>
|
||||
<mat-icon *ngIf="!isPasswordShow" matSuffix class="adf-login-password-icon"
|
||||
data-automation-id="show_password" (click)="toggleShowPassword()">
|
||||
data-automation-id="show_password" (click)="toggleShowPassword()" (keyup.enter)="toggleShowPassword()" tabindex="3">
|
||||
visibility_off
|
||||
</mat-icon>
|
||||
</mat-form-field>
|
||||
@@ -79,7 +79,7 @@
|
||||
<ng-content></ng-content>
|
||||
|
||||
<br>
|
||||
<button type="submit" id="login-button" tabindex="3"
|
||||
<button type="submit" id="login-button" tabindex="4"
|
||||
class="adf-login-button"
|
||||
mat-raised-button color="primary"
|
||||
[class.isChecking]="actualLoginStep === LoginSteps.Checking"
|
||||
|
||||
@@ -27,6 +27,7 @@ export class UserProcessModel implements LightUserRepresentation {
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
pictureId?: number = null;
|
||||
externalId?: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
@@ -35,6 +36,7 @@ export class UserProcessModel implements LightUserRepresentation {
|
||||
this.firstName = obj.firstName || null;
|
||||
this.lastName = obj.lastName || null;
|
||||
this.pictureId = obj.pictureId || null;
|
||||
this.externalId = obj.externalId || null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-core",
|
||||
"description": "Alfresco ADF core",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.4.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "bundles/adf-core.js",
|
||||
"repository": {
|
||||
@@ -26,7 +26,7 @@
|
||||
"@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-js-api": "2.4.0",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
|
||||
@@ -22,6 +22,7 @@ import { CookieService } from './cookie.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { setupTestBed } from '../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { UserRepresentation } from 'alfresco-js-api';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
@@ -311,7 +312,7 @@ describe('AuthenticationService', () => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(err).toBeDefined();
|
||||
expect(authService.getTicketBpm()).toBe(null);
|
||||
expect(authService.getTicketBpm()).toBe(undefined);
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -349,6 +350,18 @@ describe('AuthenticationService', () => {
|
||||
it('[BPM] should return isALLProvider false', () => {
|
||||
expect(authService.isALLProvider()).toBe(false);
|
||||
});
|
||||
|
||||
it('[BPM] should be able to retrieve current logged in user', (done) => {
|
||||
spyOn(apiService.getInstance().activiti.profileApi, 'getProfile').and.returnValue(
|
||||
Promise.resolve((<UserRepresentation> {
|
||||
email: 'fake-email'
|
||||
})));
|
||||
|
||||
authService.getBpmLoggedUser().subscribe((fakeUser) => {
|
||||
expect(fakeUser.email).toBe('fake-email');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the setting is both ECM and BPM ', () => {
|
||||
|
||||
@@ -26,6 +26,7 @@ import { AppConfigService, AppConfigValues } from '../app-config/app-config.serv
|
||||
import 'rxjs/add/observable/fromPromise';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/observable/throw';
|
||||
import { UserRepresentation } from 'alfresco-js-api';
|
||||
|
||||
const REMEMBER_ME_COOKIE_KEY = 'ALFRESCO_REMEMBER_ME';
|
||||
const REMEMBER_ME_UNTIL = 1000 * 60 * 60 * 24 * 30 ;
|
||||
@@ -228,6 +229,10 @@ export class AuthenticationService {
|
||||
return this.hasValidRedirection(provider) ? this.redirectUrl.url : null;
|
||||
}
|
||||
|
||||
getBpmLoggedUser(): Observable<UserRepresentation> {
|
||||
return Observable.fromPromise(this.alfrescoApi.getInstance().activiti.profileApi.getProfile());
|
||||
}
|
||||
|
||||
private hasValidRedirection(provider: string): boolean {
|
||||
return this.redirectUrl && (this.redirectUrl.provider === provider || this.hasSelectedProviderAll(provider));
|
||||
}
|
||||
|
||||
@@ -106,6 +106,12 @@
|
||||
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="full-width" floatLabel="Redirect Uri Logout">
|
||||
<mat-label>{{ 'CORE.HOST_SETTINGS.REDIRECT_LOGOUT'| translate }}</mat-label>
|
||||
<input matInput placeholder="{{ 'CORE.HOST_SETTINGS.REDIRECT_LOGOUT'| translate }}"
|
||||
name="redirectUriLogout" formControlName="redirectUriLogout">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</ng-container>
|
||||
<mat-card-actions class="adf-actions">
|
||||
|
||||
@@ -140,6 +140,7 @@ export class HostSettingsComponent implements OnInit {
|
||||
host: [oauth.host, [Validators.required, Validators.pattern(this.HOST_REGEX)]],
|
||||
clientId: [oauth.clientId, Validators.required],
|
||||
redirectUri: [oauth.redirectUri, Validators.required],
|
||||
redirectUriLogout: [oauth.redirectUriLogout],
|
||||
scope: [oauth.scope, Validators.required],
|
||||
secret: oauth.secret,
|
||||
silentLogin: oauth.silentLogin,
|
||||
@@ -250,6 +251,10 @@ export class HostSettingsComponent implements OnInit {
|
||||
return this.oauthConfig.get('redirectUri');
|
||||
}
|
||||
|
||||
get redirectUriLogout(): AbstractControl {
|
||||
return this.oauthConfig.get('redirectUriLogout');
|
||||
}
|
||||
|
||||
get oauthConfig(): AbstractControl {
|
||||
return this.form.get('oauthConfig');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-insights",
|
||||
"description": "Alfresco ADF insights",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.4.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "bundles/adf-insights.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.4.0",
|
||||
"@alfresco/adf-core": "2.4.0",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
|
||||
@@ -152,6 +152,9 @@
|
||||
"NO_FORM_MESSAGE": "No forms attached",
|
||||
"COMPLETE_TASK_MESSAGE": "Task {{taskName}} completed",
|
||||
"COMPLETE_TASK_SUB_MESSAGE": "No forms to be added"
|
||||
},
|
||||
"ATTACH_FORM":{
|
||||
"SELECT_FORM": "Select Form To Attach"
|
||||
}
|
||||
},
|
||||
"ADF_PROCESS_LIST": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@alfresco/adf-process-services",
|
||||
"description": "Alfresco ADF process services",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.4.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "bundles/adf-process-services.js",
|
||||
"repository": {
|
||||
@@ -12,8 +12,8 @@
|
||||
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alfresco/adf-core": "2.4.0-beta14",
|
||||
"@alfresco/adf-content-services": "2.4.0-beta14",
|
||||
"@alfresco/adf-core": "2.4.0",
|
||||
"@alfresco/adf-content-services": "2.4.0",
|
||||
"@angular/animations": "5.1.1",
|
||||
"@angular/cdk": "5.0.1",
|
||||
"@angular/common": "5.1.1",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@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-js-api": "2.4.0",
|
||||
"chart.js": "2.5.0",
|
||||
"core-js": "2.4.1",
|
||||
"hammerjs": "2.0.8",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<div class="adf-attach-form">
|
||||
<mat-card>
|
||||
<mat-card-content>
|
||||
<div class="adf-no-form-message-container">
|
||||
<mat-card-title class="mat-card-title">
|
||||
<h4 class="adf-form-title">{{ 'ADF_TASK_LIST.ATTACH_FORM.SELECT_FORM' | translate }}</h4>
|
||||
</mat-card-title>
|
||||
<div class="adf-attach-form-row">
|
||||
<mat-form-field class="adf-grid-full-width">
|
||||
<mat-select id="form_id" [(ngModel)]="formKey">
|
||||
<mat-option *ngFor="let form of forms" [value]="form.id">{{ form.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<adf-form
|
||||
[formId]="formKey"
|
||||
[readOnly]="true"
|
||||
[disableCompleteButton]="true"
|
||||
[showRefreshButton]="false">
|
||||
</adf-form>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="adf-no-form-mat-card-actions">
|
||||
<button mat-button id="adf-no-form-cancel-button" (click)="onCancelButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL' | translate }}</button>
|
||||
<button mat-button id="adf-no-form-attach-form-button" color="primary" (click)="onAttachFormButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
.adf-attach-form {
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.adf-no-form-mat-card-actions {
|
||||
justify-content: flex-end;
|
||||
margin-top: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*!
|
||||
* @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 { AttachFormComponent } from './attach-form.component';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { ProcessTestingModule } from '../../testing/process.testing.module';
|
||||
import { TaskListService } from './../services/tasklist.service';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
describe('AttachFormComponent', () => {
|
||||
let component: AttachFormComponent;
|
||||
let fixture: ComponentFixture<AttachFormComponent>;
|
||||
let element: HTMLElement;
|
||||
let taskService: TaskListService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
ProcessTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(AttachFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
taskService = TestBed.get(TaskListService);
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should emit cancel event if clicked on Cancel Button ', async(() => {
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
const emitSpy = spyOn(component.cancelAttachForm, 'emit');
|
||||
const el = fixture.nativeElement.querySelector('#adf-no-form-cancel-button');
|
||||
el.click();
|
||||
expect(emitSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should call attachFormToATask if clicked on Complete Button', async(() => {
|
||||
component.taskId = 1;
|
||||
component.formKey = 2;
|
||||
spyOn(taskService, 'attachFormToATask').and.returnValue(Observable.of(true));
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(element.querySelector('#adf-no-form-attach-form-button')).toBeDefined();
|
||||
const el = fixture.nativeElement.querySelector('#adf-no-form-attach-form-button');
|
||||
el.click();
|
||||
expect(taskService.attachFormToATask).toHaveBeenCalledWith(1, 2);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the adf-form of the selected form', async(() => {
|
||||
component.taskId = 1;
|
||||
component.formKey = 12;
|
||||
fixture.detectChanges();
|
||||
const formContainer = fixture.debugElement.nativeElement.querySelector('adf-form');
|
||||
fixture.whenStable().then(() => {
|
||||
expect(formContainer).toBeDefined();
|
||||
expect(formContainer).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
/*!
|
||||
* @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 { LogService } from '@alfresco/adf-core';
|
||||
import { Component, EventEmitter, Input, OnInit, OnChanges, Output } from '@angular/core';
|
||||
import { Form } from '../models/form.model';
|
||||
import { TaskListService } from './../services/tasklist.service';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-attach-form',
|
||||
templateUrl: './attach-form.component.html',
|
||||
styleUrls: ['./attach-form.component.scss']
|
||||
})
|
||||
|
||||
export class AttachFormComponent implements OnInit, OnChanges {
|
||||
constructor(private taskService: TaskListService,
|
||||
private logService: LogService) { }
|
||||
|
||||
/** The id of the task whose details we are asking for. */
|
||||
@Input()
|
||||
taskId;
|
||||
|
||||
/** Emitted when the "Cancel" button is clicked. */
|
||||
@Output()
|
||||
cancelAttachForm: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
/** Emitted when the form associated with the form task is attached. */
|
||||
@Output()
|
||||
completeAttachForm: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
/** Emitted when an error occurs. */
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
forms: Form[];
|
||||
|
||||
formKey: number;
|
||||
|
||||
ngOnInit() {
|
||||
this.loadFormsTask();
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.loadFormsTask();
|
||||
}
|
||||
|
||||
onCancelButtonClick(): void {
|
||||
this.cancelAttachForm.emit();
|
||||
}
|
||||
|
||||
onAttachFormButtonClick(): void {
|
||||
this.attachForm(this.taskId, this.formKey);
|
||||
}
|
||||
|
||||
private loadFormsTask(): void {
|
||||
this.taskService.getFormList().subscribe((res: Form[]) => {
|
||||
this.forms = res;
|
||||
},
|
||||
(err) => {
|
||||
this.error.emit(err);
|
||||
this.logService.error('An error occurred while trying to get the forms');
|
||||
});
|
||||
}
|
||||
|
||||
private attachForm(taskId: string, formKey: number) {
|
||||
if (taskId && formKey) {
|
||||
this.taskService.attachFormToATask(taskId, formKey)
|
||||
.subscribe((res) => {
|
||||
this.completeAttachForm.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,19 @@
|
||||
|
||||
import { NoTaskDetailsTemplateDirective } from './no-task-detail-template.directive';
|
||||
import { TaskDetailsComponent } from './task-details.component';
|
||||
import { FormRenderingService } from '@alfresco/adf-core';
|
||||
import { FormRenderingService, AuthenticationService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
describe('NoTaskDetailsTemplateDirective', () => {
|
||||
|
||||
let component: NoTaskDetailsTemplateDirective;
|
||||
let detailsComponent: TaskDetailsComponent;
|
||||
let authService: AuthenticationService;
|
||||
|
||||
beforeEach(() => {
|
||||
detailsComponent = new TaskDetailsComponent(null, null, null, new FormRenderingService(), null, null, null);
|
||||
authService = new AuthenticationService(null, null, null, null);
|
||||
spyOn(authService, 'getBpmLoggedUser').and.returnValue(Observable.of({ email: 'fake-email'}));
|
||||
detailsComponent = new TaskDetailsComponent(null, authService, null, new FormRenderingService(), null, null, null);
|
||||
component = new NoTaskDetailsTemplateDirective(detailsComponent);
|
||||
});
|
||||
|
||||
|
||||
@@ -39,12 +39,14 @@
|
||||
(error)='onFormError($event)'
|
||||
(executeOutcome)='onFormExecuteOutcome($event)'>
|
||||
</adf-form>
|
||||
<adf-task-standalone *ngIf="!hasFormKey()"
|
||||
[taskName]= "taskDetails.name"
|
||||
[isCompleted]="isCompletedTask()"
|
||||
[hasCompletePermission]="isCompleteButtonEnabled()"
|
||||
[hideCancelButton]="true"
|
||||
(complete)="onComplete()">
|
||||
<adf-task-standalone *ngIf="!hasFormKey()"
|
||||
[taskName]= "taskDetails.name"
|
||||
[taskId]= "taskDetails.id"
|
||||
[isCompleted]="isCompletedTask()"
|
||||
[hasCompletePermission]="isCompleteButtonEnabled()"
|
||||
[hideCancelButton]="true"
|
||||
(complete)="onComplete()"
|
||||
(formAttached)="onFormAttached()">
|
||||
</adf-task-standalone>
|
||||
</div>
|
||||
<div *ngIf="!isAssigned()" id="claim-message-id">
|
||||
|
||||
@@ -74,10 +74,12 @@ adf-task-header.assign-edit-view ::ng-deep adf-card-view ::ng-deep .adf-property
|
||||
flex-grow: 1;
|
||||
|
||||
& ::ng-deep .adf-form-debug-container {
|
||||
padding: 20px 0 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px 0;
|
||||
|
||||
.mat-slide-toggle {
|
||||
float: right;
|
||||
margin-left: auto;
|
||||
|
||||
& + div {
|
||||
background-color: black;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { By } from '@angular/platform-browser';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { FormModel, FormOutcomeEvent, FormOutcomeModel, FormService, setupTestBed, BpmUserService } from '@alfresco/adf-core';
|
||||
import { CommentProcessService, LogService } from '@alfresco/adf-core';
|
||||
import { CommentProcessService, LogService, AuthenticationService } from '@alfresco/adf-core';
|
||||
|
||||
import { UserProcessModel } from '@alfresco/adf-core';
|
||||
import { TaskDetailsModel } from '../models/task-details.model';
|
||||
@@ -51,6 +51,7 @@ describe('TaskDetailsComponent', () => {
|
||||
let logService: LogService;
|
||||
let commentProcessService: CommentProcessService;
|
||||
let peopleProcessService: PeopleProcessService;
|
||||
let authService: AuthenticationService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
@@ -80,6 +81,9 @@ describe('TaskDetailsComponent', () => {
|
||||
completeTaskSpy = spyOn(service, 'completeTask').and.returnValue(Observable.of({}));
|
||||
commentProcessService = TestBed.get(CommentProcessService);
|
||||
|
||||
authService = TestBed.get(AuthenticationService);
|
||||
spyOn(authService, 'getBpmLoggedUser').and.returnValue(Observable.of({ email: 'fake-email'}));
|
||||
|
||||
spyOn(commentProcessService, 'getTaskComments').and.returnValue(Observable.of([
|
||||
{message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}},
|
||||
{message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'}},
|
||||
@@ -156,9 +160,12 @@ describe('TaskDetailsComponent', () => {
|
||||
|
||||
it('should not display task standalone component when the task have an associated form', async(() => {
|
||||
component.taskId = '123';
|
||||
component.taskDetails = new TaskDetailsModel(taskDetailsMock);
|
||||
component.taskDetails.formKey = '10';
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('adf-task-standalone'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('adf-task-standalone'))).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
CardViewUpdateService,
|
||||
ClickNotification,
|
||||
LogService,
|
||||
FormService,
|
||||
UpdateNotification,
|
||||
FormRenderingService,
|
||||
CommentsComponent
|
||||
@@ -44,6 +45,7 @@ import { TaskQueryRequestRepresentationModel } from '../models/filter.model';
|
||||
import { TaskDetailsModel } from '../models/task-details.model';
|
||||
import { TaskListService } from './../services/tasklist.service';
|
||||
import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../../content-widget';
|
||||
import { UserRepresentation } from 'alfresco-js-api';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-task-details',
|
||||
@@ -179,10 +181,13 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
|
||||
|
||||
peopleSearch: Observable<UserProcessModel[]>;
|
||||
|
||||
currentLoggedUser: UserRepresentation;
|
||||
|
||||
constructor(private taskListService: TaskListService,
|
||||
private authService: AuthenticationService,
|
||||
private peopleProcessService: PeopleProcessService,
|
||||
private formRenderingService: FormRenderingService,
|
||||
private formService: FormService,
|
||||
private logService: LogService,
|
||||
private cardViewUpdateService: CardViewUpdateService,
|
||||
private dialog: MatDialog) {
|
||||
@@ -190,6 +195,9 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
|
||||
this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true);
|
||||
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true);
|
||||
this.peopleSearch = new Observable<UserProcessModel[]>(observer => this.peopleSearchObserver = observer).share();
|
||||
this.authService.getBpmLoggedUser().subscribe((user: UserRepresentation) => {
|
||||
this.currentLoggedUser = user;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -285,8 +293,22 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
|
||||
return this.taskDetails.assignee ? true : false;
|
||||
}
|
||||
|
||||
private hasEmailAddress(): boolean {
|
||||
return this.taskDetails.assignee.email ? true : false;
|
||||
}
|
||||
|
||||
isAssignedToMe(): boolean {
|
||||
return this.isAssigned() ? this.taskDetails.assignee.email === this.authService.getBpmUsername() : false;
|
||||
return this.isAssigned() && this.hasEmailAddress() ?
|
||||
this.isEmailEqual(this.taskDetails.assignee.email, this.currentLoggedUser.email) :
|
||||
this.isExternalIdEqual(this.taskDetails.assignee.externalId, this.currentLoggedUser.externalId);
|
||||
}
|
||||
|
||||
private isEmailEqual(assigneeMail, currentLoggedEmail): boolean {
|
||||
return assigneeMail.toLocaleLowerCase() === currentLoggedEmail.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
private isExternalIdEqual(assigneeExternalId, currentUserExternalId): boolean {
|
||||
return assigneeExternalId.toLocaleLowerCase() === currentUserExternalId.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
isCompleteButtonEnabled(): boolean {
|
||||
@@ -342,6 +364,13 @@ export class TaskDetailsComponent implements OnInit, OnChanges {
|
||||
);
|
||||
}
|
||||
|
||||
onFormAttached() {
|
||||
this.formService.getTaskForm(this.taskId)
|
||||
.subscribe((res) => {
|
||||
this.loadDetails(this.taskId);
|
||||
}, error => this.logService.error('Could not load forms'));
|
||||
}
|
||||
|
||||
onFormContentClick(content: ContentLinkModel): void {
|
||||
this.formContentClicked.emit(content);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<mat-card class="adf-message-card">
|
||||
<mat-card class="adf-message-card" *ngIf="!showAttachForm">
|
||||
<mat-card-content>
|
||||
<div class="adf-no-form-message-container">
|
||||
<div class="adf-no-form-message-list">
|
||||
@@ -18,7 +18,16 @@
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="adf-no-form-mat-card-actions">
|
||||
<button mat-button *ngIf="hasCancelButton()" id="adf-no-form-cancel-button" (click)="onCancelButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL' | translate }}</button>
|
||||
<button mat-button *ngIf="hasCompleteButton()" id="adf-no-form-complete-button" color="primary" (click)="onCompleteButtonClick()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button>
|
||||
<button mat-button *ngIf="hasAttachFormButton()" id="adf-no-form-attach-form-button" (click)="onShowAttachForm()">{{ 'ADF_TASK_LIST.START_TASK.FORM.LABEL.ATTACHFORM' | translate }}</button>
|
||||
<div>
|
||||
<button mat-button *ngIf="hasCancelButton()" id="adf-no-form-cancel-button" (click)="onCancelButtonClick()">{{ 'ADF_TASK_LIST.START_TASK.FORM.ACTION.CANCEL' | translate }}</button>
|
||||
<button mat-button *ngIf="hasCompleteButton()" id="adf-no-form-complete-button" color="primary" (click)="onCompleteButtonClick()">{{ 'ADF_TASK_LIST.DETAILS.BUTTON.COMPLETE' | translate }}</button>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</mat-card>
|
||||
|
||||
<adf-attach-form *ngIf="showAttachForm"
|
||||
[taskId]="taskId"
|
||||
(cancelAttachForm)="onCancelAttachForm()"
|
||||
(completeAttachForm)="onCompleteAttachForm()">
|
||||
</adf-attach-form>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
$config: mat-typography-config();
|
||||
$background: map-get($theme, background);
|
||||
|
||||
|
||||
.adf {
|
||||
&-message-card {
|
||||
width: 60%;
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
}
|
||||
&-no-form-message-container {
|
||||
height:256px;
|
||||
height: 256px;
|
||||
width: 100%;
|
||||
display: table;
|
||||
}
|
||||
@@ -37,8 +37,9 @@
|
||||
margin: auto;
|
||||
width: fit-content !important;
|
||||
}
|
||||
&-no-form-mat-card-actions {
|
||||
text-align: right;
|
||||
&-no-form-mat-card-actions.mat-card-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
& .mat-button {
|
||||
text-transform: uppercase;
|
||||
border-radius: 5px;
|
||||
@@ -50,4 +51,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,11 @@ export class TaskStandaloneComponent {
|
||||
|
||||
/** Name of the task. */
|
||||
@Input()
|
||||
taskName: string;
|
||||
taskName;
|
||||
|
||||
/** Id of the task. */
|
||||
@Input()
|
||||
taskId;
|
||||
|
||||
/** If true then Task completed message is shown and `Complete` and `Cancel` buttons are hidden. */
|
||||
@Input()
|
||||
@@ -50,6 +54,11 @@ export class TaskStandaloneComponent {
|
||||
@Output()
|
||||
complete: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
@Output()
|
||||
formAttached: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
||||
showAttachForm: boolean = false;
|
||||
|
||||
constructor() { }
|
||||
|
||||
onCancelButtonClick(): void {
|
||||
@@ -67,4 +76,21 @@ export class TaskStandaloneComponent {
|
||||
hasCancelButton(): boolean {
|
||||
return !this.hideCancelButton && !this.isCompleted;
|
||||
}
|
||||
|
||||
hasAttachFormButton(): boolean {
|
||||
return !this.isCompleted;
|
||||
}
|
||||
|
||||
onShowAttachForm() {
|
||||
this.showAttachForm = true;
|
||||
}
|
||||
|
||||
onCancelAttachForm() {
|
||||
this.showAttachForm = false;
|
||||
}
|
||||
|
||||
onCompleteAttachForm() {
|
||||
this.showAttachForm = false;
|
||||
this.formAttached.emit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export * from './components/task-details.component';
|
||||
export * from './components/task-audit.directive';
|
||||
export * from './components/start-task.component';
|
||||
export * from './components/task-standalone.component';
|
||||
export * from './components/attach-form.component';
|
||||
|
||||
export * from './services/tasklist.service';
|
||||
export * from './services/process-upload.service';
|
||||
|
||||
@@ -40,6 +40,7 @@ import { TaskFiltersComponent } from './components/task-filters.component';
|
||||
import { TaskHeaderComponent } from './components/task-header.component';
|
||||
import { TaskListComponent } from './components/task-list.component';
|
||||
import { TaskStandaloneComponent } from './components/task-standalone.component';
|
||||
import { AttachFormComponent } from './components/attach-form.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -63,7 +64,8 @@ import { TaskStandaloneComponent } from './components/task-standalone.component'
|
||||
ChecklistComponent,
|
||||
TaskHeaderComponent,
|
||||
StartTaskComponent,
|
||||
TaskStandaloneComponent
|
||||
TaskStandaloneComponent,
|
||||
AttachFormComponent
|
||||
],
|
||||
providers: [
|
||||
TaskListService,
|
||||
@@ -80,7 +82,8 @@ import { TaskStandaloneComponent } from './components/task-standalone.component'
|
||||
ChecklistComponent,
|
||||
TaskHeaderComponent,
|
||||
StartTaskComponent,
|
||||
TaskStandaloneComponent
|
||||
TaskStandaloneComponent,
|
||||
AttachFormComponent
|
||||
]
|
||||
})
|
||||
export class TaskListModule {
|
||||
|
||||
Generated
+5783
-5797
File diff suppressed because it is too large
Load Diff
+6
-6
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "alfresco-components",
|
||||
"description": "Alfresco Angular components",
|
||||
"version": "2.4.0-beta14",
|
||||
"version": "2.4.0",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"main": "./index.js",
|
||||
"scripts": {
|
||||
@@ -55,10 +55,10 @@
|
||||
"process services"
|
||||
],
|
||||
"dependencies": {
|
||||
"@alfresco/adf-content-services": "2.4.0-beta14",
|
||||
"@alfresco/adf-core": "2.4.0-beta14",
|
||||
"@alfresco/adf-insights": "2.4.0-beta14",
|
||||
"@alfresco/adf-process-services": "2.4.0-beta14",
|
||||
"@alfresco/adf-content-services": "2.4.0",
|
||||
"@alfresco/adf-core": "2.4.0",
|
||||
"@alfresco/adf-insights": "2.4.0",
|
||||
"@alfresco/adf-process-services": "2.4.0",
|
||||
"@angular/animations": "5.1.1",
|
||||
"@angular/cdk": "5.0.1",
|
||||
"@angular/common": "5.1.1",
|
||||
@@ -76,7 +76,7 @@
|
||||
"@mat-datetimepicker/moment": "1.0.4",
|
||||
"@ngx-translate/core": "9.1.1",
|
||||
"@nrwl/schematics": "^1.0.3",
|
||||
"alfresco-js-api": "2.4.0-beta14",
|
||||
"alfresco-js-api": "2.4.0",
|
||||
"chart.js": "2.5.0",
|
||||
"classlist.js": "1.1.20150312",
|
||||
"core-js": "2.4.1",
|
||||
|
||||
+54
-56
@@ -18,6 +18,7 @@ var configFileName = "doctool.config.json";
|
||||
var defaultFolder = path.resolve("docs");
|
||||
|
||||
|
||||
/*
|
||||
function initPhase(aggData) {
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].initPhase(aggData);
|
||||
@@ -25,19 +26,10 @@ function initPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
function readPhase(filenames, aggData) {
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
var pathname = filenames[i];//path.resolve(srcFolder, filenames[i]);
|
||||
|
||||
var src = fs.readFileSync(pathname);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(src);
|
||||
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].readPhase(tree, pathname, aggData);
|
||||
});
|
||||
}
|
||||
|
||||
//console.log(JSON.stringify(aggData.mdFileData));
|
||||
function readPhase(mdCache, aggData) {
|
||||
toolList.forEach(toolName => {
|
||||
toolModules[toolName].readPhase(mdCache, aggData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -46,36 +38,25 @@ function aggPhase(aggData) {
|
||||
toolModules[toolName].aggPhase(aggData);
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
function updatePhase(filenames, aggData) {
|
||||
function updatePhase(mdCache, aggData) {
|
||||
var errorMessages;
|
||||
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
toolList.forEach(toolName => {
|
||||
errorMessages = [];
|
||||
console.log(`Tool: ${toolName}`);
|
||||
toolModules[toolName].processDocs(mdCache, aggData, errorMessages);
|
||||
});
|
||||
|
||||
var filenames = Object.keys(mdCache);
|
||||
|
||||
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
var pathname = filenames[i];
|
||||
|
||||
if (program.verbose) {
|
||||
console.log("Reading " + pathname);
|
||||
}
|
||||
|
||||
var src = fs.readFileSync(pathname);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(src);
|
||||
var tree = mdCache[pathname].mdOutTree;
|
||||
var original = mdCache[pathname].mdInTree;
|
||||
|
||||
var original = minimiseTree(tree);
|
||||
|
||||
var modified = false;
|
||||
|
||||
toolList.forEach(toolName => {
|
||||
modified |= toolModules[toolName].updatePhase(tree, pathname, aggData, errorMessages);
|
||||
});
|
||||
|
||||
if (errorMessages.length > 0) {
|
||||
showErrors(pathname, errorMessages);
|
||||
}
|
||||
|
||||
tree = minimiseTree(tree);
|
||||
|
||||
if (program.json) {
|
||||
let filename = path.basename(pathname);
|
||||
|
||||
@@ -84,10 +65,8 @@ function updatePhase(filenames, aggData) {
|
||||
console.log(`\nFile "${filename}" after processing:`);
|
||||
console.log(JSON.stringify(tree));
|
||||
}
|
||||
|
||||
modified = !lodash.isEqual(tree, original);
|
||||
|
||||
if (modified) {
|
||||
if (!lodash.isEqual(tree, original)) {
|
||||
if (program.verbose) {
|
||||
console.log(`Modified: ${pathname}`);
|
||||
}
|
||||
@@ -113,17 +92,6 @@ function minimiseTree(tree) {
|
||||
}
|
||||
|
||||
|
||||
function showErrors(filename, errorMessages) {
|
||||
console.log(filename);
|
||||
|
||||
errorMessages.forEach(message => {
|
||||
console.log(" " + message);
|
||||
});
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
|
||||
function loadToolModules() {
|
||||
var mods = {};
|
||||
var toolsFolderPath = path.resolve(__dirname, toolsFolderName);
|
||||
@@ -164,13 +132,37 @@ function getAllDocFilePaths(docFolder, files) {
|
||||
}
|
||||
|
||||
|
||||
function initMdCache(filenames) {
|
||||
var mdCache = {};
|
||||
|
||||
for (var i = 0; i < filenames.length; i++) {
|
||||
var pathname = filenames[i];
|
||||
mdCache[pathname] = {};
|
||||
|
||||
var src = fs.readFileSync(pathname);
|
||||
var tree = remark().use(frontMatter, ["yaml"]).parse(src);
|
||||
mdCache[pathname].mdInTree = minimiseTree(tree);
|
||||
mdCache[pathname].mdOutTree = minimiseTree(tree);
|
||||
}
|
||||
|
||||
return mdCache;
|
||||
}
|
||||
|
||||
|
||||
program
|
||||
.usage("[options] <source>")
|
||||
.option("-p, --profile [profileName]", "Select named config profile", "default")
|
||||
.option("-j, --json", "Output JSON data for Markdown syntax tree")
|
||||
.option("-v, --verbose", "Log doc files as they are processed")
|
||||
.option("-t, --timing", "Output time taken for run")
|
||||
.parse(process.argv);
|
||||
|
||||
var startTime;
|
||||
|
||||
if (program.timing) {
|
||||
startTime = process.hrtime();
|
||||
}
|
||||
|
||||
var sourcePath;
|
||||
|
||||
if (program.args.length === 0) {
|
||||
@@ -206,23 +198,29 @@ if (sourceInfo.isDirectory()) {
|
||||
}
|
||||
|
||||
files = files.filter(filename =>
|
||||
(filename !== undefined) &&
|
||||
(path.extname(filename) === ".md") &&
|
||||
(filename !== "README.md")
|
||||
);
|
||||
|
||||
//files.forEach(element => console.log(element));
|
||||
|
||||
var mdCache = initMdCache(files);
|
||||
|
||||
/*
|
||||
console.log("Initialising...");
|
||||
initPhase(aggData);
|
||||
|
||||
console.log("Analysing Markdown files...");
|
||||
readPhase(files, aggData);
|
||||
readPhase(mdCache, aggData);
|
||||
|
||||
console.log("Computing aggregate data...");
|
||||
aggPhase(aggData);
|
||||
*/
|
||||
|
||||
console.log("Updating Markdown files...");
|
||||
updatePhase(files, aggData);
|
||||
|
||||
|
||||
updatePhase(mdCache, aggData);
|
||||
|
||||
if (program.timing) {
|
||||
var endTime = process.hrtime(startTime);
|
||||
console.log(`Run complete in ${endTime[0]} sec`);
|
||||
}
|
||||
@@ -19,7 +19,8 @@
|
||||
"toc"
|
||||
],
|
||||
"dev": [
|
||||
"toc"
|
||||
"tsInfo",
|
||||
"typeLinker"
|
||||
]
|
||||
},
|
||||
"statusIcons": {
|
||||
|
||||
+21
-11
@@ -12,10 +12,7 @@ var searchLibraryRecursive = require("../libsearch");
|
||||
var mdNav = require("../mdNav");
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
"processDocs": processDocs
|
||||
}
|
||||
|
||||
var angFilenameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))\.ts/;
|
||||
@@ -34,6 +31,14 @@ var adfLibNames = ["core", "content-services", "insights", "process-services"];
|
||||
|
||||
var statusIcons;
|
||||
|
||||
|
||||
function processDocs(mdCache, aggData, _errorMessages) {
|
||||
initPhase(aggData);
|
||||
readPhase(mdCache, aggData);
|
||||
aggPhase(aggData);
|
||||
}
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
statusIcons = aggData.config["statusIcons"] || {};
|
||||
aggData.stoplist = makeStoplist(aggData.config);
|
||||
@@ -45,7 +50,16 @@ function initPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
function readPhase(mdCache, aggData) {
|
||||
var pathnames = Object.keys(mdCache);
|
||||
|
||||
pathnames.forEach(pathname => {
|
||||
getFileData(mdCache[pathname].mdInTree, pathname, aggData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getFileData(tree, pathname, aggData) {
|
||||
var itemName = path.basename(pathname, ".md");
|
||||
|
||||
// Look for the first paragraph in the file by skipping other items.
|
||||
@@ -149,11 +163,6 @@ function aggPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Create a stoplist of regular expressions.
|
||||
function makeStoplist(config) {
|
||||
var listExpressions = config.undocStoplist;
|
||||
@@ -281,7 +290,7 @@ function makeMDDocumentedTableRow(docItem, forSubFolder) {
|
||||
}
|
||||
|
||||
var srcFileLink = unist.makeLink(unist.makeText("Source"), srcPath);
|
||||
var desc = docItem.briefDesc;
|
||||
var desc = JSON.parse(JSON.stringify(docItem.briefDesc));
|
||||
|
||||
removeBriefDescLinks(desc);
|
||||
|
||||
@@ -401,5 +410,6 @@ function removeBriefDescLinks(desc) {
|
||||
links.forEach(link => {
|
||||
link.item.type = "text";
|
||||
link.item.value = link.item.children[0].value;
|
||||
link.item.children = null;
|
||||
});
|
||||
}
|
||||
+15
-8
@@ -17,15 +17,18 @@ const maxTocHeadingDepth = 3;
|
||||
var templateFolder = path.resolve("tools", "doc", "templates");
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
"processDocs": processDocs
|
||||
}
|
||||
|
||||
|
||||
function processDocs(mdCache, aggData, errorMessages) {
|
||||
var pathnames = Object.keys(mdCache);
|
||||
|
||||
pathnames.forEach(pathname => {
|
||||
updateFile(mdCache[pathname].mdOutTree, pathname, aggData, errorMessages);
|
||||
});
|
||||
}
|
||||
|
||||
function initPhase(aggData) {}
|
||||
function readPhase(tree, pathname, aggData) {}
|
||||
function aggPhase(aggData) {}
|
||||
|
||||
|
||||
// Find an existing Contents section or add a new empty one if needed.
|
||||
@@ -80,7 +83,11 @@ function establishContentsSection(mdTree) {
|
||||
return numTocHeadings;
|
||||
}
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
|
||||
|
||||
|
||||
|
||||
function updateFile(tree, pathname, _aggData, _errorMessages) {
|
||||
if (path.basename(pathname, ".md").match(/README|versionIndex/)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,26 @@ var nameExceptions;
|
||||
var undocMethodNames = {
|
||||
"ngOnChanges": 1
|
||||
};
|
||||
function processDocs(mdCache, aggData, _errorMessages) {
|
||||
initPhase(aggData);
|
||||
var pathnames = Object.keys(mdCache);
|
||||
var internalErrors;
|
||||
pathnames.forEach(function (pathname) {
|
||||
internalErrors = [];
|
||||
updateFile(mdCache[pathname].mdOutTree, pathname, aggData, internalErrors);
|
||||
if (internalErrors.length > 0) {
|
||||
showErrors(pathname, internalErrors);
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.processDocs = processDocs;
|
||||
function showErrors(filename, errorMessages) {
|
||||
console.log(filename);
|
||||
errorMessages.forEach(function (message) {
|
||||
console.log(" " + message);
|
||||
});
|
||||
console.log("");
|
||||
}
|
||||
var PropInfo = /** @class */ (function () {
|
||||
function PropInfo(rawProp) {
|
||||
var _this = this;
|
||||
@@ -189,14 +209,7 @@ function initPhase(aggData) {
|
||||
}));
|
||||
aggData.projData = app.convert(sources);
|
||||
}
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
}
|
||||
exports.readPhase = readPhase;
|
||||
function aggPhase(aggData) {
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
function updatePhase(tree, pathname, aggData, errorMessages) {
|
||||
function updateFile(tree, pathname, aggData, errorMessages) {
|
||||
var compName = angNameToClassName(path.basename(pathname, ".md"));
|
||||
var classRef = aggData.projData.findReflectionByName(compName);
|
||||
if (!classRef) {
|
||||
@@ -232,7 +245,6 @@ function updatePhase(tree, pathname, aggData, errorMessages) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
function initialCap(str) {
|
||||
return str[0].toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,33 @@ let undocMethodNames = {
|
||||
};
|
||||
|
||||
|
||||
export function processDocs(mdCache, aggData, _errorMessages) {
|
||||
initPhase(aggData);
|
||||
|
||||
let pathnames = Object.keys(mdCache);
|
||||
let internalErrors;
|
||||
|
||||
pathnames.forEach(pathname => {
|
||||
internalErrors = [];
|
||||
updateFile(mdCache[pathname].mdOutTree, pathname, aggData, internalErrors);
|
||||
|
||||
if (internalErrors.length > 0) {
|
||||
showErrors(pathname, internalErrors);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function showErrors(filename, errorMessages) {
|
||||
console.log(filename);
|
||||
|
||||
errorMessages.forEach(message => {
|
||||
console.log(" " + message);
|
||||
});
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
class PropInfo {
|
||||
name: string;
|
||||
type: string;
|
||||
@@ -258,7 +285,7 @@ class ComponentInfo {
|
||||
}
|
||||
|
||||
|
||||
export function initPhase(aggData) {
|
||||
function initPhase(aggData) {
|
||||
nameExceptions = aggData.config.typeNameExceptions;
|
||||
|
||||
let app = new Application({
|
||||
@@ -276,15 +303,9 @@ export function initPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {
|
||||
}
|
||||
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData, errorMessages) {
|
||||
function updateFile(tree, pathname, aggData, errorMessages) {
|
||||
let compName = angNameToClassName(path.basename(pathname, ".md"));
|
||||
let classRef = aggData.projData.findReflectionByName(compName);
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ var unist = require("../unistHelpers");
|
||||
var tutFolder = path.resolve("docs", "tutorials");
|
||||
var templateFolder = path.resolve("tools", "doc", "templates");
|
||||
var userGuideFolder = path.resolve("docs", "user-guide");
|
||||
function initPhase(aggData) { }
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) { }
|
||||
exports.readPhase = readPhase;
|
||||
function processDocs(tree, pathname, aggData, errorMessages) {
|
||||
aggPhase(aggData);
|
||||
}
|
||||
exports.processDocs = processDocs;
|
||||
function aggPhase(aggData) {
|
||||
var indexDocData = getIndexDocData();
|
||||
var templateName = path.resolve(templateFolder, "tutIndex.ejs");
|
||||
@@ -33,11 +33,6 @@ function aggPhase(aggData) {
|
||||
});
|
||||
fs.writeFileSync(tutIndexFile, remark().use(frontMatter, { type: 'yaml', fence: '---' }).data("settings", { paddedTable: false, gfm: false }).stringify(tutIndexMD));
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
function getIndexDocData() {
|
||||
var indexFile = path.resolve(userGuideFolder, "summary.json");
|
||||
var summaryArray = JSON.parse(fs.readFileSync(indexFile, "utf8"));
|
||||
|
||||
@@ -15,12 +15,12 @@ const templateFolder = path.resolve("tools", "doc", "templates");
|
||||
const userGuideFolder = path.resolve("docs", "user-guide");
|
||||
|
||||
|
||||
export function initPhase(aggData) {}
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {}
|
||||
export function processDocs(tree, pathname, aggData, errorMessages) {
|
||||
aggPhase(aggData);
|
||||
}
|
||||
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
function aggPhase(aggData) {
|
||||
let indexDocData = getIndexDocData();
|
||||
|
||||
let templateName = path.resolve(templateFolder, "tutIndex.ejs");
|
||||
@@ -46,10 +46,6 @@ export function aggPhase(aggData) {
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function getIndexDocData() {
|
||||
let indexFile = path.resolve(userGuideFolder, "summary.json");
|
||||
|
||||
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var typedoc_1 = require("typedoc");
|
||||
var ProgressBar = require("progress");
|
||||
var unist = require("../unistHelpers");
|
||||
var ngHelpers = require("../ngHelpers");
|
||||
var includedNodeTypes = [
|
||||
@@ -13,6 +14,21 @@ var includedNodeTypes = [
|
||||
var docFolder = path.resolve("docs");
|
||||
var adfLibNames = ["core", "content-services", "insights", "process-services"];
|
||||
var externalNameLinks;
|
||||
function processDocs(mdCache, aggData, errorMessages) {
|
||||
initPhase(aggData);
|
||||
var pathnames = Object.keys(mdCache);
|
||||
var progress = new ProgressBar("Processing: [:bar] (:current/:total)", {
|
||||
total: pathnames.length,
|
||||
width: 50,
|
||||
clear: true
|
||||
});
|
||||
pathnames.forEach(function (pathname) {
|
||||
updateFile(mdCache[pathname].mdOutTree, pathname, aggData, errorMessages);
|
||||
progress.tick();
|
||||
progress.render();
|
||||
});
|
||||
}
|
||||
exports.processDocs = processDocs;
|
||||
function initPhase(aggData) {
|
||||
externalNameLinks = aggData.config.externalNameLinks;
|
||||
aggData.docFiles = {};
|
||||
@@ -36,13 +52,7 @@ function initPhase(aggData) {
|
||||
});
|
||||
//console.log(JSON.stringify(aggData.nameLookup));
|
||||
}
|
||||
exports.initPhase = initPhase;
|
||||
function readPhase(tree, pathname, aggData) { }
|
||||
exports.readPhase = readPhase;
|
||||
function aggPhase(aggData) {
|
||||
}
|
||||
exports.aggPhase = aggPhase;
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
function updateFile(tree, pathname, aggData, errorMessages) {
|
||||
traverseMDTree(tree);
|
||||
return true;
|
||||
function traverseMDTree(node) {
|
||||
@@ -86,7 +96,6 @@ function updatePhase(tree, pathname, aggData) {
|
||||
*/
|
||||
}
|
||||
}
|
||||
exports.updatePhase = updatePhase;
|
||||
var SplitNameNode = /** @class */ (function () {
|
||||
function SplitNameNode(key, value) {
|
||||
if (key === void 0) { key = ""; }
|
||||
|
||||
@@ -18,6 +18,8 @@ import {
|
||||
} from "typedoc";
|
||||
import { CommentTag } from "typedoc/dist/lib/models";
|
||||
|
||||
import * as ProgressBar from "progress";
|
||||
|
||||
import * as unist from "../unistHelpers";
|
||||
import * as ngHelpers from "../ngHelpers";
|
||||
import { match } from "minimatch";
|
||||
@@ -34,7 +36,26 @@ const adfLibNames = ["core", "content-services", "insights", "process-services"]
|
||||
|
||||
let externalNameLinks;
|
||||
|
||||
export function initPhase(aggData) {
|
||||
export function processDocs(mdCache, aggData, errorMessages) {
|
||||
initPhase(aggData);
|
||||
|
||||
var pathnames = Object.keys(mdCache);
|
||||
|
||||
let progress = new ProgressBar("Processing: [:bar] (:current/:total)", {
|
||||
total: pathnames.length,
|
||||
width: 50,
|
||||
clear: true
|
||||
});
|
||||
|
||||
pathnames.forEach(pathname => {
|
||||
updateFile(mdCache[pathname].mdOutTree, pathname, aggData, errorMessages);
|
||||
progress.tick();
|
||||
progress.render();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
externalNameLinks = aggData.config.externalNameLinks;
|
||||
aggData.docFiles = {};
|
||||
aggData.nameLookup = new SplitNameLookup();
|
||||
@@ -64,15 +85,10 @@ export function initPhase(aggData) {
|
||||
//console.log(JSON.stringify(aggData.nameLookup));
|
||||
}
|
||||
|
||||
export function readPhase(tree, pathname, aggData) {}
|
||||
|
||||
|
||||
export function aggPhase(aggData) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function updatePhase(tree, pathname, aggData) {
|
||||
function updateFile(tree, pathname, aggData, errorMessages) {
|
||||
traverseMDTree(tree);
|
||||
return true;
|
||||
|
||||
|
||||
@@ -14,10 +14,7 @@ var ngHelpers = require("../ngHelpers");
|
||||
|
||||
|
||||
module.exports = {
|
||||
"initPhase": initPhase,
|
||||
"readPhase": readPhase,
|
||||
"aggPhase": aggPhase,
|
||||
"updatePhase": updatePhase
|
||||
"processDocs": processDocs
|
||||
}
|
||||
|
||||
var angFilenameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))\.ts/;
|
||||
@@ -30,12 +27,29 @@ var initialVersion = "v2.0.0";
|
||||
|
||||
var templateFolder = path.resolve("tools", "doc", "templates");
|
||||
|
||||
|
||||
function processDocs(mdCache, aggData, errorMessages) {
|
||||
initPhase(aggData);
|
||||
readPhase(mdCache, aggData);
|
||||
aggPhase(aggData);
|
||||
}
|
||||
|
||||
|
||||
function initPhase(aggData) {
|
||||
aggData.versions = { "v2.0.0":[] };
|
||||
}
|
||||
|
||||
|
||||
function readPhase(tree, pathname, aggData) {
|
||||
function readPhase(mdCache, aggData) {
|
||||
var pathnames = Object.keys(mdCache);
|
||||
|
||||
pathnames.forEach(pathname => {
|
||||
getFileData(mdCache[pathname].mdInTree, pathname, aggData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getFileData(tree, pathname, aggData) {
|
||||
var compName = pathname;
|
||||
var angNameRegex = /([a-zA-Z0-9\-]+)\.((component)|(directive)|(model)|(pipe)|(service)|(widget))/;
|
||||
|
||||
@@ -121,8 +135,3 @@ function aggPhase(aggData) {
|
||||
|
||||
fs.writeFileSync(histFilePath, remark().use(frontMatter, {type: 'yaml', fence: '---'}).data("settings", {paddedTable: false, gfm: false}).stringify(histFileTree));
|
||||
}
|
||||
|
||||
|
||||
function updatePhase(tree, pathname, aggData) {
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user