[ADF-4858] Make sure process-services works with ng commands (#5067)

* Process-services:
Making sure you can run
ng build process-services
ng test process-services

* Fix the path of the styles

* move the file in the right place
This commit is contained in:
Maurizio Vitale
2019-09-20 09:47:17 +01:00
committed by Eugenio Romano
parent 90b2cee70d
commit cd7e21a23d
283 changed files with 1324 additions and 332 deletions

View File

@@ -0,0 +1,56 @@
<div class="menu-container" *ngIf="!isEmpty()">
<mat-list *ngIf="isList()" class="adf-app-list">
<mat-list-item class="adf-app-list-item" (click)="selectApp(app)" (keyup.enter)="selectApp(app)" *ngFor="let app of appList" tabindex="0" role="button" title="{{app.name}}">
<mat-icon matListIcon>touch_app</mat-icon>
<span matLine>{{getAppName(app) | async}}</span>
</mat-list-item>
</mat-list>
<div fxLayout="row wrap" *ngIf="isGrid()" class="adf-app-listgrid">
<div *ngFor="let app of appList"
class="adf-app-listgrid-item"
fxFlex="33.33333%" fxFlex.lt-md="50%" fxFlex.lt-sm="100%">
<mat-card tabindex="0"
fxLayout="column"
role="button"
class="adf-app-listgrid-item-card"
title="{{getAppName(app) | async}}"
[ngClass]="[getTheme(app)]"
(click)="selectApp(app)"
(keyup.enter)="selectApp(app)">
<div class="adf-app-listgrid-item-card-logo">
<mat-icon class="adf-app-listgrid-item-card-logo-icon">{{getBackgroundIcon(app)}}</mat-icon>
</div>
<div mat-card-title class="adf-app-listgrid-item-card-title">
<h1>{{getAppName(app) | async}}</h1>
</div>
<mat-card-subtitle class="adf-app-listgrid-item-card-subtitle" fxFlex="1 0 auto">
<div class="adf-line-clamp">{{app.description}}</div>
</mat-card-subtitle>
<mat-card-actions class="adf-app-listgrid-item-card-actions">
<mat-icon class="adf-app-listgrid-item-card-actions-icon" *ngIf="isSelected(app.id)">done</mat-icon>
</mat-card-actions>
</mat-card>
</div>
</div>
</div>
<ng-container *ngIf="isLoading(); else empty">
<div class="adf-app-list-spinner">
<mat-spinner></mat-spinner>
</div>
</ng-container>
<ng-template #empty>
<div class="adf-app-list-empty" *ngIf="isEmpty()">
<ng-content select="adf-custom-empty-content" *ngIf="hasEmptyCustomContentTemplate; else defaultEmptyTemplate" class="adf-custom-empty-template"></ng-content>
<ng-template #defaultEmptyTemplate>
<adf-empty-content
icon="apps"
[title]="'ADF_TASK_LIST.APPS.TITLE' | translate"
[subtitle]="'ADF_TASK_LIST.APPS.SUBTITLE' | translate">
</adf-empty-content>
</ng-template>
</div>
</ng-template>

View File

@@ -0,0 +1,137 @@
@mixin adf-apps-theme($theme) {
:host {
width: 100%;
}
.adf-app-list-item {
cursor: pointer;
}
$tile-themes: (
theme-1: (bg: #269abc, color: #168aac),
theme-2: (bg: #7da9b0, color: #6d99a0),
theme-3: (bg: #7689ab, color: #66799b),
theme-4: (bg: #c74e3e, color: #b73e2e),
theme-5: (bg: #fab96c, color: #eaa95c),
theme-6: (bg: #759d4c, color: #658d3c),
theme-7: (bg: #b1b489, color: #a1a479),
theme-8: (bg: #a17299, color: #916289),
theme-9: (bg: #696c67, color: #595c57),
theme-10: (bg: #cabb33, color: #baab23)
);
.adf-app-list-spinner, .adf-app-list-empty {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 85vh;
.mat-spinner {
margin: 0 auto;
}
}
.adf-app-listgrid {
padding: 8px;
&-item {
outline: none;
padding: 8px;
box-sizing: border-box;
&-card {
@for $i from 1 through 10 {
&.theme-#{$i} {
$tile-theme: map-get($tile-themes, theme-#{$i});
background-color: map-get($tile-theme, bg);
}
}
outline: none;
transition:
transform 280ms cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
min-height: 200px;
padding: 0 !important;
&:hover {
box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12),
0 5px 5px -3px rgba(0, 0, 0, 0.2);
cursor: pointer;
transform: scale(1.015);
}
&-logo {
position: absolute;
right: 20px;
top: 20px;
padding: 16px;
z-index: 9;
&-icon {
font-size: 70px;
width: 1em !important;
height: 1em !important;
@for $i from 1 through 10 {
.theme-#{$i} & {
$tile-theme: map-get($tile-themes, theme-#{$i});
color: map-get($tile-theme, color);
}
}
}
}
&-title {
padding: 16px;
margin-bottom: 0 !important;
z-index: 9999;
h1 {
color: white;
width: 80%;
font-size: 24px;
margin: 0;
line-height: normal;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
&-subtitle {
color: white;
z-index: 9999;
padding: 16px;
.adf-line-clamp {
@include adf-line-clamp(1.25, 3);
}
}
&-actions {
padding: 0 16px 16px !important;
border-top: 1px solid rgba(0, 0, 0, 0.1);
min-height: 48px;
box-sizing: border-box;
&-icon {
color: #e9f1f3;
}
&.mat-card-actions {
margin-left: 0;
margin-right: 0;
&:last-child {
margin-bottom: 0 !important;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,280 @@
/*!
* @license
* Copyright 2019 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 { DebugElement, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AppsProcessService, setupTestBed } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs';
import { defaultApp, deployedApps, nonDeployedApps } from '../mock/apps-list.mock';
import { AppsListComponent } from './apps-list.component';
import { ProcessTestingModule } from '../testing/process.testing.module';
describe('AppsListComponent', () => {
let component: AppsListComponent;
let fixture: ComponentFixture<AppsListComponent>;
let debugElement: DebugElement;
let service: AppsProcessService;
let getAppsSpy: jasmine.Spy;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(() => {
fixture = TestBed.createComponent(AppsListComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
service = TestBed.get(AppsProcessService);
getAppsSpy = spyOn(service, 'getDeployedApplications').and.returnValue(of(deployedApps));
});
it('should define layoutType with the default value', () => {
component.layoutType = '';
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
});
it('should load apps on init', () => {
fixture.detectChanges();
expect(getAppsSpy).toHaveBeenCalled();
});
it('loading should be false by default', () => {
expect(component.loading).toBeFalsy();
});
it('should show the loading spinner when the apps are loading', async(() => {
component.loading = true;
fixture.detectChanges();
fixture.whenStable().then(() => {
const loadingSpinner = fixture.nativeElement.querySelector('mat-spinner');
expect(loadingSpinner).toBeDefined();
});
}));
it('should show the apps filtered by defaultAppId', () => {
component.filtersAppId = [{defaultAppId: 'fake-app-1'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
});
it('should show the apps filtered by deploymentId', () => {
component.filtersAppId = [{deploymentId: '4'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].deploymentId).toEqual('4');
});
it('should show the apps filtered by name', () => {
component.filtersAppId = [{name: 'App5'}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].name).toEqual('App5');
});
it('should show the apps filtered by id', () => {
component.filtersAppId = [{id: 6}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(1);
expect(component.appList[0].id).toEqual(6);
});
it('should show the apps filtered by modelId', () => {
component.filtersAppId = [{modelId: 66}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(2);
expect(component.appList[0].modelId).toEqual(66);
});
it('should show the apps filtered by tenantId', () => {
component.filtersAppId = [{tenantId: 9}];
fixture.detectChanges();
expect(component.isEmpty()).toBe(false);
expect(component.appList).toBeDefined();
expect(component.appList.length).toEqual(2);
expect(component.appList[0].tenantId).toEqual(9);
});
it('should emit an error when an error occurs loading apps', () => {
const emitSpy = spyOn(component.error, 'emit');
getAppsSpy.and.returnValue(throwError({}));
fixture.detectChanges();
expect(emitSpy).toHaveBeenCalled();
});
describe('internationalization', () => {
it('should provide a translation for the default application name, when app name is not provided', () => {
const appDataMock = {
defaultAppId: 'tasks',
name: null
};
component.getAppName(appDataMock).subscribe((name) => {
expect(name).toBe('ADF_TASK_LIST.APPS.TASK_APP_NAME');
});
});
it('should provide the application name, when it exists', () => {
const appDataMock = {
defaultAppId: 'uiu',
name: 'the-name'
};
component.getAppName(appDataMock).subscribe((name) => {
expect(name).toBe(appDataMock.name);
});
});
});
describe('layout', () => {
it('should display a grid by default', () => {
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
expect(component.isList()).toBe(false);
});
it('should display a grid when configured to', () => {
component.layoutType = AppsListComponent.LAYOUT_GRID;
fixture.detectChanges();
expect(component.isGrid()).toBe(true);
expect(component.isList()).toBe(false);
});
it('should display a list when configured to', () => {
component.layoutType = AppsListComponent.LAYOUT_LIST;
fixture.detectChanges();
expect(component.isGrid()).toBe(false);
expect(component.isList()).toBe(true);
});
it('should throw an exception on init if unknown type configured', () => {
component.layoutType = 'unknown';
expect(component.ngOnInit).toThrowError();
});
});
describe('display apps', () => {
it('should display all deployed apps', () => {
getAppsSpy.and.returnValue(of(deployedApps));
fixture.detectChanges();
expect(debugElement.queryAll(By.css('h1')).length).toBe(6);
});
it('should not display apps that are not deployed', () => {
getAppsSpy.and.returnValue(of(nonDeployedApps));
fixture.detectChanges();
expect(debugElement.queryAll(By.css('h1')).length).toBe(0);
});
it('should display default app', () => {
getAppsSpy.and.returnValue(of(defaultApp));
fixture.detectChanges();
expect(debugElement.queryAll(By.css('h1')).length).toBe(1);
});
});
describe('select apps', () => {
beforeEach(() => {
getAppsSpy.and.returnValue(of(deployedApps));
fixture.detectChanges();
});
it('should initially have no app selected', () => {
const selectedEls = debugElement.queryAll(By.css('.selectedIcon'));
expect(selectedEls.length).toBe(0);
});
it('should emit a click event when app selected', () => {
spyOn(component.appClick, 'emit');
component.selectApp(deployedApps[1]);
expect(component.appClick.emit).toHaveBeenCalledWith(deployedApps[1]);
});
it('should have one app shown as selected after app selected', () => {
component.selectApp(deployedApps[1]);
fixture.detectChanges();
const selectedEls = debugElement.queryAll(By.css('.adf-app-listgrid-item-card-actions-icon'));
expect(selectedEls.length).toBe(1);
});
it('should have the correct app shown as selected after app selected', () => {
component.selectApp(deployedApps[1]);
fixture.detectChanges();
const appEls = debugElement.queryAll(By.css('.adf-app-listgrid > div'));
expect(appEls[1].query(By.css('.adf-app-listgrid-item-card-actions-icon'))).not.toBeNull();
});
});
});
@Component({
template: `
<adf-apps>
<adf-custom-empty-content>
<p id="custom-id">No Apps</p>
</adf-custom-empty-content>
</adf-apps>
`
})
class CustomEmptyAppListTemplateComponent {
}
describe('Custom CustomEmptyAppListTemplateComponent', () => {
let fixture: ComponentFixture<CustomEmptyAppListTemplateComponent>;
setupTestBed({
imports: [ProcessTestingModule],
declarations: [CustomEmptyAppListTemplateComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
});
beforeEach(() => {
fixture = TestBed.createComponent(CustomEmptyAppListTemplateComponent);
});
afterEach(() => {
fixture.destroy();
});
it('should render the custom no-apps template', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
const title: any = fixture.debugElement.queryAll(By.css('#custom-id'));
expect(title.length).toBe(1);
expect(title[0].nativeElement.innerText).toBe('No Apps');
});
}));
});

View File

@@ -0,0 +1,222 @@
/*!
* @license
* Copyright 2019 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 { AppsProcessService, TranslationService, CustomEmptyContentTemplateDirective } from '@alfresco/adf-core';
import { AfterContentInit, Component, EventEmitter, Input, OnInit, Output, ContentChild, OnDestroy } from '@angular/core';
import { Observable, Observer, of, Subject } from 'rxjs';
import { AppDefinitionRepresentationModel } from '../task-list';
import { IconModel } from './icon.model';
import { share, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-apps',
templateUrl: 'apps-list.component.html',
styleUrls: ['./apps-list.component.scss']
})
export class AppsListComponent implements OnInit, AfterContentInit, OnDestroy {
public static LAYOUT_LIST: string = 'LIST';
public static LAYOUT_GRID: string = 'GRID';
public static DEFAULT_TASKS_APP: string = 'tasks';
public static DEFAULT_TASKS_APP_NAME: string = 'ADF_TASK_LIST.APPS.TASK_APP_NAME';
public static DEFAULT_TASKS_APP_THEME: string = 'theme-2';
public static DEFAULT_TASKS_APP_ICON: string = 'glyphicon-asterisk';
public static DEFAULT_TASKS_APP_MATERIAL_ICON: string = 'favorite_border';
@ContentChild(CustomEmptyContentTemplateDirective)
emptyCustomContent: CustomEmptyContentTemplateDirective;
/** (**required**) Defines the layout of the apps. There are two possible
* values, "GRID" and "LIST".
*/
@Input()
layoutType: string = AppsListComponent.LAYOUT_GRID;
/** Provides a way to filter the apps to show. */
@Input()
filtersAppId: any[];
/** Emitted when an app entry is clicked. */
@Output()
appClick: EventEmitter<AppDefinitionRepresentationModel> = new EventEmitter<AppDefinitionRepresentationModel>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
private appsObserver: Observer<AppDefinitionRepresentationModel>;
apps$: Observable<AppDefinitionRepresentationModel>;
currentApp: AppDefinitionRepresentationModel;
appList: AppDefinitionRepresentationModel [] = [];
private iconsMDL: IconModel;
loading: boolean = false;
hasEmptyCustomContentTemplate: boolean = false;
private onDestroy$ = new Subject<boolean>();
constructor(
private appsProcessService: AppsProcessService,
private translationService: TranslationService) {
this.apps$ = new Observable<AppDefinitionRepresentationModel>((observer) => this.appsObserver = observer)
.pipe(share());
}
ngOnInit() {
if (!this.isValidType()) {
this.setDefaultLayoutType();
}
this.apps$
.pipe(takeUntil(this.onDestroy$))
.subscribe((app: any) => this.appList.push(app));
this.iconsMDL = new IconModel();
this.load();
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngAfterContentInit() {
if (this.emptyCustomContent) {
this.hasEmptyCustomContentTemplate = true;
}
}
private load() {
this.loading = true;
this.appsProcessService.getDeployedApplications()
.subscribe(
(res: AppDefinitionRepresentationModel[]) => {
this.filterApps(res).forEach((app: AppDefinitionRepresentationModel) => {
if (this.isDefaultApp(app)) {
app.theme = AppsListComponent.DEFAULT_TASKS_APP_THEME;
app.icon = AppsListComponent.DEFAULT_TASKS_APP_ICON;
this.appsObserver.next(app);
} else if (app.deploymentId) {
this.appsObserver.next(app);
}
this.loading = false;
});
},
(err) => {
this.error.emit(err);
this.loading = false;
}
);
}
isDefaultApp(app) {
return app.defaultAppId === AppsListComponent.DEFAULT_TASKS_APP;
}
getAppName(app) {
return this.isDefaultApp(app)
? this.translationService.get(AppsListComponent.DEFAULT_TASKS_APP_NAME)
: of(app.name);
}
/**
* Pass the selected app as next
* @param app
*/
public selectApp(app: AppDefinitionRepresentationModel) {
this.currentApp = app;
this.appClick.emit(app);
}
/**
* Return true if the appId is the current app
* @param appId
*/
isSelected(appId: number): boolean {
return (this.currentApp !== undefined && appId === this.currentApp.id);
}
private filterApps(apps: AppDefinitionRepresentationModel []): AppDefinitionRepresentationModel[] {
const filteredApps: AppDefinitionRepresentationModel[] = [];
if (this.filtersAppId) {
apps.filter((app: AppDefinitionRepresentationModel) => {
this.filtersAppId.forEach((filter) => {
if (app.defaultAppId === filter.defaultAppId ||
app.deploymentId === filter.deploymentId ||
app.name === filter.name ||
app.id === filter.id ||
app.modelId === filter.modelId ||
app.tenantId === filter.tenantId) {
filteredApps.push(app);
}
});
});
} else {
return apps;
}
return filteredApps;
}
/**
* Check if the value of the layoutType property is an allowed value
*/
isValidType(): boolean {
if (this.layoutType && (this.layoutType === AppsListComponent.LAYOUT_LIST || this.layoutType === AppsListComponent.LAYOUT_GRID)) {
return true;
}
return false;
}
/**
* Assign the default value to LayoutType
*/
setDefaultLayoutType(): void {
this.layoutType = AppsListComponent.LAYOUT_GRID;
}
/**
* Return true if the layout type is LIST
*/
isList(): boolean {
return this.layoutType === AppsListComponent.LAYOUT_LIST;
}
/**
* Return true if the layout type is GRID
*/
isGrid(): boolean {
return this.layoutType === AppsListComponent.LAYOUT_GRID;
}
isEmpty(): boolean {
return this.appList.length === 0;
}
isLoading(): boolean {
return this.loading;
}
getTheme(app: AppDefinitionRepresentationModel): string {
return app.theme ? app.theme : '';
}
getBackgroundIcon(app: AppDefinitionRepresentationModel): string {
return this.iconsMDL.mapGlyphiconToMaterialDesignIcons(app.icon);
}
}

View File

@@ -0,0 +1,47 @@
/*!
* @license
* Copyright 2019 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 { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { AppsListComponent } from './apps-list.component';
import { SelectAppsDialogComponent } from './select-apps-dialog-component';
@NgModule({
imports: [
CommonModule,
MaterialModule,
FlexLayoutModule,
CoreModule
],
declarations: [
AppsListComponent,
SelectAppsDialogComponent
],
exports: [
AppsListComponent,
SelectAppsDialogComponent
],
entryComponents: [
SelectAppsDialogComponent
]
})
export class AppsListModule {
}

View File

@@ -0,0 +1,164 @@
/*!
* @license
* Copyright 2019 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.
*/
/* spellchecker: disable */
export class IconModel {
public static DEFAULT_TASKS_APP_MATERIAL_ICON: string = 'favorite_border';
private iconsMDL: Map<string, string>;
constructor() {
this.initIconsMDL();
}
mapGlyphiconToMaterialDesignIcons(icon: string) {
return this.iconsMDL.get(icon) ? this.iconsMDL.get(icon) : IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON;
}
/**
* Map all the bootstrap glyphicon icons with Material design material icon
*/
initIconsMDL() {
this.iconsMDL = new Map<string, string>();
this.iconsMDL.set('glyphicon-asterisk', 'ac_unit');
this.iconsMDL.set('glyphicon-plus', 'add');
this.iconsMDL.set('glyphicon-euro', 'euro_symbol');
this.iconsMDL.set('glyphicon-cloud', 'cloud');
this.iconsMDL.set('glyphicon-envelope', 'mail');
this.iconsMDL.set('glyphicon-pencil', 'create');
this.iconsMDL.set('glyphicon-glass', 'local_bar');
this.iconsMDL.set('glyphicon-music', 'music_note');
this.iconsMDL.set('glyphicon-search', 'search');
this.iconsMDL.set('glyphicon-heart', 'favorite');
this.iconsMDL.set('glyphicon-heart-empty', 'favorite_border');
this.iconsMDL.set('glyphicon-star', 'star');
this.iconsMDL.set('glyphicon-star-empty', 'star_border');
this.iconsMDL.set('glyphicon-user', 'person');
this.iconsMDL.set('glyphicon-film', 'movie_creation');
this.iconsMDL.set('glyphicon-th-large', 'view_comfy');
this.iconsMDL.set('glyphicon-th', 'dashboard');
this.iconsMDL.set('glyphicon-th-list', 'list');
this.iconsMDL.set('glyphicon-ok', 'done');
this.iconsMDL.set('glyphicon-remove', 'cancel');
this.iconsMDL.set('glyphicon-zoom-in', 'zoom_in');
this.iconsMDL.set('glyphicon-zoom-out', 'zoom_out');
this.iconsMDL.set('glyphicon-off', 'highlight_off');
this.iconsMDL.set('glyphicon-signal', 'signal_cellular_4_bar');
this.iconsMDL.set('glyphicon-cog', 'settings');
this.iconsMDL.set('glyphicon-trash', 'delete');
this.iconsMDL.set('glyphicon-home', 'home');
this.iconsMDL.set('glyphicon-file', 'insert_drive_file');
this.iconsMDL.set('glyphicon-time', 'access_time');
this.iconsMDL.set('glyphicon-road', 'map');
this.iconsMDL.set('glyphicon-download-alt', 'file_download');
this.iconsMDL.set('glyphicon-download', 'file_download');
this.iconsMDL.set('glyphicon-upload', 'file_upload');
this.iconsMDL.set('glyphicon-inbox', 'inbox');
this.iconsMDL.set('glyphicon-play-circle', 'play_circle_outline');
this.iconsMDL.set('glyphicon-repeat', 'refresh');
this.iconsMDL.set('glyphicon-refresh', 'sync');
this.iconsMDL.set('glyphicon-list-alt', 'event_note');
this.iconsMDL.set('glyphicon-lock', 'lock_outline');
this.iconsMDL.set('glyphicon-flag', 'assistant_photo');
this.iconsMDL.set('glyphicon-headphones', 'headset');
this.iconsMDL.set('glyphicon-volume-up', 'volume_up');
this.iconsMDL.set('glyphicon-tag', 'local_offer');
this.iconsMDL.set('glyphicon-tags', 'local_offer');
this.iconsMDL.set('glyphicon-book', 'library_books');
this.iconsMDL.set('glyphicon-bookmark', 'collections_bookmark');
this.iconsMDL.set('glyphicon-print', 'local_printshop');
this.iconsMDL.set('glyphicon-camera', 'local_see');
this.iconsMDL.set('glyphicon-list', 'view_list');
this.iconsMDL.set('glyphicon-facetime-video', 'video_call');
this.iconsMDL.set('glyphicon-picture', 'photo');
this.iconsMDL.set('glyphicon-map-marker', 'add_location');
this.iconsMDL.set('glyphicon-adjust', 'brightness_4');
this.iconsMDL.set('glyphicon-tint', 'invert_colors');
this.iconsMDL.set('glyphicon-edit', 'edit');
this.iconsMDL.set('glyphicon-share', 'share');
this.iconsMDL.set('glyphicon-check', 'assignment_turned_in');
this.iconsMDL.set('glyphicon-move', 'open_with');
this.iconsMDL.set('glyphicon-play', 'play_arrow');
this.iconsMDL.set('glyphicon-eject', 'eject');
this.iconsMDL.set('glyphicon-plus-sign', 'add_circle');
this.iconsMDL.set('glyphicon-minus-sign', 'remove_circle');
this.iconsMDL.set('glyphicon-remove-sign', 'cancel');
this.iconsMDL.set('glyphicon-ok-sign', 'check_circle');
this.iconsMDL.set('glyphicon-question-sign', 'help');
this.iconsMDL.set('glyphicon-info-sign', 'info');
this.iconsMDL.set('glyphicon-screenshot', 'flare');
this.iconsMDL.set('glyphicon-remove-circle', 'cancel');
this.iconsMDL.set('glyphicon-ok-circle', 'add_circle');
this.iconsMDL.set('glyphicon-ban-circle', 'block');
this.iconsMDL.set('glyphicon-share-alt', 'redo');
this.iconsMDL.set('glyphicon-exclamation-sign', 'error');
this.iconsMDL.set('glyphicon-gift', 'giftcard');
this.iconsMDL.set('glyphicon-leaf', 'spa');
this.iconsMDL.set('glyphicon-fire', 'whatshot');
this.iconsMDL.set('glyphicon-eye-open', 'remove_red_eye');
this.iconsMDL.set('glyphicon-eye-close', 'remove_red_eye');
this.iconsMDL.set('glyphicon-warning-sign', 'warning');
this.iconsMDL.set('glyphicon-plane', 'airplanemode_active');
this.iconsMDL.set('glyphicon-calendar', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-random', 'shuffle');
this.iconsMDL.set('glyphicon-comment', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-magnet', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-retweet', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-shopping-cart', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-close', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-folder-open', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hdd', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bullhorn', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-bell', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-certificate', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-up', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-thumbs-down', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-hand-left', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-globe', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-wrench', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tasks', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-filter', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-briefcase', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-dashboard', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-paperclip', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-link', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-pushpin', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-usd', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-gbp', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-sort', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-flash', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-record', 'radio_button_checked');
this.iconsMDL.set('glyphicon-save', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-open', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-saved', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-send', 'send');
this.iconsMDL.set('glyphicon-floppy-disk', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-credit-card', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cutlery', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-earphone', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-phone-alt', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tower', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-stats', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-download', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-cloud-upload', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-conifer', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-tree-deciduous', IconModel.DEFAULT_TASKS_APP_MATERIAL_ICON);
this.iconsMDL.set('glyphicon-align-left', 'format_align_left');
}
}

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './public-api';

View File

@@ -0,0 +1,21 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './apps-list.component';
export * from './select-apps-dialog-component';
export * from './apps-list.module';

View File

@@ -0,0 +1,13 @@
<header mat-dialog-title id="adf-selet-app-dialog-title">{{'APP.DIALOG.TITLE' | translate}}</header>
<section mat-dialog-content>
<mat-select id="adf-selet-app-dialog-dropdown" placeholder="{{'APP.DIALOG.LIST' | translate}}" [(value)]="selectedProcess" >
<mat-option *ngFor="let currentProcessApp of processApps" [value]="currentProcessApp">
{{ currentProcessApp.name }}
</mat-option>
</mat-select>
</section>
<footer mat-dialog-actions fxLayout="row" fxLayoutAlign="end center">
<button mat-button (click)="onStart()">{{'APP.DIALOG.START' | translate}}</button>
</footer>

View File

@@ -0,0 +1,117 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ComponentFixture } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { MatDialog } from '@angular/material';
import { OverlayContainer } from '@angular/cdk/overlay';
import { AppsProcessService, setupTestBed } from '@alfresco/adf-core';
import { deployedApps } from '../mock/apps-list.mock';
import { of } from 'rxjs';
import { SelectAppsDialogComponent } from './select-apps-dialog-component';
import { ProcessTestingModule } from '../testing/process.testing.module';
@Component({
selector: 'adf-dialog-test',
template: ''
})
export class DialogSelectAppTestComponent {
processId: any;
dialogRef: any;
constructor(private dialog: MatDialog) {}
startProcessAction() {
this.dialogRef = this.dialog.open(SelectAppsDialogComponent, {
width: '630px'
});
this.dialogRef.afterClosed().subscribe((selectedProcess) => {
this.processId = selectedProcess.id;
});
}
}
describe('Select app dialog', () => {
let fixture: ComponentFixture<DialogSelectAppTestComponent>;
let component: DialogSelectAppTestComponent;
const dialogRef = {
close: jasmine.createSpy('close')
};
let overlayContainerElement: HTMLElement;
let service: AppsProcessService;
setupTestBed({
imports: [ProcessTestingModule],
declarations: [DialogSelectAppTestComponent],
providers: [
AppsProcessService,
{
provide: OverlayContainer,
useFactory: () => {
overlayContainerElement = document.createElement('div');
return {
getContainerElement: () => overlayContainerElement
};
}
},
{
provide: MatDialogRef,
useValue: dialogRef
},
{
provide: MAT_DIALOG_DATA,
useValue: {}
}
]
});
beforeEach(() => {
fixture = TestBed.createComponent(DialogSelectAppTestComponent);
component = fixture.componentInstance;
service = TestBed.get(AppsProcessService);
spyOn(service, 'getDeployedApplications').and.returnValue(
of(deployedApps)
);
});
describe('Dialog', () => {
beforeEach(() => {
fixture.detectChanges();
});
it('should init title and dropdown', () => {
component.startProcessAction();
expect(
overlayContainerElement.querySelector(
'.adf-selet-app-dialog-title'
)
).toBeDefined();
expect(
overlayContainerElement.querySelector(
'.adf-selet-app-dialog-dropdown'
)
).toBeDefined();
});
});
});

View File

@@ -0,0 +1,48 @@
/*!
* @license
* Copyright 2019 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 { AppsProcessService } from '@alfresco/adf-core';
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
@Component({
selector: 'adf-select-apps-dialog',
templateUrl: 'select-apps-dialog-component.html'
})
export class SelectAppsDialogComponent {
processApps: any;
selectedProcess: any;
constructor(private appsProcessService: AppsProcessService,
public dialogRef: MatDialogRef<SelectAppsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) {
this.appsProcessService.getDeployedApplications().subscribe(
(apps: any[]) => {
this.processApps = apps.filter((currentApp) => {
return currentApp.id;
});
}
);
}
onStart(): void {
this.dialogRef.close(this.selectedProcess);
}
}

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="17.2 134.6 562 573.1" enable-background="new 17.2 134.6 562 573.1" xml:space="preserve">
<path fill="#FFFFFF" d="M298.2,421.3L219,340.4l-2.9-2.9c-45.4-46.5-119.5-46.5-164.7-0.2c-45.6,46.3-45.6,121.5,0,167.8
c45.2,46.4,119,46.4,164.4,0L298.2,421.3z"/>
<path fill="#FFFFFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6
c0-65.6,52.4-118.8,116.5-118.8H298.2z"/>
<path fill="#FFFFFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6
c0-65.6,52.4-118.8,116.5-118.8H298.2z"/>
<path fill="#FFFFFF" d="M298.2,421.2v114.3l0.2,4.2c0,65.5-52.2,119-116.5,119c-64.3,0-116.5-53.1-116.5-118.6
c0-7.3,0.8-14.4,2-21.2c45.4,32.2,108.2,27.7,148.6-13.7l82.4-83.8V421.2z"/>
<path fill="#8ABF42" d="M181.9,436.1c-56.1,0-101.6,46.5-101.6,103.8c0,57.1,45.6,103.5,101.6,103.5c56.2,0,101.7-46.4,101.7-103.5
v-4.5v-99.3H182.1H181.9z"/>
<path fill="#FFFFFF" d="M298.2,421.2l79.2,80.8l3.3,2.9c45.2,46.4,45.5,121.8,0,168.1c-45.6,46.3-119.2,46.3-164.8,0
c-45.4-46.3-45.4-121.5,0-168L298.2,421.2z"/>
<path fill="#8ABF42" d="M226.5,515.6c-39.8,40.5-39.8,106.2,0,146.6c39.6,40.5,104,40.5,143.8,0c39.6-40.4,39.6-106.1,0-146.6
l-3.3-3l-68.7-70.2l-71.7,73.1V515.6z"/>
<path fill="#FFFFFF" d="M298.2,421.2h112.2l4.1-0.2c64.4,0,116.5,53.2,116.5,118.8c0,65.6-52,118.6-116.3,118.6
c-64.3,0-116.5-53.1-116.5-118.6V421.2z"/>
<path fill="#8ABF42" d="M313.1,539.8c0,57.3,45.4,103.7,101.6,103.7c56,0,101.4-46.4,101.4-103.7c0-57.3-45.4-103.6-101.4-103.6
h-4.3h-97.4v103.3V539.8z"/>
<path fill="#FFFFFF" d="M298.2,421.2l79.2-80.9l3.1-3.1c45.4-46.3,119.2-46.5,164.6-0.2c45.4,46.4,45.4,121.5,0,167.9
c-45.4,46.4-119.2,46.4-164.6,0L298.2,421.2z"/>
<path fill="#8ABF42" d="M391.1,494.3c39.4,40.6,103.8,40.6,143.6,0c39.8-40.4,39.8-106,0-146.5c-39.8-40.5-104.1-40.5-143.6,0
l-3.3,3.2l-68.6,70.3l71.5,73L391.1,494.3z"/>
<path fill="#FFFFFF" d="M298.2,421.2V306.8v-4.3c0-65.5,51.9-118.8,116.5-118.8c64.2,0,116.1,52.9,116.1,118.6
c0,65.6-52,118.8-116.1,118.8H298.2z"/>
<path fill="#F89F31" d="M414.7,406.1c56,0,101.4-46.4,101.4-103.7c0-57.1-45.4-103.6-101.4-103.6c-56.3,0-101.8,46.5-101.8,103.6
l0.2,4.4v99.3h101.1H414.7z"/>
<path fill="#FFFFFF" d="M298.2,421.2L219,340.3l-3.1-2.9c-45.4-46.5-45.4-121.8,0-168.1c45.2-46.4,119.1-46.4,164.6,0
c45.4,46.3,45.4,121.6,0,167.9L298.2,421.2z"/>
<path fill="#0080C5" d="M370.1,327.6c39.6-40.5,39.6-106.2,0-146.6c-39.8-40.5-104-40.5-143.7,0c-39.8,40.4-39.8,106.1,0,146.6
l2.9,3.1l69,70.1l71.6-73L370.1,327.6z"/>
<path fill="#FFFFFF" d="M298.2,422.1H186.1l-4.2,0.1c-64.1,0-116.5-53.2-116.5-118.8c0-65.5,52.2-118.7,116.3-118.7
c64.3,0,116.6,53.2,116.6,118.8V422.1z"/>
<path fill="#0080C5" d="M283.5,303.5c0-57.3-45.4-103.6-101.8-103.6c-56,0-101.6,46.3-101.6,103.5c0,57.2,45.6,103.7,101.6,103.7
l4.4-0.1h97.4V303.8V303.5z"/>
<path fill="#FFFFFF" d="M298.2,422.1l-281,0.1c0-30.4,11.2-60.8,34.2-84c45.2-46.3,119-46.3,164.4,0L298.2,422.1z"/>
<path fill="#0080C5" d="M205.4,348.9l71.9,73.3h-95.5c-51.6,0-95.5,34.3-110.7,81.9c-3.1-2.7-6.4-5.5-9.3-8.7
c-39.8-40.5-39.8-106,0-146.5C101.3,308.4,165.8,308.4,205.4,348.9"/>
<path fill="#005DA9" d="M205.6,349l56.9,58l-80.9,0.2c-46.6,0-85.8-31.9-97.8-75.5c38.6-22.1,89.2-16.8,121.6,17.1L205.6,349z"/>
<path fill="#005DA9" d="M283.5,303.7l-0.1,82.1l-57.1-58.2c-32.9-33.6-38.7-84.4-17-123.8c42.7,12.2,74.2,52.2,74.2,99.8V303.7z"/>
<path fill="#005DA9" d="M312.6,386v-82.4c0-47.5,31.5-87.5,74.2-99.8c21.6,39.5,17.6,89-16.4,123.3L312.6,386z"/>
<path fill="#FFDE4F" d="M333.9,406.1l57.1-58.3c32.9-33.6,82.8-39.3,121.4-17.2c-12.2,43.5-49.4,74.8-95.3,75.6L333.9,406.1z"/>
<path fill="#48A64A" d="M333.8,436.1h80.8c46.6,0,85.8,31.7,97.8,75.4c-38.9,22.2-88.7,16.3-121.8-17.2L333.8,436.1z"/>
<path fill="#48A64A" d="M313.1,539.2v-82l57.2,58.2c32.9,33.7,38.5,84.7,16.8,124.1c-42.7-12.2-74-52.4-74-99.9V539.2z"/>
<path fill="#48A64A" d="M226.6,515.4l56.9-58l0.1,82.4c0,47.5-31.3,87.4-74,99.7c-21.6-39.5-15.8-90.4,17-123.9V515.4z"/>
<path fill="#48A64A" d="M182.4,436.1h80.4l-57,58.2c-32.8,33.5-83.1,39.3-121.7,17.3c12.1-43.7,51.4-75.5,98-75.5H182.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="566px" height="165px" viewBox="0 0 566 165" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>empty_doc_lib</title>
<desc>Created with Sketch.</desc>
<defs>
<rect id="path-1" x="5.68434189e-14" y="-1.01962883e-12" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-2">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-3" x="-4.54747351e-13" y="5.68434189e-13" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-4">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-5" x="-1.08002496e-12" y="7.81597009e-14" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-6">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-7" x="1.29318778e-12" y="9.23705556e-14" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-8">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-9" x="-2.96651592e-13" y="-7.60280727e-13" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-10">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-11" x="3.48165941e-13" y="2.27373675e-13" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-12">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-13" x="0" y="-5.40012479e-13" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-14">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
<rect id="path-15" x="0" y="0" width="78.1679389" height="78.1679389" rx="2"></rect>
<filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-16">
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.24 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter2" result="shadowBlurOuter2"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0" type="matrix" in="shadowBlurOuter2" result="shadowMatrixOuter2"></feColorMatrix>
<feMerge>
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
<feMergeNode in="shadowMatrixOuter2"></feMergeNode>
</feMerge>
</filter>
</defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="empty-folder-state-desktop" transform="translate(-37.000000, -168.000000)">
<g id="empty_doc_lib" transform="translate(38.000000, 169.000000)">
<g id="Group-5" transform="translate(241.569490, 92.634375) rotate(-355.000000) translate(-241.569490, -92.634375) translate(202.069490, 53.134375)">
<g id="Rectangle-1196-Copy-2">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
<g id="filetype_video" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="0 58.6259542 58.6259542 58.6259542 58.6259542 0 0 0"></polygon>
<path d="M39.0839695,21.9847328 L43.9694656,21.9847328 L43.9694656,17.0992366 L39.0839695,17.0992366 L39.0839695,21.9847328 Z M39.0839695,31.7557252 L43.9694656,31.7557252 L43.9694656,26.870229 L39.0839695,26.870229 L39.0839695,31.7557252 Z M39.0839695,41.5267176 L43.9694656,41.5267176 L43.9694656,36.6412214 L39.0839695,36.6412214 L39.0839695,41.5267176 Z M14.6564885,21.9847328 L19.5419847,21.9847328 L19.5419847,17.0992366 L14.6564885,17.0992366 L14.6564885,21.9847328 Z M14.6564885,31.7557252 L19.5419847,31.7557252 L19.5419847,26.870229 L14.6564885,26.870229 L14.6564885,31.7557252 Z M14.6564885,41.5267176 L19.5419847,41.5267176 L19.5419847,36.6412214 L14.6564885,36.6412214 L14.6564885,41.5267176 Z M43.9694656,7.32824427 L43.9694656,12.2137405 L39.0839695,12.2137405 L39.0839695,7.32824427 L19.5419847,7.32824427 L19.5419847,12.2137405 L14.6564885,12.2137405 L14.6564885,7.32824427 L9.77099237,7.32824427 L9.77099237,51.2977099 L14.6564885,51.2977099 L14.6564885,46.4122137 L19.5419847,46.4122137 L19.5419847,51.2977099 L39.0839695,51.2977099 L39.0839695,46.4122137 L43.9694656,46.4122137 L43.9694656,51.2977099 L48.8549618,51.2977099 L48.8549618,7.32824427 L43.9694656,7.32824427 Z" id="Fill-2" fill="#FFC107"></path>
</g>
</g>
<g id="Group-7" transform="translate(515.948329, 81.354522) rotate(-345.000000) translate(-515.948329, -81.354522) translate(476.448329, 41.854522)">
<g id="Rectangle-1196-Copy-3">
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-3"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-3"></use>
</g>
<g id="filetype_image" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="0 58.6259542 58.6259542 58.6259542 58.6259542 0 0 0"></polygon>
<path d="M20.7636031,32.9773435 L26.8704733,40.3178015 L35.4200916,29.3132214 L46.412458,43.9697099 L12.2139847,43.9697099 L20.7636031,32.9773435 Z M51.2979542,46.412458 L51.2979542,12.2139847 C51.2979542,9.51474809 49.1116947,7.32848855 46.412458,7.32848855 L12.2139847,7.32848855 C9.51474809,7.32848855 7.32848855,9.51474809 7.32848855,12.2139847 L7.32848855,46.412458 C7.32848855,49.1116947 9.51474809,51.2979542 12.2139847,51.2979542 L46.412458,51.2979542 C49.1116947,51.2979542 51.2979542,49.1116947 51.2979542,46.412458 L51.2979542,46.412458 Z" id="Fill-2" fill="#22BE73"></path>
</g>
</g>
<g id="Group-8" transform="translate(309.051884, 62.261808) rotate(-5.000000) translate(-309.051884, -62.261808) translate(269.551884, 22.761808)">
<g id="Rectangle-1196-Copy-4">
<use fill="black" fill-opacity="1" filter="url(#filter-6)" xlink:href="#path-5"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-5"></use>
</g>
<g id="filetype_googledocs" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="6.82121026e-13 58.6259542 58.6259542 58.6259542 58.6259542 -2.98427949e-13 6.82121026e-13 -2.98427949e-13"></polygon>
<g id="Group-6" transform="translate(9.770992, 4.885496)">
<path d="M7.32824427,21.9847328 L31.7557252,21.9847328 L31.7557252,19.5419847 L7.32824427,19.5419847 L7.32824427,21.9847328 Z M7.32824427,26.870229 L31.7557252,26.870229 L31.7557252,24.4274809 L7.32824427,24.4274809 L7.32824427,26.870229 Z M7.32824427,31.7557252 L31.7557252,31.7557252 L31.7557252,29.3129771 L7.32824427,29.3129771 L7.32824427,31.7557252 Z M7.32824427,36.6412214 L21.9847328,36.6412214 L21.9847328,34.1984733 L7.32824427,34.1984733 L7.32824427,36.6412214 Z M29.3129771,0 L4.88549618,0 C2.18625954,0 0.0244274809,2.18625954 0.0244274809,4.88549618 L0,43.9694656 C0,46.6687023 2.16183206,48.8549618 4.8610687,48.8549618 L34.1984733,48.8549618 C36.8977099,48.8549618 39.0839695,46.6687023 39.0839695,43.9694656 L39.0839695,9.77099237 L29.3129771,0 Z" id="Fill-2" fill="#2979FF"></path>
<polygon id="Fill-4" fill-opacity="0.5" fill="#FFFFFF" points="29.3129771 9.77099237 29.3129771 -2.84217094e-14 39.0839695 9.77099237"></polygon>
<polygon id="Fill-5" fill-opacity="0.2" fill="#000000" points="39.0839695 9.77099237 39.0839695 19.5419847 29.3129771 9.77099237"></polygon>
</g>
</g>
</g>
<g id="Group-9" transform="translate(155.408682, 49.364493) rotate(-345.000000) translate(-155.408682, -49.364493) translate(115.908682, 9.864493)">
<g id="Rectangle-1196-Copy-5">
<use fill="black" fill-opacity="1" filter="url(#filter-8)" xlink:href="#path-7"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-7"></use>
</g>
<g id="filetype_pdf" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="0 58.6259542 58.6259542 58.6259542 58.6259542 0 0 0"></polygon>
<path d="M45.1888855,25.5877863 L45.1888855,21.9187786 L37.853313,21.9187786 L37.853313,36.5923664 L41.5198779,36.5923664 L41.5198779,31.7777099 L45.1888855,31.7777099 L45.1888855,28.1087023 L41.5198779,28.1087023 L41.5198779,25.5877863 L45.1888855,25.5877863 Z M29.3696489,32.9233588 L31.7757557,32.9233588 L31.7757557,25.5877863 L29.3696489,25.5877863 L29.3696489,32.9233588 Z M35.4447634,32.9233588 L35.4447634,25.5877863 C35.4447634,24.5960305 35.1027786,23.7361832 34.4139237,23.0082443 C33.7275115,22.2827481 32.8481221,21.9187786 31.7781985,21.9187786 L25.703084,21.9187786 L25.703084,36.5923664 L31.7781985,36.5923664 C32.8481221,36.5923664 33.7275115,36.2308397 34.4139237,35.5029008 C35.1027786,34.7774046 35.4447634,33.9175573 35.4447634,32.9233588 L35.4447634,32.9233588 Z M17.1070534,28.1087023 L19.5131603,28.1087023 L19.5131603,25.5877863 L17.1070534,25.5877863 L17.1070534,28.1087023 Z M23.1821679,28.1087023 L23.1821679,25.5877863 C23.1821679,24.5960305 22.8181985,23.7361832 22.0927023,23.0082443 C21.3672061,22.2827481 20.5073588,21.9187786 19.5131603,21.9187786 L13.4380458,21.9187786 L13.4380458,36.5923664 L17.1070534,36.5923664 L17.1070534,31.7777099 L19.5131603,31.7777099 C20.5073588,31.7777099 21.3672061,31.4161832 22.0927023,30.6882443 C22.8181985,29.9627481 23.1821679,29.1029008 23.1821679,28.1087023 L23.1821679,28.1087023 Z M46.483542,7.32824427 C47.783084,7.32824427 48.9091908,7.8070229 49.8643053,8.7621374 C50.8218626,9.71725191 51.2981985,10.8433588 51.2981985,12.1429008 L51.2981985,46.3682443 C51.2981985,47.670229 50.8218626,48.8158779 49.8643053,49.8076336 C48.9091908,50.8018321 47.783084,51.2977099 46.483542,51.2977099 L12.2581985,51.2977099 C10.9586565,51.2977099 9.81300763,50.8018321 8.81880916,49.8076336 C7.82461069,48.8158779 7.32873282,47.670229 7.32873282,46.3682443 L7.32873282,12.1429008 C7.32873282,10.8433588 7.82461069,9.71725191 8.81880916,8.7621374 C9.81300763,7.8070229 10.9586565,7.32824427 12.2581985,7.32824427 L46.483542,7.32824427 Z" id="Fill-2" fill="#E91E63"></path>
</g>
</g>
<g id="Group-12" transform="translate(49.364493, 62.584254) rotate(-15.000000) translate(-49.364493, -62.584254) translate(9.864493, 23.084254)">
<g id="Rectangle-1196-Copy-7">
<use fill="black" fill-opacity="1" filter="url(#filter-10)" xlink:href="#path-9"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-9"></use>
</g>
<g id="filetype_forms" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="0 58.6259542 58.6259542 58.6259542 58.6259542 0 0 0"></polygon>
<path d="M24.4274809,24.4250382 L41.5267176,24.4250382 L41.5267176,19.539542 L24.4274809,19.539542 L24.4274809,24.4250382 Z M24.4274809,31.7532824 L41.5267176,31.7532824 L41.5267176,26.8677863 L24.4274809,26.8677863 L24.4274809,31.7532824 Z M24.4274809,39.0839695 L41.5267176,39.0839695 L41.5267176,34.1984733 L24.4274809,34.1984733 L24.4274809,39.0839695 Z M17.0992366,24.4250382 L21.9847328,24.4250382 L21.9847328,19.539542 L17.0992366,19.539542 L17.0992366,24.4250382 Z M17.0992366,31.7532824 L21.9847328,31.7532824 L21.9847328,26.8677863 L17.0992366,26.8677863 L17.0992366,31.7532824 Z M17.0992366,39.0839695 L21.9847328,39.0839695 L21.9847328,34.1984733 L17.0992366,34.1984733 L17.0992366,39.0839695 Z M43.9694656,9.77099237 L14.6564885,9.77099237 C11.9694656,9.77099237 9.77099237,11.9694656 9.77099237,14.6564885 L9.77099237,43.9694656 C9.77099237,46.6564885 11.9694656,48.8549618 14.6564885,48.8549618 L43.9694656,48.8549618 C46.6564885,48.8549618 48.8549618,46.6564885 48.8549618,43.9694656 L48.8549618,14.6564885 C48.8549618,11.9694656 46.6564885,9.77099237 43.9694656,9.77099237 L43.9694656,9.77099237 Z" id="Fill-2" fill="#651FFF"></path>
</g>
</g>
<g id="Group-11" transform="translate(107.814782, 114.998541) rotate(-10.000000) translate(-107.814782, -114.998541) translate(68.314782, 75.498541)">
<g id="Rectangle-1196-Copy-6">
<use fill="black" fill-opacity="1" filter="url(#filter-12)" xlink:href="#path-11"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-11"></use>
</g>
<g id="filetype_excel" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="-5.68434189e-14 58.6259542 58.6259542 58.6259542 58.6259542 -1.56319402e-13 -5.68434189e-14 -1.56319402e-13"></polygon>
<g id="Group-10" transform="translate(4.885496, 4.885496)" fill="#22BE73">
<path d="M47.1621374,41.632 L28.848855,41.632 L28.848855,38.3025344 L33.2873282,38.3025344 L33.2873282,34.4161221 L28.848855,34.4161221 L28.848855,32.1981069 L33.2873282,32.1981069 L33.2873282,28.3116947 L28.848855,28.3116947 L28.848855,26.0936794 L33.2873282,26.0936794 L33.2873282,22.2072672 L28.848855,22.2072672 L28.848855,19.9868092 L33.2873282,19.9868092 L33.2873282,16.1028397 L28.848855,16.1028397 L28.848855,13.8823817 L33.2873282,13.8823817 L33.2873282,9.99841221 L28.848855,9.99841221 L28.848855,6.66894656 L47.1621374,6.66894656 L47.1621374,41.632 L47.1621374,41.632 Z M16.3444275,33.1141374 C15.4015267,30.7984122 14.2509924,28.5632977 13.5743511,26.1425344 C12.819542,28.3947481 11.7422901,30.5223817 10.8775573,32.730626 C9.6610687,32.7135267 8.4470229,32.6646718 7.23053435,32.613374 C8.65709924,29.821313 10.0348092,27.0072672 11.5053435,24.2323053 C10.2546565,21.3742901 8.88427481,18.572458 7.59694656,15.731542 C8.81832061,15.6582595 10.0396947,15.5874198 11.2610687,15.5190229 C12.0867176,17.690626 12.9929771,19.832916 13.6745038,22.0582595 C14.4073282,19.6985649 15.5016794,17.4781069 16.4372519,15.1990229 C17.6928244,15.1086412 18.9532824,15.032916 20.2112977,14.9718473 C18.7309924,18.0057405 17.2433588,21.0420763 15.7337405,24.0661985 C17.260458,27.1758168 18.8189313,30.2610076 20.3505344,33.3681832 C19.0143511,33.2900153 17.6806107,33.2069618 16.3444275,33.1141374 L16.3444275,33.1141374 Z M48.8329771,37.2203969 C48.8280916,27.591084 48.8158779,17.961771 48.8427481,8.32757252 C48.8036641,7.38467176 48.8720611,6.34161832 48.300458,5.51841221 C47.4845802,4.9590229 46.4512977,5.0249771 45.5132824,4.98589313 C39.9584733,5.01520611 34.4036641,5.00299237 28.848855,5.00299237 L28.848855,0.564519084 L25.551145,0.564519084 C17.0381679,2.06680916 8.5178626,3.52757252 4.68958206e-13,5.00787786 L4.68958206e-13,43.852458 C8.46900763,45.3327634 16.9429008,46.7544427 25.4021374,48.2909313 L28.848855,48.2909313 L28.848855,43.2979542 C34.6039695,43.2857405 40.359084,43.3126107 46.1068702,43.2979542 C47.0351145,43.2588702 48.4225954,43.2295573 48.6448855,42.0765802 C48.9819847,40.4839084 48.8036641,38.8350534 48.8329771,37.2203969 L48.8329771,37.2203969 Z" id="Fill-2"></path>
<path d="M35.5077863,13.8821374 L43.2781679,13.8821374 L43.2781679,9.99816794 L35.5077863,9.99816794 L35.5077863,13.8821374 Z M35.5077863,19.9865649 L43.2781679,19.9865649 L43.2781679,16.1025954 L35.5077863,16.1025954 L35.5077863,19.9865649 Z M35.5077863,26.0909924 L43.2781679,26.0909924 L43.2781679,22.2070229 L35.5077863,22.2070229 L35.5077863,26.0909924 Z M35.5077863,32.1954198 L43.2781679,32.1954198 L43.2781679,28.3114504 L35.5077863,28.3114504 L35.5077863,32.1954198 Z M35.5077863,38.3022901 L43.2781679,38.3022901 L43.2781679,34.4183206 L35.5077863,34.4183206 L35.5077863,38.3022901 Z" id="Combined-Shape"></path>
</g>
</g>
</g>
<g id="Group-4" transform="translate(388.820630, 86.064353) rotate(-350.000000) translate(-388.820630, -86.064353) translate(349.320630, 46.564353)">
<g id="Rectangle-1196-Copy">
<use fill="black" fill-opacity="1" filter="url(#filter-14)" xlink:href="#path-13"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-13"></use>
</g>
<g id="filetype_audio" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="-1.13686838e-13 58.6259542 58.6259542 58.6259542 58.6259542 -6.39488462e-14 -1.13686838e-13 -6.39488462e-14"></polygon>
<path d="M29.3129771,7.32824427 L43.9694656,7.32824427 L43.9694656,17.0601527 L34.2375573,17.0601527 L34.2375573,41.5658015 C34.2375573,44.2381679 33.2629008,46.5270229 31.3160305,48.4348092 C29.3691603,50.3450382 27.0607634,51.2977099 24.3883969,51.2977099 C21.7160305,51.2977099 19.4271756,50.3450382 17.5193893,48.4348092 C15.6091603,46.5270229 14.6564885,44.2381679 14.6564885,41.5658015 C14.6564885,38.8934351 15.6091603,36.5850382 17.5193893,34.6381679 C19.4271756,32.6912977 21.7160305,31.7166412 24.3883969,31.7166412 C25.9932824,31.7166412 27.6323664,32.1758779 29.3129771,33.0919084 L29.3129771,7.32824427 Z" id="Fill-2" fill="#E91E63"></path>
</g>
</g>
<g id="Group-2" transform="translate(411.603053, 1.221374)">
<g id="Group-3">
<g id="Rectangle-1196">
<use fill="black" fill-opacity="1" filter="url(#filter-16)" xlink:href="#path-15"></use>
<use fill="#FFFFFF" fill-rule="evenodd" xlink:href="#path-15"></use>
</g>
<polygon id="Fill-1" points="9.77099237 68.3969466 68.3969466 68.3969466 68.3969466 9.77099237 9.77099237 9.77099237"></polygon>
</g>
<g id="filetype_book" transform="translate(9.770992, 9.770992)">
<polygon id="Fill-1" points="0 58.6259542 58.6259542 58.6259542 58.6259542 0 0 0"></polygon>
<path d="M14.6564885,9.77099237 L26.870229,9.77099237 L26.870229,29.3129771 L20.7633588,25.648855 L14.6564885,29.3129771 L14.6564885,9.77099237 Z M43.9694656,4.88549618 L14.6564885,4.88549618 C11.9572519,4.88549618 9.77099237,7.07175573 9.77099237,9.77099237 L9.77099237,48.8549618 C9.77099237,51.5541985 11.9572519,53.740458 14.6564885,53.740458 L43.9694656,53.740458 C46.6687023,53.740458 48.8549618,51.5541985 48.8549618,48.8549618 L48.8549618,9.77099237 C48.8549618,7.07175573 46.6687023,4.88549618 43.9694656,4.88549618 L43.9694656,4.88549618 Z" id="Fill-2" fill="#FF6D40"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,47 @@
/*!
* @license
* Copyright 2019 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 { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { TaskAttachmentListComponent } from './task-attachment-list.component';
import { ProcessAttachmentListComponent } from './process-attachment-list.component';
import { CreateProcessAttachmentComponent } from './create-process-attachment.component';
import { AttachmentComponent } from './create-task-attachment.component';
import { CoreModule } from '@alfresco/adf-core';
@NgModule({
imports: [
CoreModule,
MaterialModule
],
declarations: [
TaskAttachmentListComponent,
ProcessAttachmentListComponent,
CreateProcessAttachmentComponent,
CreateProcessAttachmentComponent,
AttachmentComponent
],
exports: [
TaskAttachmentListComponent,
ProcessAttachmentListComponent,
CreateProcessAttachmentComponent,
CreateProcessAttachmentComponent,
AttachmentComponent
]
})
export class AttachmentModule {}

View File

@@ -0,0 +1,5 @@
.adf-create-attachment {
display: inline-block;
line-height: 0px;
vertical-align: middle;
}

View File

@@ -0,0 +1,13 @@
<button
id="add_new_process_content_button"
color="primary"
mat-button
mat-raised-button
mat-icon-button
class="adf-create-attachment"
adf-upload="true"
[mode]="['click']"
[multiple]="true"
(upload-files)="onFileUpload($event)">
<mat-icon>add</mat-icon>
</button>

View File

@@ -0,0 +1,120 @@
/*!
* @license
* Copyright 2019 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 { SimpleChange } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { setupTestBed } from '@alfresco/adf-core';
import { CreateProcessAttachmentComponent } from './create-process-attachment.component';
import { ProcessTestingModule } from '../testing/process.testing.module';
declare let jasmine: any;
describe('CreateProcessAttachmentComponent', () => {
let component: CreateProcessAttachmentComponent;
let fixture: ComponentFixture<CreateProcessAttachmentComponent>;
let element: HTMLElement;
const file = new File([new Blob()], 'Test');
const fileObj = { entry: null, file: file, relativeFolder: '/' };
const customEvent = { detail: { files: [fileObj] } };
const fakeUploadResponse = {
id: 9999,
name: 'BANANA.jpeg',
created: '2017-06-12T12:52:11.109Z',
createdBy: { id: 2, firstName: 'fake-user', lastName: 'fake-user', email: 'fake-user' },
relatedContent: false,
contentAvailable: true,
link: false,
mimeType: 'image/jpeg',
simpleType: 'image',
previewStatus: 'queued',
thumbnailStatus: 'queued'
};
setupTestBed({
imports: [
ProcessTestingModule
]
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateProcessAttachmentComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
component.processInstanceId = '9999';
fixture.detectChanges();
});
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('should update the processInstanceId when it is changed', () => {
component.processInstanceId = null;
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
expect(component.processInstanceId).toBe('123');
});
it('should emit content created event when the file is uploaded', async(() => {
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.id).toBe(9999);
});
component.onFileUpload(customEvent);
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeUploadResponse)
});
}));
it('should allow user to upload files via button', async(() => {
const buttonUpload: HTMLElement = <HTMLElement> element.querySelector('#add_new_process_content_button');
expect(buttonUpload).toBeDefined();
expect(buttonUpload).not.toBeNull();
component.success.subscribe((res) => {
expect(res).toBeDefined();
expect(res).not.toBeNull();
expect(res.id).toBe(9999);
});
const dropEvent = new CustomEvent('upload-files', customEvent);
buttonUpload.dispatchEvent(dropEvent);
fixture.detectChanges();
jasmine.Ajax.requests.mostRecent().respondWith({
'status': 200,
contentType: 'application/json',
responseText: JSON.stringify(fakeUploadResponse)
});
}));
});

View File

@@ -0,0 +1,70 @@
/*!
* @license
* Copyright 2019 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, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { ProcessContentService } from '@alfresco/adf-core';
@Component({
selector: 'adf-create-process-attachment',
styleUrls: ['./create-process-attachment.component.css'],
templateUrl: './create-process-attachment.component.html'
})
export class CreateProcessAttachmentComponent implements OnChanges {
/** (required) The ID of the process instance to display. */
@Input()
processInstanceId: string;
/** Emitted when an error occurs while creating or uploading an attachment
* from the user within the component.
*/
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when an attachment is successfully created or uploaded
* from within the component.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
constructor(private activitiContentService: ProcessContentService) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['processInstanceId'] && changes['processInstanceId'].currentValue) {
this.processInstanceId = changes['processInstanceId'].currentValue;
}
}
onFileUpload(event: any) {
const filesList: File[] = event.detail.files.map((obj) => obj.file);
for (const fileInfoObj of filesList) {
const file: File = fileInfoObj;
const opts = {
isRelatedContent: true
};
this.activitiContentService.createProcessRelatedContent(this.processInstanceId, file, opts).subscribe(
(res) => {
this.success.emit(res);
},
(err) => {
this.error.emit(err);
});
}
}
}

View File

@@ -0,0 +1,12 @@
<button
color="primary"
mat-button
mat-raised-button
mat-icon-button
class="adf-create-attachment"
adf-upload="true"
[mode]="['click']"
[multiple]="true"
(upload-files)="onFileUpload($event)">
<mat-icon>add</mat-icon>
</button>

View File

@@ -0,0 +1,5 @@
.adf-create-attachment {
display: inline-block;
line-height: 0;
vertical-align: middle;
}

View File

@@ -0,0 +1,81 @@
/*!
* @license
* Copyright 2019 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 { SimpleChange } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { ProcessContentService, setupTestBed } from '@alfresco/adf-core';
import { AttachmentComponent } from './create-task-attachment.component';
import { ProcessTestingModule } from '../testing/process.testing.module';
describe('AttachmentComponent', () => {
let service: ProcessContentService;
let component: AttachmentComponent;
let fixture: ComponentFixture<AttachmentComponent>;
let createTaskRelatedContentSpy: jasmine.Spy;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(() => {
fixture = TestBed.createComponent(AttachmentComponent);
component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ProcessContentService);
createTaskRelatedContentSpy = spyOn(service, 'createTaskRelatedContent').and.returnValue(of(
{
status: true
}));
});
it('should not call createTaskRelatedContent service when taskId changed', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
expect(createTaskRelatedContentSpy).not.toHaveBeenCalled();
});
it('should not call createTaskRelatedContent service when there is no file uploaded', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
const customEvent: any = {
detail: {
files: []
}
};
component.onFileUpload(customEvent);
expect(createTaskRelatedContentSpy).not.toHaveBeenCalled();
});
it('should call createTaskRelatedContent service when there is a file uploaded', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'taskId': change});
const file = new File([new Blob()], 'Test');
const customEvent = {
detail: {
files: [
file
]
}
};
component.onFileUpload(customEvent);
expect(createTaskRelatedContentSpy).toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,71 @@
/*!
* @license
* Copyright 2019 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, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { ProcessContentService } from '@alfresco/adf-core';
@Component({
selector: 'adf-create-task-attachment',
styleUrls: ['./create-task-attachment.component.scss'],
templateUrl: './create-task-attachment.component.html'
})
export class AttachmentComponent implements OnChanges {
/** (required) The numeric ID of the task to display. */
@Input()
taskId: string;
/** Emitted when an error occurs while creating or uploading an
* attachment from the user within the component.
*/
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when an attachment is created or uploaded successfully
* from within the component.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
constructor(private activitiContentService: ProcessContentService) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['taskId'] && changes['taskId'].currentValue) {
this.taskId = changes['taskId'].currentValue;
}
}
onFileUpload(event: any) {
const filesList: File[] = event.detail.files.map((obj) => obj.file);
for (const fileInfoObj of filesList) {
const file: File = fileInfoObj;
const opts = {
isRelatedContent: true
};
this.activitiContentService.createTaskRelatedContent(this.taskId, file, opts).subscribe(
(res) => {
this.success.emit(res);
},
(err) => {
this.error.emit(err);
}
);
}
}
}

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './public-api';

View File

@@ -0,0 +1,35 @@
<adf-datatable [rows]="attachments"
[actions]="true"
[loading]="isLoading"
(rowDblClick)="openContent($event)"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)">
<adf-no-content-template>
<ng-template>
<ng-content *ngIf="hasCustomTemplate; else defaulEmptyList" class="adf-custom-empty-template"></ng-content>
<ng-template #defaulEmptyList>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">
{{'ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER' | translate}}
</div>
</adf-empty-list>
</ng-template>
</ng-template>
</adf-no-content-template>
<data-columns>
<data-column key="icon" type="image" srTitle="ADF_PROCESS_LIST.PROPERTIES.THUMBNAIL" [sortable]="false"></data-column>
<data-column key="name" type="text" title="{{'ADF_PROCESS_LIST.PROPERTIES.NAME' | translate}}" class="adf-full-width adf-ellipsis-cell" [sortable]="true"></data-column>
<data-column key="created" type="date" format="shortDate" title="{{'ADF_PROCESS_LIST.PROPERTIES.CREATED' | translate}}"></data-column>
</data-columns>
<adf-loading-content-template>
<ng-template>
<!--Add your custom loading template here-->
<mat-progress-spinner class="adf-attachment-list-loading-margin" [color]="'primary'" [mode]="'indeterminate'">
</mat-progress-spinner>
</ng-template>
</adf-loading-content-template>
</adf-datatable>

View File

@@ -0,0 +1,52 @@
@mixin adf-process-attachment-list-theme($theme) {
.adf-data-cell {
cursor: pointer !important;
}
.adf-attachment-list-loading-margin {
margin-left: calc((100% - 100px) / 2);
margin-right: calc((100% - 100px) / 2);
}
.adf-empty-list-header {
height: 32px;
opacity: 0.26 !important;
font-size: 24px;
line-height: 1.33;
letter-spacing: -1px;
}
.adf-empty-list-drag_drop {
min-height: 56px;
opacity: 0.54;
font-size: 56px;
line-height: 1;
letter-spacing: -2px;
margin-top: 40px !important;
word-break: break-all;
white-space: pre-line;
}
.adf-empty-list__any-files-here-to-add {
min-height: 24px;
opacity: 0.54;
font-size: 16px;
line-height: 1.5;
letter-spacing: -0.4px;
margin-top: 17px;
word-break: break-all;
white-space: pre-line;
}
.adf-empty-list__empty_doc_lib {
width: 565px;
height: 161px;
object-fit: contain;
margin-top: 17px;
@media screen and ($mat-xsmall) {
width: 250px;
}
}
}

View File

@@ -0,0 +1,333 @@
/*!
* @license
* Copyright 2019 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 { SimpleChange, Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ProcessContentService, setupTestBed } from '@alfresco/adf-core';
import { of, throwError } from 'rxjs';
import { ProcessAttachmentListComponent } from './process-attachment-list.component';
import { ProcessTestingModule } from '../testing/process.testing.module';
describe('ProcessAttachmentListComponent', () => {
let service: ProcessContentService;
let component: ProcessAttachmentListComponent;
let fixture: ComponentFixture<ProcessAttachmentListComponent>;
let getProcessRelatedContentSpy: jasmine.Spy;
let mockAttachment: any;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(() => {
fixture = TestBed.createComponent(ProcessAttachmentListComponent);
component = fixture.componentInstance;
service = fixture.debugElement.injector.get(ProcessContentService);
mockAttachment = {
size: 2,
total: 2,
start: 0,
data: [{
id: 4001,
name: 'Invoice01.pdf',
created: '2017-05-12T12:50:05.522+0000',
createdBy: {
id: 1,
firstName: 'Apps',
lastName: 'Administrator',
email: 'admin@app.activiti.com',
company: 'Alfresco.com',
pictureId: 3003
},
relatedContent: true,
contentAvailable: true,
link: false,
mimeType: 'application/pdf',
simpleType: 'pdf',
previewStatus: 'created',
thumbnailStatus: 'created'
},
{
id: 4002,
name: 'Invoice02.pdf',
created: '2017-05-12T12:50:05.522+0000',
createdBy: {
id: 1,
firstName: 'Apps',
lastName: 'Administrator',
email: 'admin@app.activiti.com',
company: 'Alfresco.com',
pictureId: 3003
},
relatedContent: true,
contentAvailable: true,
link: false,
mimeType: 'application/pdf',
simpleType: 'pdf',
previewStatus: 'created',
thumbnailStatus: 'created'
}]
};
getProcessRelatedContentSpy = spyOn(service, 'getProcessRelatedContent').and.returnValue(of(mockAttachment));
spyOn(service, 'deleteRelatedContent').and.returnValue(of({successCode: true}));
const blobObj = new Blob();
spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj));
});
afterEach(() => {
fixture.destroy();
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
});
});
it('should load attachments when processInstanceId specified', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
expect(getProcessRelatedContentSpy).toHaveBeenCalled();
});
it('should emit an error when an error occurs loading attachments', () => {
const emitSpy = spyOn(component.error, 'emit');
getProcessRelatedContentSpy.and.returnValue(throwError({}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
expect(emitSpy).toHaveBeenCalled();
});
it('should emit a success event when the attachments are loaded', () => {
const change = new SimpleChange(null, '123', true);
component.success.subscribe((attachments) => {
expect(attachments[0].name).toEqual(mockAttachment.data[0].name);
expect(attachments[0].id).toEqual(mockAttachment.data[0].id);
});
component.ngOnChanges({'taskId': change});
});
it('should not attach when no processInstanceId is specified', () => {
fixture.detectChanges();
expect(getProcessRelatedContentSpy).not.toHaveBeenCalled();
});
it('should display attachments when the process has attachments', async(() => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
});
}));
it('should display all actions if attachments are not read only', async(() => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
fixture.detectChanges();
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
actionButton.click();
fixture.whenStable().then(() => {
fixture.detectChanges();
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
expect(actionMenu).toBe(3);
});
}));
it('should not display remove action if attachments are read only', async(() => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'processInstanceId': change });
component.disabled = true;
fixture.detectChanges();
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
actionButton.click();
fixture.whenStable().then(() => {
fixture.detectChanges();
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).toBeNull();
expect(actionMenu).toBe(2);
});
}));
it('should show the empty list component when the attachments list is empty', async(() => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
});
}));
it('should not show the empty list drag and drop component when is disabled', async(() => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.disabled = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('adf-empty-list .adf-empty-list-drag_drop')).toBeNull();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
});
}));
it('should show the empty list component when the attachments list is empty for completed process', async(() => {
getProcessRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.disabled = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim())
.toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
});
}));
it('should not show the empty list component when the attachments list is not empty for completed process', async(() => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.disabled = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]')).toBeNull();
});
}));
it('should call getProcessRelatedContent with opt isRelatedContent=true', () => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
const isRelatedContent = 'true';
component.ngOnChanges({'processInstanceId': change});
expect(getProcessRelatedContentSpy).toHaveBeenCalled();
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('123', isRelatedContent);
});
describe('change detection', () => {
const change = new SimpleChange('123', '456', true);
const nullChange = new SimpleChange('123', null, true);
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.whenStable().then(() => {
getProcessRelatedContentSpy.calls.reset();
});
}));
it('should fetch new attachments when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('456', 'true');
});
it('should NOT fetch new attachments when empty changeset made', () => {
component.ngOnChanges({});
expect(getProcessRelatedContentSpy).not.toHaveBeenCalled();
});
it('should NOT fetch new attachments when processInstanceId changed to null', () => {
component.ngOnChanges({ 'processInstanceId': nullChange });
expect(getProcessRelatedContentSpy).not.toHaveBeenCalled();
});
});
describe('Delete attachments', () => {
beforeEach(async(() => {
component.processInstanceId = '123';
fixture.whenStable();
}));
it('should display a dialog to the user when the Add button clicked', () => {
expect(true).toBe(true);
});
});
});
@Component({
template: `
<adf-process-attachment-list>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">Custom header</div>
</adf-empty-list>
</adf-process-attachment-list>
`
})
class CustomEmptyTemplateComponent {
}
describe('Custom CustomEmptyTemplateComponent', () => {
let fixture: ComponentFixture<CustomEmptyTemplateComponent>;
setupTestBed({
imports: [ProcessTestingModule],
declarations: [CustomEmptyTemplateComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
});
beforeEach(() => {
fixture = TestBed.createComponent(CustomEmptyTemplateComponent);
fixture.detectChanges();
});
afterEach(() => {
fixture.destroy();
});
it('should render the custom template', async(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
const title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]'));
expect(title.length).toBe(1);
expect(title[0].nativeElement.innerText).toBe('Custom header');
});
}));
});

View File

@@ -0,0 +1,221 @@
/*!
* @license
* Copyright 2019 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 { ContentService, EmptyListComponent , ThumbnailService } from '@alfresco/adf-core';
import { AfterContentInit, ContentChild, Component, EventEmitter, Input, NgZone, OnChanges, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
import { ProcessContentService } from '@alfresco/adf-core';
@Component({
selector: 'adf-process-attachment-list',
styleUrls: ['./process-attachment-list.component.scss'],
templateUrl: './process-attachment-list.component.html',
encapsulation: ViewEncapsulation.None
})
export class ProcessAttachmentListComponent implements OnChanges, AfterContentInit {
@ContentChild(EmptyListComponent)
emptyTemplate: EmptyListComponent;
/** (**required**) The ID of the process instance to display. */
@Input()
processInstanceId: string;
/** Disable/Enable read-only mode for attachment list. */
@Input()
disabled: boolean = false;
/** Emitted when the attachment is double-clicked or the
* view option is selected from the context menu by the user from
* within the component. Returns a Blob representing the object
* that was clicked.
*/
@Output()
attachmentClick = new EventEmitter();
/** Emitted when the attachment list has fetched all the attachments.
* Returns a list of attachments.
*/
@Output()
success = new EventEmitter();
/** Emitted when the attachment list is not able to fetch the attachments
* (eg, following a network error).
*/
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
hasCustomTemplate: boolean = false;
attachments: any[] = [];
isLoading: boolean = false;
constructor(private activitiContentService: ProcessContentService,
private contentService: ContentService,
private thumbnailService: ThumbnailService,
private ngZone: NgZone) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['processInstanceId'] && changes['processInstanceId'].currentValue) {
this.loadAttachmentsByProcessInstanceId(changes['processInstanceId'].currentValue);
}
}
ngAfterContentInit() {
if (this.emptyTemplate) {
this.hasCustomTemplate = true;
}
}
reset() {
this.attachments = [];
}
reload(): void {
this.ngZone.run(() => {
this.loadAttachmentsByProcessInstanceId(this.processInstanceId);
});
}
hasCustomEmptyTemplate() {
return !!this.emptyTemplate;
}
add(content: any): void {
this.ngZone.run(() => {
this.attachments.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
}
private loadAttachmentsByProcessInstanceId(processInstanceId: string) {
if (processInstanceId) {
this.reset();
this.isLoading = true;
const opts: string = 'true';
this.activitiContentService.getProcessRelatedContent(processInstanceId, opts).subscribe(
(res: any) => {
res.data.forEach((content) => {
this.attachments.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
private deleteAttachmentById(contentId: number) {
if (contentId) {
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
() => {
this.attachments = this.attachments.filter((content) => {
return content.id !== contentId;
});
},
(err) => {
this.error.emit(err);
});
}
}
isEmpty(): boolean {
return this.attachments && this.attachments.length === 0;
}
onShowRowActionsMenu(event: any) {
const viewAction = {
title: 'ADF_PROCESS_LIST.MENU_ACTIONS.VIEW_CONTENT',
name: 'view'
};
const removeAction = {
title: 'ADF_PROCESS_LIST.MENU_ACTIONS.REMOVE_CONTENT',
name: 'remove'
};
const downloadAction = {
title: 'ADF_PROCESS_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT',
name: 'download'
};
event.value.actions = [
viewAction,
downloadAction
];
if (!this.disabled) {
event.value.actions.splice(1, 0, removeAction);
}
}
onExecuteRowAction(event: any) {
const args = event.value;
const action = args.action;
if (action.name === 'view') {
this.emitDocumentContent(args.row.obj);
} else if (action.name === 'remove') {
this.deleteAttachmentById(args.row.obj.id);
} else if (action.name === 'download') {
this.downloadContent(args.row.obj);
}
}
openContent(event: any): void {
const content = event.value.obj;
this.emitDocumentContent(content);
}
emitDocumentContent(content: any) {
this.activitiContentService.getFileRawContent(content.id).subscribe(
(blob: Blob) => {
content.contentBlob = blob;
this.attachmentClick.emit(content);
},
(err) => {
this.error.emit(err);
}
);
}
downloadContent(content: any): void {
this.activitiContentService.getFileRawContent(content.id).subscribe(
(blob: Blob) => this.contentService.downloadBlob(blob, content.name),
(err) => {
this.error.emit(err);
}
);
}
isDisabled(): boolean {
return this.disabled;
}
}

View File

@@ -0,0 +1,23 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './task-attachment-list.component';
export * from './process-attachment-list.component';
export * from './create-process-attachment.component';
export * from './create-task-attachment.component';
export * from './attachment.module';

View File

@@ -0,0 +1,32 @@
<adf-datatable [rows]="attachments"
[actions]="true"
[loading]="isLoading"
(rowDblClick)="openContent($event)"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)">
<adf-no-content-template>
<ng-template>
<ng-content *ngIf="hasCustomTemplate; else defaulEmptyList" class="adf-custom-empty-template"></ng-content>
<ng-template #defaulEmptyList>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">
{{'ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER' | translate}}
</div>
</adf-empty-list>
</ng-template>
</ng-template>
</adf-no-content-template>
<data-columns>
<data-column key="icon" type="image" srTitle="ADF_TASK_LIST.PROPERTIES.THUMBNAIL" [sortable]="false"></data-column>
<data-column key="name" type="text" title="ADF_TASK_LIST.PROPERTIES.NAME" class="adf-full-width adf-ellipsis-cell" [sortable]="true"></data-column>
<data-column key="created" type="date" format="shortDate" title="ADF_TASK_LIST.PROPERTIES.CREATED"></data-column>
</data-columns>
<adf-loading-content-template>
<ng-template>
<!--Add your custom loading template here-->
<mat-progress-spinner class="adf-attachment-list-loading-margin" [color]="'primary'" [mode]="'indeterminate'">
</mat-progress-spinner>
</ng-template>
</adf-loading-content-template>
</adf-datatable>

View File

@@ -0,0 +1,58 @@
@mixin adf-task-attachment-list-theme($theme) {
adf-datatable .adf-data-cell {
cursor: pointer !important;
}
.adf-attachment-list-loading-margin {
margin-left: calc((100% - 100px) / 2);
margin-right: calc((100% - 100px) / 2);
}
.adf-empty-list-header {
height: 32px;
opacity: 0.26;
font-size: 24px;
line-height: 1.33;
letter-spacing: -1px;
}
.adf-empty-list-drag_drop {
min-height: 56px;
opacity: 0.54;
font-size: 56px;
line-height: 1;
letter-spacing: -2px;
margin-top: 40px;
word-break: break-all;
white-space: pre-line;
@media screen and ($mat-xsmall) {
font-size: 40px;
}
}
.adf-empty-list__any-files-here-to-add {
min-height: 24px;
opacity: 0.54;
font-size: 16px;
line-height: 1.5;
letter-spacing: -0.4px;
margin-top: 17px;
word-break: break-all;
white-space: pre-line;
}
.adf-empty-list__empty_doc_lib {
width: 565px;
max-width: 100%;
height: 161px;
object-fit: contain;
margin-top: 17px;
@media screen and ($mat-xsmall) {
width: 250px;
}
}
}

View File

@@ -0,0 +1,354 @@
/*!
* @license
* Copyright 2019 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 { SimpleChange, Component, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { TaskAttachmentListComponent } from './task-attachment-list.component';
import { ProcessContentService, setupTestBed } from '@alfresco/adf-core';
import { ProcessTestingModule } from '../testing/process.testing.module';
describe('TaskAttachmentList', () => {
let component: TaskAttachmentListComponent;
let fixture: ComponentFixture<TaskAttachmentListComponent>;
let service: ProcessContentService;
let getTaskRelatedContentSpy: jasmine.Spy;
let mockAttachment: any;
let deleteContentSpy: jasmine.Spy;
let getFileRawContentSpy: jasmine.Spy;
let disposableSuccess: any;
setupTestBed({
imports: [ProcessTestingModule],
schemas: [NO_ERRORS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(TaskAttachmentListComponent);
component = fixture.componentInstance;
service = TestBed.get(ProcessContentService);
mockAttachment = {
size: 2,
total: 2,
start: 0,
data: [
{
id: 8,
name: 'fake.zip',
created: 1494595697381,
createdBy: { id: 2, firstName: 'user', lastName: 'user', email: 'user@user.com' },
relatedContent: true,
contentAvailable: true,
link: false,
mimeType: 'application/zip',
simpleType: 'content',
previewStatus: 'unsupported',
thumbnailStatus: 'unsupported'
},
{
id: 9,
name: 'fake.jpg',
created: 1494595655381,
createdBy: { id: 2, firstName: 'user', lastName: 'user', email: 'user@user.com' },
relatedContent: true,
contentAvailable: true,
link: false,
mimeType: 'image/jpeg',
simpleType: 'image',
previewStatus: 'unsupported',
thumbnailStatus: 'unsupported'
}
]
};
getTaskRelatedContentSpy = spyOn(service, 'getTaskRelatedContent').and.returnValue(of(
mockAttachment
));
deleteContentSpy = spyOn(service, 'deleteRelatedContent').and.returnValue(of({ successCode: true }));
const blobObj = new Blob();
getFileRawContentSpy = spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj));
});
afterEach(() => {
const overlayContainers = <any> window.document.querySelectorAll('.cdk-overlay-container');
overlayContainers.forEach((overlayContainer) => {
overlayContainer.innerHTML = '';
});
if (disposableSuccess) {
disposableSuccess.unsubscribe();
}
});
it('should load attachments when taskId specified', () => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
expect(getTaskRelatedContentSpy).toHaveBeenCalled();
});
it('should emit an error when an error occurs loading attachments', () => {
const emitSpy = spyOn(component.error, 'emit');
getTaskRelatedContentSpy.and.returnValue(throwError({}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
expect(emitSpy).toHaveBeenCalled();
});
it('should emit a success event when the attachments are loaded', () => {
const change = new SimpleChange(null, '123', true);
disposableSuccess = component.success.subscribe((attachments) => {
expect(attachments[0].name).toEqual(mockAttachment.data[0].name);
expect(attachments[0].id).toEqual(mockAttachment.data[0].id);
});
component.ngOnChanges({ 'taskId': change });
});
it('should not attach when no taskId is specified', () => {
fixture.detectChanges();
expect(getTaskRelatedContentSpy).not.toHaveBeenCalled();
});
it('should display attachments when the task has attachments', (done) => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.css('.adf-datatable-body > .adf-datatable-row')).length).toBe(2);
done();
});
});
it('emit document when a user wants to view the document', () => {
component.emitDocumentContent(mockAttachment.data[1]);
fixture.detectChanges();
expect(getFileRawContentSpy).toHaveBeenCalled();
});
it('download document when a user wants to view the document', () => {
component.downloadContent(mockAttachment.data[1]);
fixture.detectChanges();
expect(getFileRawContentSpy).toHaveBeenCalled();
});
it('should show the empty default message when has no custom template', async(() => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.hasCustomTemplate = false;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('.adf-custom-empty-template')).toBeNull();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER');
});
}));
it('should display all actions if attachments are not read only', async(() => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
actionButton.click();
fixture.whenStable().then(() => {
fixture.detectChanges();
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
expect(actionMenu).toBe(3);
});
}));
it('should not display remove action if attachments are read only', async(() => {
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.disabled = true;
fixture.detectChanges();
const actionButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="action_menu_0"]');
actionButton.click();
fixture.whenStable().then(() => {
fixture.detectChanges();
const actionMenu = window.document.querySelectorAll('button.mat-menu-item').length;
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT"]')).not.toBeNull();
expect(window.document.querySelector('[data-automation-id="ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT"]')).toBeNull();
expect(actionMenu).toBe(2);
});
}));
it('should show the empty list component when the attachments list is empty', async(() => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER');
});
}));
it('should show the empty list component when the attachments list is empty for completed task', async(() => {
getTaskRelatedContentSpy.and.returnValue(of({
'size': 0,
'total': 0,
'start': 0,
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.disabled = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_TASK_LIST.ATTACHMENT.EMPTY.HEADER');
});
}));
it('should not show the empty list component when the attachments list is not empty for completed task', (done) => {
getTaskRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({ 'taskId': change });
component.disabled = true;
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]')).toBeNull();
done();
});
});
it('loading should be false by default', () => {
expect(component.isLoading).toBeFalsy();
});
describe('change detection', () => {
let change;
let nullChange;
beforeEach(() => {
change = new SimpleChange('123', '456', true);
nullChange = new SimpleChange('123', null, true);
});
beforeEach(async(() => {
component.taskId = '123';
fixture.whenStable().then(() => {
getTaskRelatedContentSpy.calls.reset();
});
}));
it('should fetch new attachments when taskId changed', (done) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
component.ngOnChanges({ 'taskId': change });
expect(getTaskRelatedContentSpy).toHaveBeenCalledWith('456', 'true');
done();
});
});
it('should NOT fetch new attachments when empty change set made', () => {
component.ngOnChanges({});
expect(getTaskRelatedContentSpy).not.toHaveBeenCalled();
});
it('should NOT fetch new attachments when taskId changed to null', () => {
component.ngOnChanges({ 'taskId': nullChange });
expect(getTaskRelatedContentSpy).not.toHaveBeenCalled();
});
});
describe('Delete attachments', () => {
beforeEach(async(() => {
component.taskId = '123';
fixture.whenStable();
}));
it('should display a dialog to the user when the Add button clicked', () => {
expect(true).toBe(true);
});
it('delete content by contentId', () => {
component.deleteAttachmentById(5);
fixture.detectChanges();
expect(deleteContentSpy).toHaveBeenCalled();
});
});
});
@Component({
template: `
<adf-task-attachment-list>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">Custom header</div>
</adf-empty-list>
</adf-task-attachment-list>
`
})
class CustomEmptyTemplateComponent {
}
describe('Custom CustomEmptyTemplateComponent', () => {
let fixture: ComponentFixture<CustomEmptyTemplateComponent>;
setupTestBed({
imports: [ProcessTestingModule],
declarations: [CustomEmptyTemplateComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(CustomEmptyTemplateComponent);
fixture.detectChanges();
});
afterEach(() => {
fixture.destroy();
});
it('should render the custom template', async(() => {
fixture.whenStable().then(() => {
fixture.detectChanges();
const title: any = fixture.debugElement.queryAll(By.css('[adf-empty-list-header]'));
expect(title.length).toBe(1);
expect(title[0].nativeElement.innerText).toBe('Custom header');
});
}));
});

View File

@@ -0,0 +1,231 @@
/*!
* @license
* Copyright 2019 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 { ContentService, ThumbnailService, EmptyListComponent } from '@alfresco/adf-core';
import {
AfterContentInit,
ContentChild,
Component,
EventEmitter,
Input,
NgZone,
OnChanges,
Output,
SimpleChanges,
ViewEncapsulation
} from '@angular/core';
import { ProcessContentService } from '@alfresco/adf-core';
@Component({
selector: 'adf-task-attachment-list',
styleUrls: ['./task-attachment-list.component.scss'],
templateUrl: './task-attachment-list.component.html',
encapsulation: ViewEncapsulation.None
})
export class TaskAttachmentListComponent implements OnChanges, AfterContentInit {
@ContentChild(EmptyListComponent)
emptyTemplate: EmptyListComponent;
/** (**required**) The ID of the task to display. */
@Input()
taskId: string;
/** Disable/Enable read only mode for attachment list. */
@Input()
disabled: boolean = false;
/** Emitted when the attachment is double-clicked or a view
* option is selected from the context menu by the user from within the component.
* Returns a Blob representing the clicked object.
*/
@Output()
attachmentClick = new EventEmitter();
/** Emitted when the attachment list has fetched all the attachments.
* Returns a list of attachments.
*/
@Output()
success = new EventEmitter();
/** Emitted when an error occurs while fetching the attachments. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
hasCustomTemplate: boolean = false;
attachments: any[] = [];
isLoading: boolean = false;
constructor(private activitiContentService: ProcessContentService,
private contentService: ContentService,
private thumbnailService: ThumbnailService,
private ngZone: NgZone) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes['taskId'] && changes['taskId'].currentValue) {
this.loadAttachmentsByTaskId(changes['taskId'].currentValue);
}
}
ngAfterContentInit() {
if (this.emptyTemplate) {
this.hasCustomTemplate = true;
}
}
reset(): void {
this.attachments = [];
}
hasCustomEmptyTemplate() {
return !!this.emptyTemplate;
}
reload(): void {
this.ngZone.run(() => {
this.loadAttachmentsByTaskId(this.taskId);
});
}
add(content: any): void {
this.ngZone.run(() => {
this.attachments.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
}
private loadAttachmentsByTaskId(taskId: string) {
if (taskId) {
this.isLoading = true;
this.reset();
const opts = 'true';
this.activitiContentService.getTaskRelatedContent(taskId, opts).subscribe(
(res: any) => {
const attachList = [];
res.data.forEach((content) => {
attachList.push({
id: content.id,
name: content.name,
created: content.created,
createdBy: content.createdBy.firstName + ' ' + content.createdBy.lastName,
icon: this.thumbnailService.getMimeTypeIcon(content.mimeType)
});
});
this.attachments = attachList;
this.success.emit(this.attachments);
this.isLoading = false;
},
(err) => {
this.error.emit(err);
this.isLoading = false;
});
}
}
deleteAttachmentById(contentId: number) {
if (contentId) {
this.activitiContentService.deleteRelatedContent(contentId).subscribe(
() => {
this.attachments = this.attachments.filter((content) => {
return content.id !== contentId;
});
},
(err) => {
this.error.emit(err);
});
}
}
isEmpty(): boolean {
return this.attachments && this.attachments.length === 0;
}
onShowRowActionsMenu(event: any) {
const viewAction = {
title: 'ADF_TASK_LIST.MENU_ACTIONS.VIEW_CONTENT',
name: 'view'
};
const removeAction = {
title: 'ADF_TASK_LIST.MENU_ACTIONS.REMOVE_CONTENT',
name: 'remove'
};
const downloadAction = {
title: 'ADF_TASK_LIST.MENU_ACTIONS.DOWNLOAD_CONTENT',
name: 'download'
};
event.value.actions = [
viewAction,
downloadAction
];
if (!this.disabled) {
event.value.actions.splice(1, 0, removeAction);
}
}
onExecuteRowAction(event: any) {
const args = event.value;
const action = args.action;
if (action.name === 'view') {
this.emitDocumentContent(args.row.obj);
} else if (action.name === 'remove') {
this.deleteAttachmentById(args.row.obj.id);
} else if (action.name === 'download') {
this.downloadContent(args.row.obj);
}
}
openContent(event: any): void {
const content = event.value.obj;
this.emitDocumentContent(content);
}
emitDocumentContent(content: any) {
this.activitiContentService.getFileRawContent(content.id).subscribe(
(blob: Blob) => {
content.contentBlob = blob;
this.attachmentClick.emit(content);
},
(err) => {
this.error.emit(err);
}
);
}
downloadContent(content: any): void {
this.activitiContentService.getFileRawContent(content.id).subscribe(
(blob: Blob) => this.contentService.downloadBlob(blob, content.name),
(err) => {
this.error.emit(err);
}
);
}
isDisabled(): boolean {
return this.disabled;
}
}

View File

@@ -0,0 +1,28 @@
/*!
* @license
* Copyright 2019 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 { Subject } from 'rxjs';
import { Node } from '@alfresco/js-api';
export interface AttachFileWidgetDialogComponentData {
title: string;
actionName?: string;
selected: Subject<Node[]>;
ecmHost: string;
context?: string;
isSelectionValid?: (entry: Node) => boolean;
}

View File

@@ -0,0 +1,37 @@
<header
mat-dialog-title
data-automation-id="content-node-selector-title">{{data?.title}}
</header>
<mat-dialog-content class="adf-login-dialog-content">
<adf-login-dialog-panel id="attach-file-login-panel" #adfLoginPanel *ngIf="!isLoggedIn()">
</adf-login-dialog-panel>
<adf-content-node-selector-panel *ngIf="isLoggedIn()"
id="attach-file-content-node"
[isSelectionValid]="data?.isSelectionValid"
(select)="onSelect($event)">
</adf-content-node-selector-panel>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button
mat-button
(click)="close()"
data-automation-id="attach-file-dialog-actions-cancel">{{ 'ATTACH-FILE.ACTIONS.CANCEL' | translate }}
</button>
<button *ngIf="!isLoggedIn()"
mat-button
(click)="performLogin()"
data-automation-id="attach-file-dialog-actions-login">{{ 'ATTACH-FILE.ACTIONS.LOGIN' | translate }}
</button>
<button *ngIf="isLoggedIn()"
mat-button
[disabled]="!chosenNode"
class="adf-choose-action"
(click)="onClick()"
data-automation-id="attach-file-dialog-actions-choose">{{ buttonActionName | translate }}
</button>
</mat-dialog-actions>

View File

@@ -0,0 +1,32 @@
@mixin adf-attach-file-widget-dialog-component-theme($theme) {
$primary: map-get($theme, primary);
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
.adf-attach-file-widget-dialog {
.mat-dialog-actions {
background-color: mat-color($background, background);
display: flex;
justify-content: flex-end;
color: mat-color($foreground, secondary-text);
button {
text-transform: uppercase;
font-weight: normal;
}
.adf-choose-action {
&[disabled] {
opacity: 0.6;
}
&:enabled {
color: mat-color($primary);
}
}
}
}
}

View File

@@ -0,0 +1,151 @@
/*!
* @license
* Copyright 2019 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 { MAT_DIALOG_DATA } from '@angular/material';
import { ContentModule, ContentNodeSelectorPanelComponent } from '@alfresco/adf-content-services';
import { EventEmitter } from '@angular/core';
import { ProcessTestingModule } from '../testing/process.testing.module';
import { AttachFileWidgetDialogComponent } from './attach-file-widget-dialog.component';
import { setupTestBed, AuthenticationService, SitesService, CoreModule } from '@alfresco/adf-core';
import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { By } from '@angular/platform-browser';
import { Node } from '@alfresco/js-api';
describe('AttachFileWidgetDialogComponent', () => {
let widget: AttachFileWidgetDialogComponent;
let fixture: ComponentFixture<AttachFileWidgetDialogComponent>;
const data: AttachFileWidgetDialogComponentData = {
title: 'Move along citizen...',
actionName: 'move',
selected: new EventEmitter<any>(),
ecmHost: 'http://fakeUrl.com/'
};
let element: HTMLInputElement;
let authService: AuthenticationService;
let siteService: SitesService;
let isLogged = false;
setupTestBed({
imports: [
CoreModule.forRoot(),
ProcessTestingModule,
ContentModule.forRoot(),
RouterTestingModule
],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: data }
]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(AttachFileWidgetDialogComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
authService = fixture.debugElement.injector.get(AuthenticationService);
siteService = fixture.debugElement.injector.get(SitesService);
spyOn(siteService, 'getSites').and.returnValue(of({ list: { entries: [] } }));
spyOn(widget, 'isLoggedIn').and.callFake(() => {
return isLogged;
});
}));
afterEach(() => {
fixture.destroy();
});
it('should be able to create the widget', () => {
expect(widget).not.toBeNull();
});
describe('When is not logged in', () => {
beforeEach(async(() => {
fixture.detectChanges();
isLogged = false;
}));
it('should show the login form', () => {
expect(element.querySelector('#attach-file-login-panel')).not.toBeNull();
expect(element.querySelector('#username')).not.toBeNull();
expect(element.querySelector('#password')).not.toBeNull();
expect(element.querySelector('button[data-automation-id="attach-file-dialog-actions-login"]')).not.toBeNull();
});
it('should be able to login', (done) => {
spyOn(authService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket'}));
isLogged = true;
let loginButton: HTMLButtonElement = element.querySelector('button[data-automation-id="attach-file-dialog-actions-login"]');
const usernameInput: HTMLInputElement = element.querySelector('#username');
const passwordInput: HTMLInputElement = element.querySelector('#password');
usernameInput.value = 'fakse-user';
passwordInput.value = 'fakse-user';
usernameInput.dispatchEvent(new Event('input'));
passwordInput.dispatchEvent(new Event('input'));
loginButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#attach-file-content-node')).not.toBeNull();
loginButton = element.querySelector('button[data-automation-id="attach-file-dialog-actions-login"]');
const chooseButton = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]');
expect(loginButton).toBeNull();
expect(chooseButton).not.toBeNull();
done();
});
});
});
describe('When is logged in', () => {
let contentNodePanel;
beforeEach(async(() => {
isLogged = true;
fixture.detectChanges();
contentNodePanel = fixture.debugElement.query(By.directive(ContentNodeSelectorPanelComponent));
}));
it('should show the content node selector', () => {
expect(element.querySelector('#attach-file-content-node')).not.toBeNull();
expect(element.querySelector('#username')).toBeNull();
expect(element.querySelector('#password')).toBeNull();
expect(element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]')).not.toBeNull();
});
it('should be able to select a file', (done) => {
data.selected.subscribe((nodeList: Node[]) => {
expect(nodeList[0].id).toBe('fake');
expect(nodeList[0].isFile).toBeTruthy();
done();
});
const fakeNode: Node = new Node({ id: 'fake', isFile: true});
contentNodePanel.componentInstance.select.emit([fakeNode]);
fixture.detectChanges();
fixture.whenStable().then(() => {
const chooseButton: HTMLButtonElement = element.querySelector('button[data-automation-id="attach-file-dialog-actions-choose"]');
chooseButton.click();
});
});
});
});

View File

@@ -0,0 +1,76 @@
/*!
* @license
* Copyright 2019 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, Inject, ViewEncapsulation, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material';
import { ExternalAlfrescoApiService, AlfrescoApiService, AuthenticationService, LoginDialogPanelComponent, SitesService, SearchService } from '@alfresco/adf-core';
import { DocumentListService, ContentNodeSelectorService } from '@alfresco/adf-content-services';
import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface';
import { Node } from '@alfresco/js-api';
@Component({
selector: 'adf-attach-file-widget-dialog',
templateUrl: './attach-file-widget-dialog.component.html',
styleUrls: ['./attach-file-widget-dialog.component.scss'],
encapsulation: ViewEncapsulation.None,
providers: [ AuthenticationService,
DocumentListService,
SitesService,
ContentNodeSelectorService,
SearchService,
{ provide: AlfrescoApiService, useClass: ExternalAlfrescoApiService} ]
})
export class AttachFileWidgetDialogComponent {
@ViewChild('adfLoginPanel')
loginPanel: LoginDialogPanelComponent;
chosenNode: Node[];
buttonActionName;
constructor(@Inject(MAT_DIALOG_DATA) public data: AttachFileWidgetDialogComponentData,
private externalApiService: AlfrescoApiService) {
(<any> externalApiService).init(data.ecmHost, data.context);
this.buttonActionName = data.actionName ? `ATTACH-FILE.ACTIONS.${data.actionName.toUpperCase()}` : 'ATTACH-FILE.ACTIONS.CHOOSE';
}
isLoggedIn() {
return this.externalApiService.getInstance().isLoggedIn();
}
performLogin() {
this.loginPanel.submitForm();
}
close() {
this.data.selected.complete();
}
onSelect(nodeList: Node[]) {
if (nodeList && nodeList[0].isFile) {
this.chosenNode = nodeList;
} else {
this.chosenNode = null;
}
}
onClick() {
this.data.selected.next(this.chosenNode);
this.data.selected.complete();
}
}

View File

@@ -0,0 +1,66 @@
/*!
* @license
* Copyright 2019 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 { TestBed } from '@angular/core/testing';
import { MatDialog } from '@angular/material';
import { AttachFileWidgetDialogService } from './attach-file-widget-dialog.service';
import { Subject, of } from 'rxjs';
import { setupTestBed, CoreModule } from '@alfresco/adf-core';
import { ProcessModule } from '../process.module';
describe('AttachFileWidgetDialogService', () => {
let service: AttachFileWidgetDialogService;
let materialDialog: MatDialog;
let spyOnDialogOpen: jasmine.Spy;
setupTestBed({
imports: [
CoreModule.forRoot(),
ProcessModule.forRoot()
]
});
beforeEach(() => {
service = TestBed.get(AttachFileWidgetDialogService);
materialDialog = TestBed.get(MatDialog);
spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({
afterOpen: () => of({}),
afterClosed: () => of({}),
componentInstance: {
error: new Subject<any>()
}
});
});
it('should be able to create the service', () => {
expect(service).not.toBeNull();
expect(service).toBeDefined();
});
it('should be able to open the dialog when node has permission', () => {
service.openLogin('fake-title', 'fake-action');
expect(spyOnDialogOpen).toHaveBeenCalled();
});
it('should be able to close the material dialog', () => {
spyOn(materialDialog, 'closeAll');
service.close();
expect(materialDialog.closeAll).toHaveBeenCalled();
});
});

View File

@@ -0,0 +1,76 @@
/*!
* @license
* Copyright 2019 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 { MatDialog } from '@angular/material';
import { EventEmitter, Injectable, Output } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface';
import { Node } from '@alfresco/js-api';
import { AttachFileWidgetDialogComponent } from './attach-file-widget-dialog.component';
@Injectable({
providedIn: 'root'
})
export class AttachFileWidgetDialogService {
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
constructor(private dialog: MatDialog) {
}
/**
* Opens a dialog to choose a file to upload.
* @param action Name of the action to show in the title
* @param contentEntry Item to upload
* @returns Information about the chosen file(s)
*/
openLogin(ecmHost: string, actionName?: string, context?: string): Observable<Node[]> {
const titleString: string = `Please log in for ${ecmHost}`;
const selected = new Subject<Node[]>();
selected.subscribe({
complete: this.close.bind(this)
});
const data: AttachFileWidgetDialogComponentData = {
title : titleString,
actionName,
selected,
ecmHost,
context,
isSelectionValid: this.isNodeFile.bind(this)
};
this.openLoginDialog(data, 'adf-attach-file-widget-dialog', '630px');
return selected;
}
private openLoginDialog(data: AttachFileWidgetDialogComponentData, currentPanelClass: string, chosenWidth: string) {
this.dialog.open(AttachFileWidgetDialogComponent, { data, panelClass: currentPanelClass, width: chosenWidth });
}
/** Closes the currently open dialog. */
close() {
this.dialog.closeAll();
}
private isNodeFile(entry: Node): boolean {
return entry.isFile;
}
}

View File

@@ -0,0 +1,101 @@
<div class="adf-attach-widget {{field.className}}"
[class.adf-invalid]="!field.isValid"
[class.adf-readonly]="field.readOnly">
<label class="adf-label" [attr.for]="field.id">{{field.name}}
<span *ngIf="isRequired()">*</span>
</label>
<div class="adf-attach-widget-container">
<div id="adf-attach-widget-simple-upload" *ngIf="isSimpleUploadButton() && isUploadButtonVisible()">
<a mat-raised-button color="primary">
{{ 'FORM.FIELD.UPLOAD' | translate }}
<mat-icon>file_upload</mat-icon>
<input #uploadFiles
[multiple]="multipleOption"
type="file"
[id]="field.id"
(change)="onAttachFileChanged($event)" />
</a>
</div>
<div class="adf-attach-widget__menu-upload" *ngIf="isUploadButtonVisible() && isMultipleSourceUpload()">
<button mat-raised-button color="primary" [matMenuTriggerFor]="menu" [id]="field.id">
{{ 'FORM.FIELD.UPLOAD' | translate }}
<mat-icon>attach_file</mat-icon>
</button>
<mat-menu #menu="matMenu" class="adf-attach-widget__menu-content">
<button mat-menu-item (click)="uploadFile.click()"
id="attach-local-file"
*ngIf="isAllFileSourceSelected()">
{{ 'FORM.FIELD.LOCALSTORAGE' | translate }}
<mat-icon>file_upload</mat-icon>
<input #uploadFile
class="adf-attach-widget__input-type"
[multiple]="multipleOption"
type="file"
[id]="field.id"
(change)="onAttachFileChanged($event)" />
</button>
<button mat-menu-item
*ngIf="isDefinedSourceFolder()"
id="attach-{{field.params?.fileSource?.name}}"
(click)="openSelectDialogFromFileSource()">
{{field.params?.fileSource?.name}}
<mat-icon>
<img alt="alfresco" class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg">
</mat-icon>
</button>
<div *ngIf="!isDefinedSourceFolder()">
<button mat-menu-item *ngFor="let repo of repositoryList"
id="attach-{{repo?.name}}"
(click)="openSelectDialog(repo)">
{{repo.name}}
<mat-icon>
<img alt="alfresco" class="adf-attach-widget__image-logo" src="../assets/images/alfresco-flower.svg">
</mat-icon>
</button>
</div>
</mat-menu>
</div>
</div>
</div>
<div id="adf-attach-widget-readonly-list">
<mat-list *ngIf="hasFile">
<mat-list-item class="adf-attach-files-row" *ngFor="let file of field.value">
<img mat-list-icon class="adf-attach-widget__icon"
[id]="'file-'+file.id+'-icon'"
[src]="file.content ? getIcon(file.content.mimeType) : getIcon(file.mimeType)"
[alt]="mimeTypeIcon"
(click)="onAttachFileClicked(file)"
(keyup.enter)="onAttachFileClicked(file)"
role="button"
tabindex="0"/>
<span matLine id="{{'file-'+file.id}}" (click)="onAttachFileClicked(file)" (keyup.enter)="onAttachFileClicked(file)"
role="button" tabindex="0" class="adf-file">{{file.name}}</span>
<button id="{{'file-'+file.id+'-option-menu'}}" mat-icon-button [matMenuTriggerFor]="fileActionMenu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #fileActionMenu="matMenu" xPosition="before">
<button id="{{'file-'+file.id+'-show-file'}}"
[disabled]="file.isExternal"
mat-menu-item (click)="onAttachFileClicked(file)">
<mat-icon>image</mat-icon>
<span>{{ 'FORM.FIELD.SHOW_FILE' | translate }}</span>
</button>
<button id="{{'file-'+file.id+'-download-file'}}"
mat-menu-item (click)="downloadContent(file)">
<mat-icon>file_download</mat-icon>
<span>{{ 'FORM.FIELD.DOWNLOAD_FILE' | translate }}</span>
</button>
<button *ngIf="!field.readOnly" id="{{'file-'+file.id+'-remove-file'}}"
mat-menu-item [id]="'file-'+file.id+'-remove'"
(click)="onRemoveAttachFile(file);" (keyup.enter)="onRemoveAttachFile(file);">
<mat-icon class="mat-24">highlight_off</mat-icon>
<span>{{ 'FORM.FIELD.REMOVE_FILE' | translate }}</span>
</button>
</mat-menu>
</mat-list-item>
</mat-list>
</div>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>

View File

@@ -0,0 +1,73 @@
.adf {
&-attach-widget-container {
margin-bottom: 15px;
display: flex;
align-items: center;
input {
cursor: pointer;
height: 100%;
right: 0;
opacity: 0;
position: absolute;
top: 0;
width: 300px;
z-index: 4;
}
}
&-attach-widget__menu-upload {
display: flex;
align-items: center;
}
&-attach-widget__input-type {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
&-attach-widget__image-logo {
padding-left: 5px;
}
&-attach-widget-repo-button {
padding-left: 10px;
.mat-button-wrapper {
display: inline;
}
.mat-mini-fab.mat-accent {
background-color: inherit;
}
}
&-attach-widget {
width: 100%;
word-break: break-all;
padding: 0.4375em 0;
border-top: 0.84375em solid transparent;
}
&-attach-widget__icon {
padding: 6px;
float: left;
cursor: pointer;
}
&-attach-widget__reset {
margin-top: -2px;
}
&-attach-files-row {
.mat-line {
margin-bottom: 0;
}
}
}

View File

@@ -0,0 +1,239 @@
/*!
* @license
* Copyright 2019 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 { Component, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
import {
UploadWidgetComponent,
FormService,
LogService,
ThumbnailService,
ProcessContentService,
ActivitiContentService,
ContentService,
AppConfigValues,
AppConfigService
} from '@alfresco/adf-core';
import { ContentNodeDialogService } from '@alfresco/adf-content-services';
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
import { from, zip, of, Subject } from 'rxjs';
import { mergeMap, takeUntil } from 'rxjs/operators';
import { AttachFileWidgetDialogService } from './attach-file-widget-dialog.service';
@Component({
selector: 'attach-widget',
templateUrl: './attach-file-widget.component.html',
styleUrls: ['./attach-file-widget.component.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
'(change)': 'event($event)',
'(focus)': 'event($event)',
'(focusin)': 'event($event)',
'(focusout)': 'event($event)',
'(input)': 'event($event)',
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
encapsulation: ViewEncapsulation.None
})
export class AttachFileWidgetComponent extends UploadWidgetComponent implements OnInit, OnDestroy {
repositoryList = [];
private tempFilesList = [];
private onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private logger: LogService,
public thumbnails: ThumbnailService,
public processContentService: ProcessContentService,
private activitiContentService: ActivitiContentService,
private contentService: ContentService,
private contentDialog: ContentNodeDialogService,
private appConfigService: AppConfigService,
private attachDialogService: AttachFileWidgetDialogService) {
super(formService, logger, thumbnails, processContentService);
}
ngOnInit() {
super.ngOnInit();
this.activitiContentService.getAlfrescoRepositories(null, true).subscribe((repoList) => {
this.repositoryList = repoList;
});
this.formService.taskSaved
.pipe(takeUntil(this.onDestroy$))
.subscribe(formSaved => {
if (formSaved.form.id === this.field.form.id) {
this.tempFilesList = [];
}
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
isFileSourceConfigured(): boolean {
return !!this.field.params && !!this.field.params.fileSource;
}
isMultipleSourceUpload(): boolean {
return !this.field.readOnly && this.isFileSourceConfigured() && !this.isOnlyLocalSourceSelected();
}
isAllFileSourceSelected(): boolean {
return this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === 'all-file-sources';
}
isOnlyLocalSourceSelected(): boolean {
return this.field.params &&
this.field.params.fileSource &&
this.field.params.fileSource.serviceId === 'local-file';
}
isSimpleUploadButton(): boolean {
return this.isUploadButtonVisible() &&
!this.isFileSourceConfigured() ||
this.isOnlyLocalSourceSelected();
}
isUploadButtonVisible(): boolean {
return (!this.hasFile || this.multipleOption) && !this.field.readOnly;
}
isDefinedSourceFolder(): boolean {
return !!this.field.params &&
!!this.field.params.fileSource &&
!!this.field.params.fileSource.selectedFolder;
}
isTemporaryFile(file): boolean {
return this.tempFilesList.findIndex((elem) => elem.name === file.name) >= 0;
}
openSelectDialogFromFileSource() {
const params = this.field.params;
if (this.isDefinedSourceFolder()) {
this.contentDialog.openFileBrowseDialogByFolderId(params.fileSource.selectedFolder.pathId).subscribe(
(selections: Node[]) => {
this.tempFilesList.push(...selections);
this.uploadFileFromCS(selections,
this.field.params.fileSource.selectedFolder.accountId,
this.field.params.fileSource.selectedFolder.siteId);
});
}
}
onAttachFileChanged(event: any) {
this.tempFilesList.push(...Array.from(event.target.files));
this.onFileChanged(event);
}
onRemoveAttachFile(file: File | RelatedContentRepresentation) {
if (this.isTemporaryFile(file)) {
this.tempFilesList.splice(this.tempFilesList.indexOf((<RelatedContentRepresentation> file).contentBlob), 1);
}
this.removeFile(file);
}
onAttachFileClicked(file: any) {
if (file.isExternal) {
this.logger.info(`The file ${file.name} comes from an external source and cannot be showed at this moment`);
return;
}
if (this.isTemporaryFile(file)) {
this.formService.formContentClicked.next(file);
} else {
this.fileClicked(file);
}
}
downloadContent(file: any | RelatedContentRepresentation): void {
if (this.isTemporaryFile(file)) {
this.contentService.downloadBlob((<RelatedContentRepresentation> file).contentBlob, file.name);
} else {
this.processContentService.getFileRawContent((<any> file).id).subscribe(
(blob: Blob) => {
this.contentService.downloadBlob(blob, (<any> file).name);
},
() => {
this.logger.error('Impossible retrieve content for download');
}
);
}
}
openSelectDialog(repository) {
const accountIdentifier = 'alfresco-' + repository.id + '-' + repository.name;
const currentECMHost = this.getDomainHost(this.appConfigService.get(AppConfigValues.ECMHOST));
const chosenRepositoryHost = this.getDomainHost(repository.repositoryUrl);
if (chosenRepositoryHost !== currentECMHost) {
const formattedRepositoryHost = repository.repositoryUrl.replace('/alfresco', '');
this.attachDialogService.openLogin(formattedRepositoryHost).subscribe(
(selections: any[]) => {
selections.forEach((node) => node.isExternal = true);
this.tempFilesList.push(...selections);
this.uploadFileFromCS(selections, accountIdentifier);
});
} else {
this.contentDialog.openFileBrowseDialogBySite().subscribe(
(selections: Node[]) => {
this.tempFilesList.push(...selections);
this.uploadFileFromCS(selections, accountIdentifier);
});
}
}
private uploadFileFromCS(fileNodeList: any[], accountId: string, siteId?: string) {
const filesSaved = [];
from(fileNodeList).pipe(
mergeMap((node) =>
zip(
of(node.content.mimeType),
this.activitiContentService.applyAlfrescoNode(node, siteId, accountId),
of(node.isExternal)
)
)
)
.subscribe(([mimeType, res, isExternal]) => {
res.mimeType = mimeType;
res.isExternal = isExternal;
filesSaved.push(res);
},
(error) => {
this.logger.error(error);
},
() => {
const previousFiles = this.field.value;
this.field.value = [ ...previousFiles, ...filesSaved ];
this.field.json.value = [ ...previousFiles, ...filesSaved ];
this.hasFile = true;
});
}
private getDomainHost(urlToCheck) {
const result = urlToCheck.match('^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/?\n]+)');
return result[1];
}
}

View File

@@ -0,0 +1,373 @@
/*!
* @license
* Copyright 2019 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 { AttachFileWidgetComponent } from './attach-file-widget.component';
import {
FormFieldModel,
FormModel,
FormFieldTypes,
FormService,
ProcessContentService,
ActivitiContentService,
FormFieldMetadata,
ContentService,
setupTestBed
} from '@alfresco/adf-core';
import { ContentNodeDialogService, ContentModule } from '@alfresco/adf-content-services';
import { of } from 'rxjs';
import { Node } from '@alfresco/js-api';
import { ProcessTestingModule } from '../testing/process.testing.module';
const fakeRepositoryListAnswer = [
{
'authorized': true,
'serviceId': 'alfresco-9999-SHAREME',
'metaDataAllowed': true,
'name': 'SHAREME',
'repositoryUrl' : 'http://localhost:0000/SHAREME'
},
{
'authorized': true,
'serviceId': 'alfresco-0000-GOKUSHARE',
'metaDataAllowed': true,
'name': 'GOKUSHARE',
'repositoryUrl' : 'http://localhost:0000/GOKUSHARE'
}];
const onlyLocalParams = {
fileSource : {
serviceId: 'local-file'
}
};
const allSourceParams = {
fileSource : {
serviceId: 'all-file-sources'
}
};
const definedSourceParams = {
fileSource : {
serviceId: 'goku-sources',
name: 'pippo-baudo',
selectedFolder: {
accountId: 'goku-share-account-id'
}
}
};
const fakeMinimalNode: Node = <Node> {
id: 'fake',
name: 'fake-name',
content: {
mimeType: 'application/pdf'
}
};
const fakePngUpload = {
'id': 1166,
'name': 'fake-png.png',
'created': '2017-07-25T17:17:37.099Z',
'createdBy': {'id': 1001, 'firstName': 'Admin', 'lastName': 'admin', 'email': 'admin'},
'relatedContent': false,
'contentAvailable': true,
'link': false,
'mimeType': 'image/png',
'simpleType': 'image',
'previewStatus': 'queued',
'thumbnailStatus': 'queued'
};
const fakePngAnswer = {
'id': 1155,
'name': 'a_png_file.png',
'created': '2017-07-25T17:17:37.099Z',
'createdBy': {'id': 1001, 'firstName': 'Admin', 'lastName': 'admin', 'email': 'admin'},
'relatedContent': false,
'contentAvailable': true,
'link': false,
'mimeType': 'image/png',
'simpleType': 'image',
'previewStatus': 'queued',
'thumbnailStatus': 'queued'
};
describe('AttachFileWidgetComponent', () => {
let widget: AttachFileWidgetComponent;
let fixture: ComponentFixture<AttachFileWidgetComponent>;
let element: HTMLInputElement;
let activitiContentService: ActivitiContentService;
let contentNodeDialogService: ContentNodeDialogService;
let processContentService: ProcessContentService;
let contentService: ContentService;
let formService: FormService;
setupTestBed({
imports: [
ProcessTestingModule,
ContentModule.forRoot()
]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(AttachFileWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
activitiContentService = TestBed.get(ActivitiContentService);
contentNodeDialogService = TestBed.get(ContentNodeDialogService);
processContentService = TestBed.get(ProcessContentService);
contentService = TestBed.get(ContentService);
formService = TestBed.get(FormService);
}));
afterEach(() => {
fixture.destroy();
});
it('should be able to create the widget', () => {
expect(widget).not.toBeNull();
});
it('should show up as simple upload when is configured for only local files', async(() => {
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'simple-upload-button';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#simple-upload-button')).not.toBeNull();
});
}));
it('should show up all the repository option on menu list', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
fixture.detectChanges();
fixture.whenRenderingDone().then(() => {
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach');
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeNull();
expect(fixture.debugElement.queryAll(By.css('#attach-local-file'))).not.toBeUndefined();
expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeNull();
expect(fixture.debugElement.queryAll(By.css('#attach-SHAREME'))).not.toBeUndefined();
expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeNull();
expect(fixture.debugElement.queryAll(By.css('#attach-GOKUSHARE'))).not.toBeUndefined();
});
});
}));
it('should be able to upload files coming from content node selector', async(() => {
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of(fakePngAnswer));
spyOn(contentNodeDialogService, 'openFileBrowseDialogBySite').and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach');
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.detectChanges();
fixture.debugElement.query(By.css('#attach-SHAREME')).nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
});
}));
it('should be able to upload more than one file from content node selector', async(() => {
const clickAttachFile = () => {
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach');
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.detectChanges();
};
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValues(of(fakePngAnswer), of(fakePngUpload));
spyOn(contentNodeDialogService, 'openFileBrowseDialogBySite').and.returnValue(of([fakeMinimalNode]));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> allSourceParams;
widget.field.params.multiple = true;
fixture.detectChanges();
fixture.whenStable().then(() => {
clickAttachFile();
fixture.debugElement.query(By.css('#attach-SHAREME')).nativeElement.click();
fixture.detectChanges();
clickAttachFile();
fixture.debugElement.query(By.css('#attach-GOKUSHARE')).nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155')).not.toBeNull();
expect(element.querySelector('#file-1166')).not.toBeNull();
});
});
}));
it('should be able to upload files when a defined folder is selected', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> definedSourceParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(fakeRepositoryListAnswer));
spyOn(activitiContentService, 'applyAlfrescoNode').and.returnValue(of(fakePngAnswer));
spyOn(contentNodeDialogService, 'openFileBrowseDialogByFolderId').and.returnValue(of([fakeMinimalNode]));
fixture.detectChanges();
fixture.whenStable().then(() => {
const attachButton: HTMLButtonElement = element.querySelector('#attach-file-attach');
expect(attachButton).not.toBeNull();
attachButton.click();
fixture.detectChanges();
fixture.debugElement.query(By.css('#attach-pippo-baudo')).nativeElement.click();
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
it('should be able to upload files from local source', async(() => {
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer));
fixture.detectChanges();
fixture.whenStable().then(() => {
const inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach'));
inputDebugElement.triggerEventHandler('change', { target: { files: [fakePngAnswer] } });
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
it('should display file list when field has value', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: [fakePngAnswer]
});
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
describe('when a file is uploaded', () => {
beforeEach(async(() => {
widget.field = new FormFieldModel(new FormModel(), {
type: FormFieldTypes.UPLOAD,
value: []
});
widget.field.id = 'attach-file-attach';
widget.field.params = <FormFieldMetadata> onlyLocalParams;
spyOn(activitiContentService, 'getAlfrescoRepositories').and.returnValue(of(null));
spyOn(processContentService, 'createTemporaryRawRelatedContent').and.returnValue(of(fakePngAnswer));
fixture.detectChanges();
fixture.whenStable().then(() => {
const inputDebugElement = fixture.debugElement.query(By.css('#attach-file-attach'));
inputDebugElement.triggerEventHandler('change', {target: {files: [fakePngAnswer]}});
fixture.detectChanges();
expect(element.querySelector('#file-1155-icon')).not.toBeNull();
});
}));
it('should show the action menu', async(() => {
const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu');
expect(menuButton).not.toBeNull();
menuButton.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.debugElement.query(By.css('#file-1155-show-file'))).not.toBeNull();
expect(fixture.debugElement.query(By.css('#file-1155-download-file'))).not.toBeNull();
expect(fixture.debugElement.query(By.css('#file-1155-remove'))).not.toBeNull();
});
}));
it('should remove file when remove is clicked', async(() => {
const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu');
expect(menuButton).not.toBeNull();
menuButton.click();
fixture.detectChanges();
const removeOption: HTMLButtonElement = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-remove')).nativeElement;
removeOption.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#file-1155')).toBeNull();
});
}));
it('should download file when download is clicked', async(() => {
spyOn(contentService, 'downloadBlob').and.stub();
const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu');
expect(menuButton).not.toBeNull();
menuButton.click();
fixture.detectChanges();
const downloadOption: HTMLButtonElement = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-download-file')).nativeElement;
downloadOption.click();
fixture.whenStable().then(() => {
expect(contentService.downloadBlob).toHaveBeenCalled();
});
}));
it('should raise formContentClicked event when show file is clicked', async(() => {
spyOn(processContentService, 'getFileRawContent').and.returnValue(of(fakePngAnswer));
formService.formContentClicked.subscribe((file) => {
expect(file).not.toBeNull();
expect(file.id).toBe(1155);
});
const menuButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#file-1155-option-menu');
expect(menuButton).not.toBeNull();
menuButton.click();
fixture.detectChanges();
const showOption: HTMLButtonElement = <HTMLButtonElement> fixture.debugElement.query(By.css('#file-1155-show-file')).nativeElement;
showOption.click();
}));
});
});

View File

@@ -0,0 +1,30 @@
<div class="adf-attach-folder-widget {{field.className}}"
[class.adf-invalid]="!field.isValid"
[class.adf-readonly]="field.readOnly">
<label class="adf-label" [attr.for]="field.id">{{field.name}}<span *ngIf="isRequired()">*</span></label>
<div class="adf-attach-folder-widget-container">
<div *ngIf="hasFolder" class="adf-attach-folder-result">
<mat-icon>folder</mat-icon>
<div class="adf-attach-folder-files-row">
<span matLine id="{{'folder-'+field?.id}}"
role="button" tabindex="0" class="adf-folder">{{selectedFolderName}}</span>
<button *ngIf="!field.readOnly" mat-icon-button [id]="'folder-'+field?.id+'-remove'"
(click)="removeFolder();">
<mat-icon class="mat-24">highlight_off</mat-icon>
</button>
</div>
</div>
<div *ngIf="!hasFolder && !field.readOnly">
<button mat-raised-button
color="primary"
(click)="openSelectDialogFromFileSource()"
[id]="'folder-'+field?.id+'-button'">
{{ 'FORM.FIELD.UPLOAD' | translate }}
<mat-icon>cloud_upload</mat-icon>
</button>
</div>
</div>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>

View File

@@ -0,0 +1,39 @@
.adf {
&-attach-folder-widget-container {
margin-bottom: 15px;
display: flex;
align-items: center;
input {
cursor: pointer;
height: 100%;
right: 0;
opacity: 0;
position: absolute;
top: 0;
width: 300px;
z-index: 4;
}
}
&-attach-folder-widget {
width: 100%;
word-break: break-all;
padding: 0.4375em 0;
border-top: 0.84375em solid transparent;
}
&-attach-folder-files-row {
padding-left: 8px;
.mat-line {
margin-bottom: 0;
}
}
&-attach-folder-result {
display: flex;
align-items: center;
}
}

View File

@@ -0,0 +1,154 @@
/*!
* @license
* Copyright 2019 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 { AttachFolderWidgetComponent } from './attach-folder-widget.component';
import {
FormFieldModel,
FormModel,
NodesApiService,
setupTestBed
} from '@alfresco/adf-core';
import { ContentNodeDialogService } from '@alfresco/adf-content-services';
import { of } from 'rxjs';
import { Node } from '@alfresco/js-api';
import { ProcessTestingModule } from '../testing/process.testing.module';
const fakeMinimalNode: Node = <Node> {
id: 'fake',
name: 'fake-name'
};
const definedSourceParams = {
folderSource : {
serviceId: 'goofy-sources',
name: 'pippo-baudo',
selectedFolder: {
accountId: 'goku-share-account-id',
pathId: 'fake-pippo-baudo-id'
}
}
};
describe('AttachFolderWidgetComponent', () => {
let widget: AttachFolderWidgetComponent;
let fixture: ComponentFixture<AttachFolderWidgetComponent>;
let element: HTMLInputElement;
let contentNodeDialogService: ContentNodeDialogService;
let nodeService: NodesApiService;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(AttachFolderWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
contentNodeDialogService = TestBed.get(ContentNodeDialogService);
nodeService = TestBed.get(NodesApiService);
}));
afterEach(() => {
fixture.destroy();
});
it('should be able to create the widget', () => {
expect(widget).not.toBeNull();
});
it('should be rendered correctly', () => {
expect(widget).not.toBeNull();
widget.field = new FormFieldModel(new FormModel(), {
type: 'select-folder',
id: 'fake-widget',
value: null
});
fixture.detectChanges();
expect(element.querySelector('#folder-fake-widget-button')).toBeDefined();
expect(element.querySelector('#folder-fake-widget-button')).not.toBeNull();
});
it('should show the folder selected by content node', async(() => {
spyOn(contentNodeDialogService, 'openFolderBrowseDialogBySite').and.returnValue(of([fakeMinimalNode]));
expect(widget).not.toBeNull();
widget.field = new FormFieldModel(new FormModel(), {
type: 'select-folder',
id: 'fake-widget',
value: null
});
fixture.detectChanges();
fixture.debugElement.query(By.css('#folder-fake-widget-button')).nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#folder-fake-widget')).not.toBeNull();
});
}));
it('should show the folder selected by content node opening on a configured folder', async(() => {
spyOn(contentNodeDialogService, 'openFolderBrowseDialogByFolderId').and.returnValue(of([fakeMinimalNode]));
expect(widget).not.toBeNull();
widget.field = new FormFieldModel(new FormModel(), {
type: 'select-folder',
id: 'fake-widget',
value: null,
params: definedSourceParams
});
fixture.detectChanges();
fixture.debugElement.query(By.css('#folder-fake-widget-button')).nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#folder-fake-widget')).not.toBeNull();
});
}));
it('should retrieve the node information on init', async(() => {
spyOn(nodeService, 'getNode').and.returnValue(of(fakeMinimalNode));
expect(widget).not.toBeNull();
widget.field = new FormFieldModel(new FormModel(), {
type: 'select-folder',
id: 'fake-widget',
value: 'fake-pippo-baudo-id'
});
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#folder-fake-widget')).not.toBeNull();
expect(element.querySelector('#folder-fake-widget-button')).toBeNull();
});
}));
it('should remove the folder via the remove button', async(() => {
spyOn(nodeService, 'getNode').and.returnValue(of(fakeMinimalNode));
expect(widget).not.toBeNull();
widget.field = new FormFieldModel(new FormModel(), {
type: 'select-folder',
id: 'fake-widget',
value: 'fake-pippo-baudo-id'
});
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(element.querySelector('#folder-fake-widget')).not.toBeNull();
expect(element.querySelector('#folder-fake-widget-button')).toBeNull();
fixture.debugElement.query(By.css('#folder-fake-widget-remove')).nativeElement.click();
fixture.detectChanges();
expect(element.querySelector('#folder-fake-widget')).toBeNull();
});
}));
});

View File

@@ -0,0 +1,98 @@
/*!
* @license
* Copyright 2019 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 { Component, ViewEncapsulation, OnInit } from '@angular/core';
import {
WidgetComponent,
FormService,
NodesApiService
} from '@alfresco/adf-core';
import { ContentNodeDialogService } from '@alfresco/adf-content-services';
import { Node } from '@alfresco/js-api';
@Component({
selector: 'attach-folder-widget',
templateUrl: './attach-folder-widget.component.html',
styleUrls: ['./attach-folder-widget.component.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
'(change)': 'event($event)',
'(focus)': 'event($event)',
'(focusin)': 'event($event)',
'(focusout)': 'event($event)',
'(input)': 'event($event)',
'(invalid)': 'event($event)',
'(select)': 'event($event)'
},
encapsulation: ViewEncapsulation.None
})
export class AttachFolderWidgetComponent extends WidgetComponent implements OnInit {
hasFolder: boolean = false;
selectedFolderName: string = '';
constructor(private contentDialog: ContentNodeDialogService,
public formService: FormService,
private nodeService: NodesApiService) {
super();
}
ngOnInit() {
if (this.field &&
this.field.value) {
this.hasFolder = true;
this.nodeService.getNode(this.field.value).subscribe((node: Node) => {
this.selectedFolderName = node.name;
});
}
}
isDefinedSourceFolder(): boolean {
return !!this.field.params &&
!!this.field.params.folderSource &&
!!this.field.params.folderSource.selectedFolder;
}
openSelectDialogFromFileSource() {
const params = this.field.params;
if (this.isDefinedSourceFolder()) {
this.contentDialog.openFolderBrowseDialogByFolderId(params.folderSource.selectedFolder.pathId).subscribe(
(selections: Node[]) => {
this.selectedFolderName = selections[0].name;
this.field.value = selections[0].id;
this.hasFolder = true;
});
} else {
this.contentDialog.openFolderBrowseDialogBySite().subscribe(
(selections: Node[]) => {
this.selectedFolderName = selections[0].name;
this.field.value = selections[0].id;
this.hasFolder = true;
});
}
}
removeFolder() {
this.field.value = null;
this.selectedFolderName = '';
this.hasFolder = false;
}
}

View File

@@ -0,0 +1,49 @@
/*!
* @license
* Copyright 2019 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 { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { ContentNodeSelectorModule } from '@alfresco/adf-content-services';
import { AttachFileWidgetComponent } from './attach-file-widget.component';
import { AttachFolderWidgetComponent } from './attach-folder-widget.component';
import { AttachFileWidgetDialogComponent } from './attach-file-widget-dialog.component';
@NgModule({
imports: [
CoreModule,
ContentNodeSelectorModule,
MaterialModule
],
entryComponents: [
AttachFileWidgetComponent,
AttachFolderWidgetComponent,
AttachFileWidgetDialogComponent
],
declarations: [
AttachFileWidgetComponent,
AttachFolderWidgetComponent,
AttachFileWidgetDialogComponent
],
exports: [
AttachFileWidgetComponent,
AttachFolderWidgetComponent,
AttachFileWidgetDialogComponent
]
})
export class ContentWidgetModule {}

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './public-api';

View File

@@ -0,0 +1,24 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './attach-file-widget.component';
export * from './attach-folder-widget.component';
export * from './attach-file-widget-dialog-component.interface';
export * from './attach-file-widget-dialog.component';
export * from './attach-file-widget-dialog.service';
export * from './content-widget.module';

View File

@@ -0,0 +1,46 @@
<div *ngIf="!hasForm()">
<ng-content select="[empty-form]">
</ng-content>
</div>
<div *ngIf="hasForm()" class="adf-form-container">
<mat-card>
<mat-card-header>
<mat-card-title>
<h4>
<div *ngIf="showValidationIcon" class="adf-form-validation-button">
<i id="adf-valid-form-icon" class="material-icons"
*ngIf="form.isValid; else no_valid_form">check_circle</i>
<ng-template #no_valid_form>
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
</ng-template>
</div>
<div *ngIf="showRefreshButton" class="adf-form-reload-button">
<button mat-icon-button (click)="onRefreshClicked()">
<mat-icon>refresh</mat-icon>
</button>
</div>
<span *ngIf="isTitleEnabled()" class="adf-form-title">
{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
</ng-container>
</span>
</h4>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<adf-form-renderer [formDefinition]="form">
</adf-form-renderer>
</mat-card-content>
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions">
<button [id]="'adf-form-'+ outcome.name | formatSpace" *ngFor="let outcome of form.outcomes"
[color]="getColorForOutcome(outcome.name)" mat-button [disabled]="!isOutcomeButtonEnabled(outcome)"
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
(click)="onOutcomeClicked(outcome)">
{{outcome.name | translate | uppercase }}
</button>
</mat-card-actions>
</mat-card>
</div>

View File

@@ -0,0 +1,950 @@
/*!
* @license
* Copyright 2019 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 { SimpleChange } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { FormFieldModel, FormFieldTypes, FormModel, FormOutcomeEvent, FormOutcomeModel,
FormService, WidgetVisibilityService, NodeService, LogService, ContainerModel, fakeForm, FormRenderingService } from '@alfresco/adf-core';
import { FormComponent } from './form.component';
describe('FormComponent', () => {
let formService: FormService;
let formComponent: FormComponent;
let visibilityService: WidgetVisibilityService;
let nodeService: NodeService;
let logService: LogService;
let formRenderingService: FormRenderingService;
beforeEach(() => {
logService = new LogService(null);
visibilityService = new WidgetVisibilityService(null, logService);
spyOn(visibilityService, 'refreshVisibility').and.stub();
formService = new FormService(null, null, logService);
nodeService = new NodeService(null);
formRenderingService = new FormRenderingService();
formComponent = new FormComponent(formService, visibilityService, null, nodeService, formRenderingService);
});
it('should check form', () => {
expect(formComponent.hasForm()).toBeFalsy();
formComponent.form = new FormModel();
expect(formComponent.hasForm()).toBeTruthy();
});
it('should allow title if task name available', () => {
const formModel = new FormModel();
formComponent.form = formModel;
expect(formComponent.showTitle).toBeTruthy();
expect(formModel.taskName).toBe(FormModel.UNSET_TASK_NAME);
expect(formComponent.isTitleEnabled()).toBeTruthy();
formComponent.form = null;
expect(formComponent.isTitleEnabled()).toBeFalsy();
});
it('should not allow title', () => {
const formModel = new FormModel();
formComponent.form = formModel;
formComponent.showTitle = false;
expect(formModel.taskName).toBe(FormModel.UNSET_TASK_NAME);
expect(formComponent.isTitleEnabled()).toBeFalsy();
});
it('should return primary color for complete button', () => {
expect(formComponent.getColorForOutcome('COMPLETE')).toBe('primary');
});
it('should not enable outcome button when model missing', () => {
expect(formComponent.isOutcomeButtonVisible(null, false)).toBeFalsy();
});
it('should enable custom outcome buttons', () => {
const formModel = new FormModel();
formComponent.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' });
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
});
it('should allow controlling [complete] button visibility', () => {
const formModel = new FormModel();
formComponent.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
formComponent.showSaveButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
formComponent.showSaveButton = false;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
});
it('should show only [complete] button with readOnly form ', () => {
const formModel = new FormModel();
formModel.readOnly = true;
formComponent.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION });
formComponent.showCompleteButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
});
it('should not show [save] button with readOnly form ', () => {
const formModel = new FormModel();
formModel.readOnly = true;
formComponent.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
formComponent.showSaveButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
});
it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => {
const formModel = new FormModel({ selectedOutcome: 'custom-outcome' });
formModel.readOnly = true;
formComponent.form = formModel;
let outcome = new FormOutcomeModel(formModel, { id: '$customoutome', name: 'custom-outcome' });
formComponent.showCompleteButton = true;
formComponent.showSaveButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
outcome = new FormOutcomeModel(formModel, { id: '$customoutome2', name: 'custom-outcome2' });
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
});
it('should allow controlling [save] button visibility', () => {
const formModel = new FormModel();
formModel.readOnly = false;
formComponent.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION });
formComponent.showCompleteButton = true;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeTruthy();
formComponent.showCompleteButton = false;
expect(formComponent.isOutcomeButtonVisible(outcome, formComponent.form.readOnly)).toBeFalsy();
});
it('should load form on refresh', () => {
spyOn(formComponent, 'loadForm').and.stub();
formComponent.onRefreshClicked();
expect(formComponent.loadForm).toHaveBeenCalled();
});
it('should get form by task id on load', () => {
spyOn(formComponent, 'getFormByTaskId').and.stub();
const taskId = '123';
formComponent.taskId = taskId;
formComponent.loadForm();
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
});
it('should get process variable if is a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(of({}));
spyOn(formService, 'getTask').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: '10201' });
observer.complete();
});
});
const taskId = '123';
formComponent.taskId = taskId;
formComponent.loadForm();
expect(visibilityService.getTaskProcessVariable).toHaveBeenCalledWith(taskId);
});
it('should not get process variable if is not a process task', () => {
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
spyOn(visibilityService, 'getTaskProcessVariable').and.returnValue(of({}));
spyOn(formService, 'getTask').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId, processDefinitionId: 'null' });
observer.complete();
});
});
const taskId = '123';
formComponent.taskId = taskId;
formComponent.loadForm();
expect(visibilityService.getTaskProcessVariable).toHaveBeenCalledWith(taskId);
});
it('should get form definition by form id on load', () => {
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
const formId = 123;
formComponent.formId = formId;
formComponent.loadForm();
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
});
it('should refresh visibility when the form is loaded', () => {
spyOn(formService, 'getFormDefinitionById').and.returnValue(of(JSON.parse(JSON.stringify(fakeForm))));
const formId = 123;
formComponent.formId = formId;
formComponent.loadForm();
expect(formService.getFormDefinitionById).toHaveBeenCalledWith(formId);
expect(visibilityService.refreshVisibility).toHaveBeenCalled();
});
it('should get form definition by form name on load', () => {
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
const formName = '<form>';
formComponent.formName = formName;
formComponent.loadForm();
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
});
it('should reload form by task id on binding changes', () => {
spyOn(formComponent, 'getFormByTaskId').and.stub();
const taskId = '<task id>';
const change = new SimpleChange(null, taskId, true);
formComponent.ngOnChanges({ 'taskId': change });
expect(formComponent.getFormByTaskId).toHaveBeenCalledWith(taskId);
});
it('should reload form definition by form id on binding changes', () => {
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
const formId = '123';
const change = new SimpleChange(null, formId, true);
formComponent.ngOnChanges({ 'formId': change });
expect(formComponent.getFormDefinitionByFormId).toHaveBeenCalledWith(formId);
});
it('should reload form definition by name on binding changes', () => {
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
const formName = '<form>';
const change = new SimpleChange(null, formName, true);
formComponent.ngOnChanges({ 'formName': change });
expect(formComponent.getFormDefinitionByFormName).toHaveBeenCalledWith(formName);
});
it('should not get form on load', () => {
spyOn(formComponent, 'getFormByTaskId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
formComponent.taskId = null;
formComponent.formId = null;
formComponent.formName = null;
formComponent.loadForm();
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormName).not.toHaveBeenCalled();
});
it('should not reload form on binding changes', () => {
spyOn(formComponent, 'getFormByTaskId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormId').and.stub();
spyOn(formComponent, 'getFormDefinitionByFormName').and.stub();
formComponent.ngOnChanges({ 'tag': new SimpleChange(null, 'hello world', true) });
expect(formComponent.getFormByTaskId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormId).not.toHaveBeenCalled();
expect(formComponent.getFormDefinitionByFormName).not.toHaveBeenCalled();
});
it('should complete form on custom outcome click', () => {
const formModel = new FormModel();
const outcomeName = 'Custom Action';
const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
let saved = false;
formComponent.form = formModel;
formComponent.formSaved.subscribe(() => saved = true);
spyOn(formComponent, 'completeTaskForm').and.stub();
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeTruthy();
expect(saved).toBeTruthy();
expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcomeName);
});
it('should save form on [save] outcome click', () => {
const formModel = new FormModel();
const outcome = new FormOutcomeModel(formModel, {
id: FormComponent.SAVE_OUTCOME_ID,
name: 'Save',
isSystem: true
});
formComponent.form = formModel;
spyOn(formComponent, 'saveTaskForm').and.stub();
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeTruthy();
expect(formComponent.saveTaskForm).toHaveBeenCalled();
});
it('should complete form on [complete] outcome click', () => {
const formModel = new FormModel();
const outcome = new FormOutcomeModel(formModel, {
id: FormComponent.COMPLETE_OUTCOME_ID,
name: 'Complete',
isSystem: true
});
formComponent.form = formModel;
spyOn(formComponent, 'completeTaskForm').and.stub();
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeTruthy();
expect(formComponent.completeTaskForm).toHaveBeenCalled();
});
it('should emit form saved event on custom outcome click', () => {
const formModel = new FormModel();
const outcome = new FormOutcomeModel(formModel, {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom',
isSystem: true
});
let saved = false;
formComponent.form = formModel;
formComponent.formSaved.subscribe(() => saved = true);
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeTruthy();
expect(saved).toBeTruthy();
});
it('should do nothing when clicking outcome for readonly form', () => {
const formModel = new FormModel();
const outcomeName = 'Custom Action';
const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
formComponent.form = formModel;
spyOn(formComponent, 'completeTaskForm').and.stub();
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
formComponent.readOnly = true;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
});
it('should require outcome model when clicking outcome', () => {
formComponent.form = new FormModel();
formComponent.readOnly = false;
expect(formComponent.onOutcomeClicked(null)).toBeFalsy();
});
it('should require loaded form when clicking outcome', () => {
const formModel = new FormModel();
const outcomeName = 'Custom Action';
const outcome = new FormOutcomeModel(formModel, { id: 'custom1', name: outcomeName });
formComponent.readOnly = false;
formComponent.form = null;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
});
it('should not execute unknown system outcome', () => {
const formModel = new FormModel();
const outcome = new FormOutcomeModel(formModel, { id: 'unknown', name: 'Unknown', isSystem: true });
formComponent.form = formModel;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
});
it('should require custom action name to complete form', () => {
const formModel = new FormModel();
let outcome = new FormOutcomeModel(formModel, { id: 'custom' });
formComponent.form = formModel;
expect(formComponent.onOutcomeClicked(outcome)).toBeFalsy();
outcome = new FormOutcomeModel(formModel, { id: 'custom', name: 'Custom' });
spyOn(formComponent, 'completeTaskForm').and.stub();
expect(formComponent.onOutcomeClicked(outcome)).toBeTruthy();
});
it('should fetch and parse form by task id', (done) => {
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formService, 'getTaskForm').and.callFake((currentTaskId) => {
return new Observable((observer) => {
observer.next({ taskId: currentTaskId });
observer.complete();
});
});
const taskId = '456';
formComponent.formLoaded.subscribe(() => {
expect(formService.getTaskForm).toHaveBeenCalledWith(taskId);
expect(formComponent.form).toBeDefined();
expect(formComponent.form.taskId).toBe(taskId);
done();
});
expect(formComponent.form).toBeUndefined();
formComponent.getFormByTaskId(taskId);
});
it('should handle error when getting form by task id', (done) => {
const error = 'Some error';
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formComponent, 'handleError').and.stub();
spyOn(formService, 'getTaskForm').and.callFake(() => {
return throwError(error);
});
formComponent.getFormByTaskId('123').then((_) => {
expect(formComponent.handleError).toHaveBeenCalledWith(error);
done();
});
});
it('should apply readonly state when getting form by task id', (done) => {
spyOn(formService, 'getTask').and.returnValue(of({}));
spyOn(formService, 'getTaskForm').and.callFake((taskId) => {
return new Observable((observer) => {
observer.next({ taskId: taskId });
observer.complete();
});
});
formComponent.readOnly = true;
formComponent.getFormByTaskId('123').then((_) => {
expect(formComponent.form).toBeDefined();
expect(formComponent.form.readOnly).toBe(true);
done();
});
});
it('should fetch and parse form definition by id', () => {
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormId) => {
return new Observable((observer) => {
observer.next({ id: currentFormId });
observer.complete();
});
});
const formId = 456;
let loaded = false;
formComponent.formLoaded.subscribe(() => loaded = true);
expect(formComponent.form).toBeUndefined();
formComponent.getFormDefinitionByFormId(formId);
expect(loaded).toBeTruthy();
expect(formComponent.form).toBeDefined();
expect(formComponent.form.id).toBe(formId);
});
it('should handle error when getting form by definition id', () => {
const error = 'Some error';
spyOn(formComponent, 'handleError').and.stub();
spyOn(formService, 'getFormDefinitionById').and.callFake(() => throwError(error));
formComponent.getFormDefinitionByFormId(123);
expect(formComponent.handleError).toHaveBeenCalledWith(error);
});
it('should fetch and parse form definition by form name', () => {
spyOn(formService, 'getFormDefinitionByName').and.callFake((currentFormName) => {
return new Observable((observer) => {
observer.next(currentFormName);
observer.complete();
});
});
spyOn(formService, 'getFormDefinitionById').and.callFake((currentFormName) => {
return new Observable((observer) => {
observer.next({ name: currentFormName });
observer.complete();
});
});
const formName = '<form>';
let loaded = false;
formComponent.formLoaded.subscribe(() => loaded = true);
expect(formComponent.form).toBeUndefined();
formComponent.getFormDefinitionByFormName(formName);
expect(loaded).toBeTruthy();
expect(formService.getFormDefinitionByName).toHaveBeenCalledWith(formName);
expect(formComponent.form).toBeDefined();
expect(formComponent.form.name).toBe(formName);
});
it('should save task form and raise corresponding event', () => {
spyOn(formService, 'saveTaskForm').and.callFake(() => {
return new Observable((observer) => {
observer.next();
observer.complete();
});
});
let saved = false;
let savedForm = null;
formComponent.formSaved.subscribe((form) => {
saved = true;
savedForm = form;
});
const formModel = new FormModel({
taskId: '123',
fields: [
{ id: 'field1' },
{ id: 'field2' }
]
});
formComponent.form = formModel;
formComponent.saveTaskForm();
expect(formService.saveTaskForm).toHaveBeenCalledWith(formModel.taskId, formModel.values);
expect(saved).toBeTruthy();
expect(savedForm).toEqual(formModel);
});
it('should handle error during form save', () => {
const error = 'Error';
spyOn(formService, 'saveTaskForm').and.callFake(() => throwError(error));
spyOn(formComponent, 'handleError').and.stub();
formComponent.form = new FormModel({ taskId: '123' });
formComponent.saveTaskForm();
expect(formComponent.handleError).toHaveBeenCalledWith(error);
});
it('should require form with task id to save', () => {
spyOn(formService, 'saveTaskForm').and.stub();
formComponent.form = null;
formComponent.saveTaskForm();
formComponent.form = new FormModel();
formComponent.saveTaskForm();
expect(formService.saveTaskForm).not.toHaveBeenCalled();
});
it('should require form with task id to complete', () => {
spyOn(formService, 'completeTaskForm').and.stub();
formComponent.form = null;
formComponent.completeTaskForm('save');
formComponent.form = new FormModel();
formComponent.completeTaskForm('complete');
expect(formService.completeTaskForm).not.toHaveBeenCalled();
});
it('should complete form and raise corresponding event', () => {
spyOn(formService, 'completeTaskForm').and.callFake(() => {
return new Observable((observer) => {
observer.next();
observer.complete();
});
});
const outcome = 'complete';
let completed = false;
formComponent.formCompleted.subscribe(() => completed = true);
const formModel = new FormModel({
taskId: '123',
fields: [
{ id: 'field1' },
{ id: 'field2' }
]
});
formComponent.form = formModel;
formComponent.completeTaskForm(outcome);
expect(formService.completeTaskForm).toHaveBeenCalledWith(formModel.taskId, formModel.values, outcome);
expect(completed).toBeTruthy();
});
it('should require json to parse form', () => {
expect(formComponent.parseForm(null)).toBeNull();
});
it('should parse form from json', () => {
const form = formComponent.parseForm({
id: 1,
fields: [
{ id: 'field1', type: FormFieldTypes.CONTAINER }
]
});
expect(form).toBeDefined();
expect(form.id).toBe(1);
expect(form.fields.length).toBe(1);
expect(form.fields[0].id).toBe('field1');
});
it('should provide outcomes for form definition', () => {
spyOn(formComponent, 'getFormDefinitionOutcomes').and.callThrough();
const form = formComponent.parseForm({ id: 1 });
expect(formComponent.getFormDefinitionOutcomes).toHaveBeenCalledWith(form);
});
it('should prevent default outcome execution', () => {
const outcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom'
});
formComponent.form = new FormModel();
formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
expect(event.outcome).toBe(outcome);
event.preventDefault();
expect(event.defaultPrevented).toBeTruthy();
});
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeFalsy();
});
it('should not prevent default outcome execution', () => {
const outcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom'
});
formComponent.form = new FormModel();
formComponent.executeOutcome.subscribe((event: FormOutcomeEvent) => {
expect(event.outcome).toBe(outcome);
expect(event.defaultPrevented).toBeFalsy();
});
spyOn(formComponent, 'completeTaskForm').and.callThrough();
const result = formComponent.onOutcomeClicked(outcome);
expect(result).toBeTruthy();
expect(formComponent.completeTaskForm).toHaveBeenCalledWith(outcome.name);
});
it('should check visibility only if field with form provided', () => {
formComponent.checkVisibility(null);
expect(visibilityService.refreshVisibility).not.toHaveBeenCalled();
let field = new FormFieldModel(null);
formComponent.checkVisibility(field);
expect(visibilityService.refreshVisibility).not.toHaveBeenCalled();
field = new FormFieldModel(new FormModel());
formComponent.checkVisibility(field);
expect(visibilityService.refreshVisibility).toHaveBeenCalledWith(field.form);
});
it('should load form for ecm node', () => {
const metadata = {};
spyOn(nodeService, 'getNodeMetadata').and.returnValue(
new Observable((observer) => {
observer.next({ metadata: metadata });
observer.complete();
})
);
spyOn(formComponent, 'loadFormFromActiviti').and.stub();
const nodeId = '<id>';
const change = new SimpleChange(null, nodeId, false);
formComponent.ngOnChanges({ 'nodeId': change });
expect(nodeService.getNodeMetadata).toHaveBeenCalledWith(nodeId);
expect(formComponent.loadFormFromActiviti).toHaveBeenCalled();
expect(formComponent.data).toBe(metadata);
});
it('should disable custom outcome buttons for readonly form', () => {
const formModel = new FormModel();
formModel.readOnly = true;
formComponent.form = formModel;
const outcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom'
});
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
});
it('should require outcome to eval button state', () => {
formComponent.form = new FormModel();
expect(formComponent.isOutcomeButtonEnabled(null)).toBeFalsy();
});
it('should disable outcome buttons for invalid form', () => {
const formModel = new FormModel();
const field = new FormFieldModel(formModel, {
type: 'text',
value: null,
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeFalsy();
const outcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom'
});
expect(formComponent.isOutcomeButtonEnabled(outcome)).toBeFalsy();
});
it('should disable complete outcome button when disableCompleteButton is true', () => {
const formModel = new FormModel();
formComponent.form = formModel;
formComponent.disableCompleteButton = true;
const field = new FormFieldModel(formModel, {
type: 'text',
value: 'text',
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeTruthy();
const completeOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.COMPLETE_OUTCOME_ID,
name: FormOutcomeModel.COMPLETE_ACTION
});
expect(formModel.isValid).toBeTruthy();
expect(formComponent.isOutcomeButtonEnabled(completeOutcome)).toBeFalsy();
});
it('should disable save outcome button when form is valid and readOnly', () => {
const formModel = new FormModel();
const field = new FormFieldModel(formModel, {
type: 'text',
value: 'text',
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeTruthy();
const saveOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.SAVE_OUTCOME_ID,
name: FormOutcomeModel.SAVE_ACTION
});
formComponent.form.readOnly = true;
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
});
it('should enable save outcome button when form is valid and not readOnly', () => {
const formModel = new FormModel();
const field = new FormFieldModel(formModel, {
type: 'text',
value: 'text',
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeTruthy();
const saveOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.SAVE_OUTCOME_ID,
name: FormOutcomeModel.SAVE_ACTION
});
formComponent.form.readOnly = false;
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeTruthy();
});
it('should disable save outcome button when disableSaveButton is true', () => {
const formModel = new FormModel();
formComponent.form = formModel;
formComponent.disableSaveButton = true;
const saveOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.SAVE_OUTCOME_ID,
name: FormOutcomeModel.SAVE_ACTION
});
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
});
it('should disable save outcome button when the form is invalid', () => {
const formModel = new FormModel();
formComponent.form = formModel;
const field = new FormFieldModel(formModel, {
type: 'text',
value: null,
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeFalsy();
const saveOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.SAVE_OUTCOME_ID,
name: FormOutcomeModel.SAVE_ACTION
});
expect(formComponent.isOutcomeButtonEnabled(saveOutcome)).toBeFalsy();
});
it('should disable start process outcome button when disableStartProcessButton is true', () => {
const formModel = new FormModel();
formComponent.form = formModel;
formComponent.disableStartProcessButton = true;
const field = new FormFieldModel(formModel, {
type: 'text',
value: 'text',
required: true
});
const containerModel = new ContainerModel(field);
formModel.fields.push(containerModel);
formComponent.form = formModel;
formModel.onFormFieldChanged(field);
expect(formModel.isValid).toBeTruthy();
const startProcessOutcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.START_PROCESS_OUTCOME_ID,
name: FormOutcomeModel.START_PROCESS_ACTION
});
expect(formComponent.isOutcomeButtonEnabled(startProcessOutcome)).toBeFalsy();
});
it('should raise [executeOutcome] event for formService', (done) => {
formService.executeOutcome.subscribe(() => {
done();
});
const outcome = new FormOutcomeModel(new FormModel(), {
id: FormComponent.CUSTOM_OUTCOME_ID,
name: 'Custom'
});
formComponent.form = new FormModel();
formComponent.onOutcomeClicked(outcome);
});
it('should refresh form values when data is changed', () => {
formComponent.form = new FormModel(JSON.parse(JSON.stringify(fakeForm)));
let formFields = formComponent.form.getFormFields();
let labelField = formFields.find((field) => field.id === 'label');
let radioField = formFields.find((field) => field.id === 'radio');
expect(labelField.value).toBe('empty');
expect(radioField.value).toBeNull();
const formValues: any = {};
formValues.label = {
id: 'option_2',
name: 'test2'
};
formValues.radio = { id: 'option_2', name: 'Option 2' };
const change = new SimpleChange(null, formValues, false);
formComponent.data = formValues;
formComponent.ngOnChanges({ 'data': change });
formFields = formComponent.form.getFormFields();
labelField = formFields.find((field) => field.id === 'label');
radioField = formFields.find((field) => field.id === 'radio');
expect(labelField.value).toBe('option_2');
expect(radioField.value).toBe('option_2');
});
it('should refresh radio buttons value when id is given to data', () => {
formComponent.form = new FormModel(JSON.parse(JSON.stringify(fakeForm)));
let formFields = formComponent.form.getFormFields();
let radioFieldById = formFields.find((field) => field.id === 'radio');
const formValues: any = {};
formValues.radio = 'option_3';
const change = new SimpleChange(null, formValues, false);
formComponent.data = formValues;
formComponent.ngOnChanges({ 'data': change });
formFields = formComponent.form.getFormFields();
radioFieldById = formFields.find((field) => field.id === 'radio');
expect(radioFieldById.value).toBe('option_3');
});
});

View File

@@ -0,0 +1,407 @@
/*!
* @license
* Copyright 2019 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, EventEmitter, Input, Output, ViewEncapsulation, SimpleChanges, OnInit, OnDestroy, OnChanges } from '@angular/core';
import { AttachFileWidgetComponent, AttachFolderWidgetComponent } from '../content-widget';
import { EcmModelService, NodeService, WidgetVisibilityService,
FormService, FormRenderingService, FormBaseComponent, FormOutcomeModel,
FormEvent, FormErrorEvent, FormFieldModel,
FormModel, FormOutcomeEvent, FormValues, ContentLinkModel } from '@alfresco/adf-core';
import { Observable, of, Subject } from 'rxjs';
import { switchMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-form',
templateUrl: './form.component.html',
encapsulation: ViewEncapsulation.None
})
export class FormComponent extends FormBaseComponent implements OnInit, OnDestroy, OnChanges {
/** Underlying form model instance. */
@Input()
form: FormModel;
/** Task id to fetch corresponding form and values. */
@Input()
taskId: string;
/** Content Services node ID for the form metadata. */
@Input()
nodeId: string;
/** The id of the form definition to load and display with custom values. */
@Input()
formId: number;
/** Name of the form definition to load and display with custom values. */
@Input()
formName: string;
/** Toggle saving of form metadata. */
@Input()
saveMetadata: boolean = false;
/** Custom form values map to be used with the rendered form. */
@Input()
data: FormValues;
/** Emitted when the form is submitted with the `Save` or custom outcomes. */
@Output()
formSaved: EventEmitter<FormModel> = new EventEmitter<FormModel>();
/** Emitted when the form is submitted with the `Complete` outcome. */
@Output()
formCompleted: EventEmitter<FormModel> = new EventEmitter<FormModel>();
/** Emitted when form content is clicked. */
@Output()
formContentClicked: EventEmitter<ContentLinkModel> = new EventEmitter<ContentLinkModel>();
/** Emitted when the form is loaded or reloaded. */
@Output()
formLoaded: EventEmitter<FormModel> = new EventEmitter<FormModel>();
/** Emitted when form values are refreshed due to a data property change. */
@Output()
formDataRefreshed: EventEmitter<FormModel> = new EventEmitter<FormModel>();
debugMode: boolean = false;
protected onDestroy$ = new Subject<boolean>();
constructor(protected formService: FormService,
protected visibilityService: WidgetVisibilityService,
protected ecmModelService: EcmModelService,
protected nodeService: NodeService,
protected formRenderingService: FormRenderingService) {
super();
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileWidgetComponent, true);
this.formRenderingService.setComponentTypeResolver('select-folder', () => AttachFolderWidgetComponent, true);
}
ngOnInit() {
this.formService.formContentClicked
.pipe(takeUntil(this.onDestroy$))
.subscribe(content => this.formContentClicked.emit(content));
this.formService.validateForm
.pipe(takeUntil(this.onDestroy$))
.subscribe(validateFormEvent => {
if (validateFormEvent.errorsField.length > 0) {
this.formError.next(validateFormEvent.errorsField);
}
});
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
ngOnChanges(changes: SimpleChanges) {
const taskId = changes['taskId'];
if (taskId && taskId.currentValue) {
this.getFormByTaskId(taskId.currentValue);
return;
}
const formId = changes['formId'];
if (formId && formId.currentValue) {
this.getFormDefinitionByFormId(formId.currentValue);
return;
}
const formName = changes['formName'];
if (formName && formName.currentValue) {
this.getFormDefinitionByFormName(formName.currentValue);
return;
}
const nodeId = changes['nodeId'];
if (nodeId && nodeId.currentValue) {
this.loadFormForEcmNode(nodeId.currentValue);
return;
}
const data = changes['data'];
if (data && data.currentValue) {
this.refreshFormData();
return;
}
}
/**
* Invoked when user clicks form refresh button.
*/
onRefreshClicked() {
this.loadForm();
}
loadForm() {
if (this.taskId) {
this.getFormByTaskId(this.taskId);
return;
}
if (this.formId) {
this.getFormDefinitionByFormId(this.formId);
return;
}
if (this.formName) {
this.getFormDefinitionByFormName(this.formName);
return;
}
}
findProcessVariablesByTaskId(taskId: string): Observable<any> {
return this.formService.getTask(taskId).pipe(
switchMap((task: any) => {
if (this.isAProcessTask(task)) {
return this.visibilityService.getTaskProcessVariable(taskId);
} else {
return of({});
}
})
);
}
isAProcessTask(taskRepresentation) {
return taskRepresentation.processDefinitionId && taskRepresentation.processDefinitionDeploymentId !== 'null';
}
getFormByTaskId(taskId: string): Promise<FormModel> {
return new Promise<FormModel>(resolve => {
this.findProcessVariablesByTaskId(taskId).subscribe(() => {
this.formService
.getTaskForm(taskId)
.subscribe(
(form) => {
const parsedForm = this.parseForm(form);
this.visibilityService.refreshVisibility(parsedForm);
parsedForm.validateForm();
this.form = parsedForm;
this.onFormLoaded(this.form);
resolve(this.form);
},
(error) => {
this.handleError(error);
// reject(error);
resolve(null);
}
);
});
});
}
getFormDefinitionByFormId(formId: number) {
this.formService
.getFormDefinitionById(formId)
.subscribe(
(form) => {
this.formName = form.name;
this.form = this.parseForm(form);
this.visibilityService.refreshVisibility(this.form);
this.form.validateForm();
this.onFormLoaded(this.form);
},
(error) => {
this.handleError(error);
}
);
}
getFormDefinitionByFormName(formName: string) {
this.formService
.getFormDefinitionByName(formName)
.subscribe(
(id) => {
this.formService.getFormDefinitionById(id).subscribe(
(form) => {
this.form = this.parseForm(form);
this.visibilityService.refreshVisibility(this.form);
this.form.validateForm();
this.onFormLoaded(this.form);
},
(error) => {
this.handleError(error);
}
);
},
(error) => {
this.handleError(error);
}
);
}
saveTaskForm() {
if (this.form && this.form.taskId) {
this.formService
.saveTaskForm(this.form.taskId, this.form.values)
.subscribe(
() => {
this.onTaskSaved(this.form);
this.storeFormAsMetadata();
},
(error) => this.onTaskSavedError(this.form, error)
);
}
}
completeTaskForm(outcome?: string) {
if (this.form && this.form.taskId) {
this.formService
.completeTaskForm(this.form.taskId, this.form.values, outcome)
.subscribe(
() => {
this.onTaskCompleted(this.form);
this.storeFormAsMetadata();
},
(error) => this.onTaskCompletedError(this.form, error)
);
}
}
handleError(err: any): any {
this.error.emit(err);
}
parseForm(formRepresentationJSON: any): FormModel {
if (formRepresentationJSON) {
const form = new FormModel(formRepresentationJSON, this.data, this.readOnly, this.formService);
if (!formRepresentationJSON.fields) {
form.outcomes = this.getFormDefinitionOutcomes(form);
}
if (this.fieldValidators && this.fieldValidators.length > 0) {
form.fieldValidators = this.fieldValidators;
}
return form;
}
return null;
}
/**
* Get custom set of outcomes for a Form Definition.
* @param form Form definition model.
*/
getFormDefinitionOutcomes(form: FormModel): FormOutcomeModel[] {
return [
new FormOutcomeModel(form, { id: '$save', name: FormOutcomeModel.SAVE_ACTION, isSystem: true })
];
}
checkVisibility(field: FormFieldModel) {
if (field && field.form) {
this.visibilityService.refreshVisibility(field.form);
}
}
private refreshFormData() {
this.form = this.parseForm(this.form.json);
this.onFormLoaded(this.form);
this.onFormDataRefreshed(this.form);
}
private loadFormForEcmNode(nodeId: string): void {
this.nodeService.getNodeMetadata(nodeId).subscribe((data) => {
this.data = data.metadata;
this.loadFormFromActiviti(data.nodeType);
},
this.handleError);
}
loadFormFromActiviti(nodeType: string): any {
this.formService.searchFrom(nodeType).subscribe(
(form) => {
if (!form) {
this.formService.createFormFromANode(nodeType).subscribe((formMetadata) => {
this.loadFormFromFormId(formMetadata.id);
});
} else {
this.loadFormFromFormId(form.id);
}
},
(error) => {
this.handleError(error);
}
);
}
private loadFormFromFormId(formId: number) {
this.formId = formId;
this.loadForm();
}
protected storeFormAsMetadata() {
if (this.saveMetadata) {
this.ecmModelService.createEcmTypeForActivitiForm(this.formName, this.form).subscribe((type) => {
this.nodeService.createNodeMetadata(type.nodeType || type.entry.prefixedName, EcmModelService.MODEL_NAMESPACE, this.form.values, this.path, this.nameNode);
},
(error) => {
this.handleError(error);
}
);
}
}
protected onFormLoaded(form: FormModel) {
this.formLoaded.emit(form);
this.formService.formLoaded.next(new FormEvent(form));
}
protected onFormDataRefreshed(form: FormModel) {
this.formDataRefreshed.emit(form);
this.formService.formDataRefreshed.next(new FormEvent(form));
}
protected onTaskSaved(form: FormModel) {
this.formSaved.emit(form);
this.formService.taskSaved.next(new FormEvent(form));
}
protected onTaskSavedError(form: FormModel, error: any) {
this.handleError(error);
this.formService.taskSavedError.next(new FormErrorEvent(form, error));
}
protected onTaskCompleted(form: FormModel) {
this.formCompleted.emit(form);
this.formService.taskCompleted.next(new FormEvent(form));
}
protected onTaskCompletedError(form: FormModel, error: any) {
this.handleError(error);
this.formService.taskCompletedError.next(new FormErrorEvent(form, error));
}
protected onExecuteOutcome(outcome: FormOutcomeModel): boolean {
const args = new FormOutcomeEvent(outcome);
this.formService.executeOutcome.next(args);
if (args.defaultPrevented) {
return false;
}
this.executeOutcome.emit(args);
if (args.defaultPrevented) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,244 @@
/*!
* @license
* Copyright 2019 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 { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { SimpleChange } from '@angular/core';
import { of } from 'rxjs';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { formDefinitionDropdownField, formDefinitionTwoTextFields,
formDefinitionRequiredField, FormService, setupTestBed, CoreModule,
formDefVisibilitiFieldDependsOnNextOne, formDefVisibilitiFieldDependsOnPreviousOne,
formReadonlyTwoTextFields } from '@alfresco/adf-core';
import { FormComponent } from './form.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
/** Duration of the select opening animation. */
const SELECT_OPEN_ANIMATION = 200;
/** Duration of the select closing animation and the timeout interval for the backdrop. */
const SELECT_CLOSE_ANIMATION = 500;
describe('FormComponent UI and visibility', () => {
let component: FormComponent;
let service: FormService;
let fixture: ComponentFixture<FormComponent>;
function openSelect() {
let trigger: HTMLElement;
trigger = fixture.debugElement.query(By.css('[class="mat-select-trigger"]')).nativeElement;
trigger.click();
fixture.detectChanges();
}
setupTestBed({
imports: [
NoopAnimationsModule,
CoreModule.forRoot()
],
declarations: [
FormComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
service = TestBed.get(FormService);
});
afterEach(() => {
fixture.destroy();
TestBed.resetTestingModule();
});
it('should create instance of FormComponent', () => {
expect(fixture.componentInstance instanceof FormComponent).toBe(true, 'should create FormComponent');
});
describe('Validation icon', () => {
it('should display valid icon for valid form', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeDefined();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).not.toBeNull();
expect(fixture.debugElement.query(By.css('#adf-invalid-form-icon'))).toBeNull();
});
it('should display invalid icon for valid form', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionRequiredField));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeNull();
expect(fixture.debugElement.query(By.css('#adf-invalid-form-icon'))).toBeDefined();
expect(fixture.debugElement.query(By.css('#adf-invalid-form-icon'))).not.toBeNull();
});
it('should NOT display validation icon when [showValidationIcon] is false', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
component.showValidationIcon = false;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('#adf-valid-form-icon'))).toBeNull();
expect(fixture.debugElement.query(By.css('#adf-invalid-form-icon'))).toBeNull();
});
});
describe('form definition', () => {
it('should display two text fields form definition', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
const firstNameEl = fixture.debugElement.query(By.css('#firstname'));
expect(firstNameEl).not.toBeNull();
expect(firstNameEl).toBeDefined();
const lastNameEl = fixture.debugElement.query(By.css('#lastname'));
expect(lastNameEl).not.toBeNull();
expect(lastNameEl).toBeDefined();
});
it('should display dropdown field', fakeAsync(() => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefinitionDropdownField));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
openSelect();
tick(SELECT_OPEN_ANIMATION);
const dropdown = fixture.debugElement.queryAll(By.css('#country'));
expect(dropdown).toBeDefined();
expect(dropdown).not.toBeNull();
const options = fixture.debugElement.queryAll(By.css('mat-option'));
const optOne = options[1];
const optTwo = options[2];
const optThree = options[3];
expect(optOne.nativeElement.innerText.trim()).toEqual('united kingdom');
expect(optTwo.nativeElement.innerText.trim()).toEqual('italy');
expect(optThree.nativeElement.innerText.trim()).toEqual('france');
optTwo.nativeElement.click();
fixture.detectChanges();
expect(dropdown[0].nativeElement.innerText.trim()).toEqual('italy');
tick(SELECT_CLOSE_ANIMATION);
}));
describe('Visibility conditions', () => {
it('should hide the field based on the next one', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
const firstEl = fixture.debugElement.query(By.css('#field-country-container'));
expect(firstEl.nativeElement.hidden).toBeTruthy();
const secondEl = fixture.debugElement.query(By.css('#name'));
expect(secondEl).not.toBeNull();
expect(secondEl).toBeDefined();
expect(fixture.nativeElement.querySelector('#field-name-container').hidden).toBeFalsy();
});
it('should hide the field based on the previous one', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnPreviousOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
const firstEl = fixture.debugElement.query(By.css('#name'));
expect(firstEl).not.toBeNull();
expect(firstEl).toBeDefined();
expect(fixture.nativeElement.querySelector('#field-name-container').hidden).toBeFalsy();
const secondEl = fixture.debugElement.query(By.css('#field-country-container'));
expect(secondEl.nativeElement.hidden).toBeTruthy();
});
it('should show the hidden field when the visibility condition change to true', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formDefVisibilitiFieldDependsOnNextOne));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
let firstEl = fixture.debugElement.query(By.css('#field-country-container'));
expect(firstEl.nativeElement.hidden).toBeTruthy();
const secondEl = fixture.debugElement.query(By.css('#field-name-container'));
expect(secondEl.nativeElement.hidden).toBeFalsy();
const inputElement = fixture.nativeElement.querySelector('#name');
inputElement.value = 'italy';
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
firstEl = fixture.debugElement.query(By.css('#field-country-container'));
expect(firstEl.nativeElement.hidden).toBeFalsy();
});
});
describe('Readonly Form', () => {
it('should display two text fields readonly', () => {
spyOn(service, 'getTask').and.returnValue(of({}));
spyOn(service, 'getTaskForm').and.returnValue(of(formReadonlyTwoTextFields));
const change = new SimpleChange(null, 1, true);
component.ngOnChanges({ 'taskId': change });
fixture.detectChanges();
const firstNameEl = fixture.debugElement.query(By.css('#firstname'));
expect(firstNameEl).not.toBeNull();
expect(firstNameEl).toBeDefined();
expect(firstNameEl.nativeElement.value).toEqual('fakeFirstName');
const lastNameEl = fixture.debugElement.query(By.css('#lastname'));
expect(lastNameEl).not.toBeNull();
expect(lastNameEl).toBeDefined();
expect(lastNameEl.nativeElement.value).toEqual('fakeLastName');
});
});
});
});

View File

@@ -0,0 +1,38 @@
/*!
* @license
* Copyright 2019 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 { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { CoreModule } from '@alfresco/adf-core';
import { FormComponent } from './form.component';
import { StartFormComponent } from './start-form.component';
@NgModule({
imports: [
CoreModule,
MaterialModule
],
declarations: [
FormComponent,
StartFormComponent
],
exports: [
FormComponent,
StartFormComponent
]
})
export class FormModule {}

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './public-api';

View File

@@ -0,0 +1,20 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './form.component';
export * from './start-form.component';
export * from './form.module';

View File

@@ -0,0 +1,40 @@
<div class="adf-start-form-container" *ngIf="hasForm()">
<mat-card>
<mat-card-header>
<mat-card-title>
<h2 *ngIf="isTitleEnabled()" class="mdl-card__title-text">{{form.taskName}}</h2>
</mat-card-title>
</mat-card-header>
<mat-card-content>
<div *ngIf="form.hasTabs()">
<tabs-widget [tabs]="form.tabs" (formTabChanged)="checkVisibility($event);"></tabs-widget>
</div>
<div *ngIf="!form.hasTabs() && form.hasFields()">
<div *ngFor="let field of form.fields">
<adf-form-field [field]="field.field"></adf-form-field>
</div>
</div>
</mat-card-content>
<mat-card-content class="adf-start-form-actions" *ngIf="showOutcomeButtons && form.hasOutcomes()"
#outcomesContainer>
<ng-content select="[adf-form-custom-button], [form-custom-button]"></ng-content>
<button *ngFor="let outcome of form.outcomes"
mat-button
[attr.data-automation-id]="'adf-form-' + outcome.name | lowercase"
[disabled]="!isOutcomeButtonEnabled(outcome)"
[class.mdl-button--colored]="!outcome.isSystem"
[class.adf-form-hide-button]="!isOutcomeButtonVisible(outcome, form.readOnly)"
(click)="onOutcomeClicked(outcome)">
{{ outcome.name | uppercase | translate | uppercase }}
</button>
</mat-card-content>
<mat-card-actions *ngIf="showRefreshButton">
<button mat-button
(click)="onRefreshClicked()">
<mat-icon>refresh</mat-icon>
</button>
</mat-card-actions>
</mat-card>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,130 @@
@mixin adf-start-form-component-theme($theme) {
$config: mat-typography-config();
$warn: map-get($theme, warn);
$accent: map-get($theme, accent);
.adf {
&-form-container {
max-width: 100% !important;
max-height: 100% !important;
& .mat-card {
padding: 16px 24px;
overflow: hidden;
}
& .mat-card-header-text {
margin: 0 !important;
}
& .mat-tab-body-content {
overflow: hidden;
}
& .mat-tab-label {
font-size: mat-font-size($config, subheading-2);
line-height: mat-line-height($config, headline);
letter-spacing: -0.4px;
text-align: left;
color: rgba(0, 0, 0, 0.54);
text-transform: uppercase;
}
& .mat-ink-bar {
height: 4px;
}
& .mat-form-field-wrapper {
margin: 0 12px 0 0;
}
}
&-form-title {
font-size: mat-font-size($alfresco-typography, title);
}
&-form-debug-container {
padding: 10px;
}
&-form-debug-container .adf-debug-toggle-text {
padding-left: 15px;
cursor: pointer;
}
&-form-debug-container .adf-debug-toggle-text:hover {
font-weight: bold;
}
&-form-reload-button {
position: absolute;
right: 12px;
top: 30px;
}
&-form-validation-button {
position: absolute;
right: 50px;
top: 39px;
color: mat-color($accent);
& .adf-invalid-color {
color: mat-color($warn);
}
}
&-form-hide-button {
display: none !important;
}
&-task-title {
text-align: center;
}
&-label {
width: 32px;
height: 16px;
font-size: mat-font-size($config, caption);
line-height: mat-line-height($config, headline);
text-align: left;
white-space: nowrap;
}
&-form-mat-card-actions {
float: right;
padding-bottom: 25px !important;
padding-right: 25px !important;
& .mat-button {
height: 36px;
border-radius: 5px;
}
& .mat-button-wrapper {
width: 58px;
height: 20px;
opacity: 0.54;
font-size: mat-font-size($config, body-2);
font-weight: bold;
}
}
}
form-field {
width: 100%;
.mat-input-element {
font-size: mat-font-size($config, body-2);
padding-top: 8px;
line-height: normal;
}
}
[dir='rtl'] .adf-form-validation-button {
left: 50px;
right: unset;
}
}

View File

@@ -0,0 +1,454 @@
/*!
* @license
* Copyright 2019 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 { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of, throwError } from 'rxjs';
import { startFormDateWidgetMock, startFormDropdownDefinitionMock, startFormTextDefinitionMock, startMockForm, startMockFormWithTab } from './start-form.component.mock';
import { startFormAmountWidgetMock, startFormNumberWidgetMock, startFormRadioButtonWidgetMock } from './start-form.component.mock';
import { StartFormComponent } from './start-form.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormService, WidgetVisibilityService, setupTestBed, CoreModule, FormModel, FormOutcomeModel } from '@alfresco/adf-core';
import { TranslateService } from '@ngx-translate/core';
describe('StartFormComponent', () => {
let formService: FormService;
let component: StartFormComponent;
let fixture: ComponentFixture<StartFormComponent>;
let getStartFormSpy: jasmine.Spy;
let visibilityService: WidgetVisibilityService;
let translate: TranslateService;
const exampleId1 = 'my:process1';
const exampleId2 = 'my:process2';
setupTestBed({
imports: [
NoopAnimationsModule,
CoreModule.forRoot()
],
declarations: [
StartFormComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(StartFormComponent);
component = fixture.componentInstance;
formService = TestBed.get(FormService);
visibilityService = TestBed.get(WidgetVisibilityService);
translate = TestBed.get(TranslateService);
getStartFormSpy = spyOn(formService, 'getStartFormDefinition').and.returnValue(of({
processDefinitionName: 'my:process'
}));
spyOn(translate, 'instant').and.callFake((key) => { return key; });
spyOn(translate, 'get').and.callFake((key) => { return of(key); });
});
afterEach(() => {
fixture.destroy();
});
it('should load start form on change if processDefinitionId defined', () => {
component.processDefinitionId = exampleId1;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
expect(formService.getStartFormDefinition).toHaveBeenCalled();
});
it('should load start form when processDefinitionId changed', () => {
component.processDefinitionId = exampleId1;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
expect(formService.getStartFormDefinition).toHaveBeenCalled();
});
it('should check visibility when the start form is loaded', () => {
spyOn(visibilityService, 'refreshVisibility');
component.processDefinitionId = exampleId1;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
expect(formService.getStartFormDefinition).toHaveBeenCalled();
expect(visibilityService.refreshVisibility).toHaveBeenCalled();
});
it('should not load start form when changes notified but no change to processDefinitionId', () => {
component.processDefinitionId = exampleId1;
component.ngOnChanges({ otherProp: new SimpleChange(exampleId1, exampleId2, true) });
expect(formService.getStartFormDefinition).not.toHaveBeenCalled();
});
it('should consume errors encountered when loading start form', () => {
getStartFormSpy.and.returnValue(throwError({}));
component.processDefinitionId = exampleId1;
component.ngOnInit();
});
it('should show outcome buttons by default', () => {
getStartFormSpy.and.returnValue(of({
id: '1',
processDefinitionName: 'my:process',
outcomes: [{
id: 'approve',
name: 'Approve'
}]
}));
component.processDefinitionId = exampleId1;
component.ngOnInit();
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
expect(component.outcomesContainer).toBeTruthy();
});
it('should show outcome buttons if showOutcomeButtons is true', () => {
getStartFormSpy.and.returnValue(of({
id: '1',
processDefinitionName: 'my:process',
outcomes: [{
id: 'approve',
name: 'Approve'
}]
}));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
expect(component.outcomesContainer).toBeTruthy();
});
it('should fetch start form details by processDefinitionId ', () => {
getStartFormSpy.and.returnValue(of(startMockForm));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
expect(component.outcomesContainer).toBeTruthy();
expect(getStartFormSpy).toHaveBeenCalled();
});
describe('Display widgets', () => {
it('should be able to display a textWidget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormTextDefinitionMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'mocktext');
const textWidget = fixture.debugElement.nativeElement.querySelector('text-widget');
const textWidgetLabel = fixture.debugElement.nativeElement.querySelector('.adf-label');
expect(labelField.type).toBe('text');
expect(textWidget).toBeDefined();
expect(textWidgetLabel.innerText).toBe('mockText');
});
});
it('should be able to display a radioButtonWidget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormRadioButtonWidgetMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'radio-but');
const radioButtonWidget = fixture.debugElement.nativeElement.querySelector('radio-buttons-widget');
const radioButtonWidgetLabel = fixture.debugElement.nativeElement.querySelector('.adf-input');
expect(labelField.type).toBe('radio-buttons');
expect(radioButtonWidget).toBeDefined();
expect(radioButtonWidgetLabel.innerText).toBe('radio-buttons');
});
});
it('should be able to display a amountWidget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormAmountWidgetMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'amount');
const amountWidget = fixture.debugElement.nativeElement.querySelector('amount-widget');
const amountWidgetLabel = fixture.debugElement.nativeElement.querySelector('.adf-input');
expect(labelField.type).toBe('amount');
expect(amountWidget).toBeDefined();
expect(amountWidgetLabel.innerText).toBe('amount');
});
});
it('should be able to display a numberWidget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormNumberWidgetMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'number');
const numberWidget = fixture.debugElement.nativeElement.querySelector('number-widget');
expect(labelField.type).toBe('integer');
expect(numberWidget).toBeDefined();
});
});
it('should be able to display a dropDown Widget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormDropdownDefinitionMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'mockTypeDropDown');
const dropDownWidget = fixture.debugElement.nativeElement.querySelector('dropdown-widget');
const selectElement = fixture.debugElement.nativeElement.querySelector('.adf-dropdown-widget>mat-select .mat-select-trigger');
selectElement.click();
expect(selectElement).toBeDefined();
expect(dropDownWidget).toBeDefined();
expect(selectElement.innerText).toBe('Choose one...');
expect(labelField.type).toBe('dropdown');
expect(labelField.options[0].name).toBe('Chooseone...');
expect(labelField.options[1].name).toBe('Option-1');
expect(labelField.options[2].name).toBe('Option-2');
});
});
it('should be able to display a date Widget from a process definition', () => {
getStartFormSpy.and.returnValue(of(startFormDateWidgetMock));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'date');
const dateWidget = fixture.debugElement.nativeElement.querySelector('dropdown-widget');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#data-widget .mat-form-field-infix> .adf-label');
expect(dateWidget).toBeDefined();
expect(labelField.type).toBe('date');
expect(dateLabelElement.innerText).toBe('date (D-M-YYYY)');
});
});
it('should fetch and define form fields with proper type', () => {
getStartFormSpy.and.returnValue(of(startMockForm));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'billdate');
expect(labelField.type).toBe('date');
const formFields1 = component.form.getFormFields();
const labelField1 = formFields1.find((field) => field.id === 'claimtype');
expect(labelField1.type).toBe('dropdown');
});
it('should show dropdown options', () => {
getStartFormSpy.and.returnValue(of(startMockForm));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'claimtype');
expect(labelField.type).toBe('dropdown');
expect(labelField.options[0].name).toBe('Chooseone...');
expect(labelField.options[1].name).toBe('Cashless');
expect(labelField.options[2].name).toBe('Reimbursement');
});
});
it('should display start form with fields ', async(() => {
getStartFormSpy.and.returnValue(of(startMockForm));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.whenStable().then(() => {
fixture.detectChanges();
const formFieldsWidget = fixture.debugElement.nativeElement.querySelector('form-field');
const inputElement = fixture.debugElement.nativeElement.querySelector('.adf-input');
const inputLabelElement = fixture.debugElement.nativeElement.querySelector('.mat-form-field-infix > .adf-label');
const dateElement = fixture.debugElement.nativeElement.querySelector('#billdate');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#data-widget .mat-form-field-infix> .adf-label');
const selectElement = fixture.debugElement.nativeElement.querySelector('#claimtype');
const selectLabelElement = fixture.debugElement.nativeElement.querySelector('.adf-dropdown-widget > .adf-label');
expect(formFieldsWidget).toBeDefined();
expect(inputElement).toBeDefined();
expect(dateElement).toBeDefined();
expect(selectElement).toBeDefined();
translate.get(inputLabelElement.textContent).subscribe( (value) => {
expect(value).toBe('ClientName*');
});
translate.get(dateLabelElement.innerText).subscribe( (value) => {
expect(value).toBe('BillDate (D-M-YYYY)');
});
translate.get(selectLabelElement.innerText).subscribe( (value) => {
expect(value).toBe('ClaimType');
});
});
}));
it('should refresh start form on click of refresh button ', async(() => {
getStartFormSpy.and.returnValue(of(startMockForm));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.showRefreshButton = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
const refreshElement = fixture.debugElement.nativeElement.querySelector('.mat-card-actions>button');
refreshElement.click();
fixture.detectChanges();
/* cspell:disable-next-line */
const selectElement = fixture.debugElement.nativeElement.querySelector('#claimtype');
const selectLabelElement = fixture.debugElement.nativeElement.querySelector('.adf-dropdown-widget > .adf-label');
expect(refreshElement).toBeDefined();
expect(selectElement).toBeDefined();
translate.get(selectLabelElement.innerText).subscribe( (value) => {
expect(value).toBe('ClaimType');
});
});
}));
it('should define custom-tabs ', async(() => {
getStartFormSpy.and.returnValue(of(startMockFormWithTab));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.showRefreshButton = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
const formTabs = component.form.tabs;
const tabField1 = formTabs.find((tab) => tab.id === 'form1');
const tabField2 = formTabs.find((tab) => tab.id === 'form2');
const tabsWidgetElement = fixture.debugElement.nativeElement.querySelector('tabs-widget');
expect(tabField1.name).toBe('Tab 1');
expect(tabField2.name).toBe('Tab 2');
expect(tabsWidgetElement).toBeDefined();
});
}));
it('should define title and [custom-action-buttons]', async(() => {
getStartFormSpy.and.returnValue(of(startMockFormWithTab));
component.processDefinitionId = exampleId1;
component.showOutcomeButtons = true;
component.showRefreshButton = true;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
fixture.detectChanges();
fixture.whenStable().then(() => {
const titleIcon = fixture.debugElement.nativeElement.querySelector('mat-card-title>mat-icon');
const titleElement = fixture.debugElement.nativeElement.querySelector('mat-card-title>h2');
const actionButtons = fixture.debugElement.nativeElement.querySelectorAll('.mat-button');
expect(titleIcon).toBeDefined();
expect(titleElement).toBeDefined();
expect(actionButtons.length).toBe(4);
expect(actionButtons[0].innerText).toBe('Save');
expect(actionButtons[0].disabled).toBeFalsy();
expect(actionButtons[1].innerText).toBe('Approve');
expect(actionButtons[1].disabled).toBeTruthy();
expect(actionButtons[2].innerText).toBe('Complete');
expect(actionButtons[2].disabled).toBeTruthy();
});
}));
});
describe('OutCome Actions', () => {
it('should not enable outcome button when model missing', () => {
expect(component.isOutcomeButtonVisible(null, false)).toBeFalsy();
});
it('should enable custom outcome buttons', () => {
const formModel = new FormModel();
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: 'action1', name: 'Action 1' });
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeTruthy();
});
it('should allow controlling [complete] button visibility', () => {
const formModel = new FormModel();
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
component.showSaveButton = true;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeTruthy();
component.showSaveButton = false;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeFalsy();
});
it('should show only [complete] button with readOnly form ', () => {
const formModel = new FormModel();
formModel.readOnly = true;
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$complete', name: FormOutcomeModel.COMPLETE_ACTION });
component.showCompleteButton = true;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeTruthy();
});
it('should not show [save] button with readOnly form ', () => {
const formModel = new FormModel();
formModel.readOnly = true;
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.SAVE_ACTION });
component.showSaveButton = true;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeFalsy();
});
it('should show [custom-outcome] button with readOnly form and selected custom-outcome', () => {
const formModel = new FormModel({ selectedOutcome: 'custom-outcome' });
formModel.readOnly = true;
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$customoutome', name: 'custom-outcome' });
component.showCompleteButton = true;
component.showSaveButton = true;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeTruthy();
const outcome1 = new FormOutcomeModel(formModel, { id: '$customoutome2', name: 'custom-outcome2' });
expect(component.isOutcomeButtonVisible(outcome1, component.form.readOnly)).toBeFalsy();
});
it('should allow controlling [save] button visibility', () => {
const formModel = new FormModel();
formModel.readOnly = false;
component.form = formModel;
const outcome = new FormOutcomeModel(formModel, { id: '$save', name: FormOutcomeModel.COMPLETE_ACTION });
component.showCompleteButton = true;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeTruthy();
component.showCompleteButton = false;
expect(component.isOutcomeButtonVisible(outcome, component.form.readOnly)).toBeFalsy();
});
});
});

View File

@@ -0,0 +1,164 @@
/*!
* @license
* Copyright 2019 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,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation,
OnDestroy
} from '@angular/core';
import { FormComponent } from './form.component';
import { ContentLinkModel, FormService, WidgetVisibilityService, FormRenderingService, FormOutcomeModel } from '@alfresco/adf-core';
@Component({
selector: 'adf-start-form',
templateUrl: './start-form.component.html',
styleUrls: ['./start-form.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class StartFormComponent extends FormComponent implements OnChanges, OnInit, OnDestroy {
/** Definition ID of the process to start. */
@Input()
processDefinitionId: string;
/** Process ID of the process to start. */
@Input()
processId: string;
/** Should form outcome buttons be shown? */
@Input()
showOutcomeButtons: boolean = true;
/** Should the refresh button be shown? */
@Input()
showRefreshButton: boolean = true;
/** Is the form read-only (ie, can't be edited)? */
@Input()
readOnlyForm: boolean = false;
/** Emitted when the user clicks one of the outcome buttons that completes the form. */
@Output()
outcomeClick: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when a field of the form is clicked. */
@Output()
formContentClicked: EventEmitter<ContentLinkModel> = new EventEmitter<ContentLinkModel>();
@ViewChild('outcomesContainer', {})
outcomesContainer: ElementRef = null;
constructor(formService: FormService,
visibilityService: WidgetVisibilityService,
formRenderingService: FormRenderingService) {
super(formService, visibilityService, null, null, formRenderingService);
this.showTitle = false;
}
ngOnChanges(changes: SimpleChanges) {
const processDefinitionId = changes['processDefinitionId'];
if (processDefinitionId && processDefinitionId.currentValue) {
this.visibilityService.cleanProcessVariable();
this.getStartFormDefinition(processDefinitionId.currentValue);
return;
}
const processId = changes['processId'];
if (processId && processId.currentValue) {
this.visibilityService.cleanProcessVariable();
this.loadStartForm(processId.currentValue);
return;
}
}
loadStartForm(processId: string) {
this.formService.getProcessInstance(processId)
.subscribe((instance: any) => {
this.formService
.getStartFormInstance(processId)
.subscribe(
(form) => {
this.formName = form.name;
if (instance.variables) {
form.processVariables = instance.variables;
}
this.form = this.parseForm(form);
this.visibilityService.refreshVisibility(this.form);
this.form.validateForm();
this.form.readOnly = this.readOnlyForm;
this.onFormLoaded(this.form);
},
(error) => this.handleError(error)
);
});
}
getStartFormDefinition(processId: string) {
this.formService
.getStartFormDefinition(processId)
.subscribe(
(form) => {
this.formName = form.processDefinitionName;
this.form = this.parseForm(form);
this.visibilityService.refreshVisibility(this.form);
this.form.validateForm();
this.form.readOnly = this.readOnlyForm;
this.onFormLoaded(this.form);
},
(error) => this.handleError(error)
);
}
/** @override */
isOutcomeButtonVisible(outcome: FormOutcomeModel, isFormReadOnly: boolean): boolean {
if (outcome && outcome.isSystem && (outcome.name === FormOutcomeModel.SAVE_ACTION ||
outcome.name === FormOutcomeModel.COMPLETE_ACTION)) {
return false;
} else if (outcome && outcome.name === FormOutcomeModel.START_PROCESS_ACTION) {
return true;
}
return super.isOutcomeButtonVisible(outcome, isFormReadOnly);
}
/** @override */
saveTaskForm() {
// do nothing
}
/** @override */
onRefreshClicked() {
if (this.processDefinitionId) {
this.visibilityService.cleanProcessVariable();
this.getStartFormDefinition(this.processDefinitionId);
} else if (this.processId) {
this.visibilityService.cleanProcessVariable();
this.loadStartForm(this.processId);
}
}
completeTaskForm(outcome?: string) {
this.outcomeClick.emit(outcome);
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "انقر فوق حفظ لإضافة تقرير بالإعدادات الحالية إلى قائمة تقاريرك.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "تاريخ البدء",
"END-DATE": "تاريخ الانتهاء",
"MESSAGES": {
"START-DATE-REQUIRED": "تاريخ البدء مطلوب",
"START-LESS-THAN-END-DATE": "يجب أن يكون تاريخ البدء قبل تاريخ الانتهاء"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "لم يتم العثور على تطبيقات",
"SUBTITLE": "أنشئ تطبيقًا جديدًا تريد العثور عليه بسهولة لاحقًا",
"TASK_APP_NAME": "تطبيق المهمة"
},
"LIST": {
"MESSAGES": {
"TITLE": "لم يتم العثور على مهام",
"SUBTITLE": "أنشئ مهمة جديدة تريد العثور عليها بسهولة لاحقًا",
"NONE": "لم يتم العثور على قوائم مهام"
}
},
"PROPERTIES": {
"TASK_NAME": "مهمة",
"THUMBNAIL": "صورة مصغرة",
"DURATION": "المدة",
"PARENT_TASK_ID": "معرف المهمة الأصلية",
"NAME": "الاسم",
"ASSIGNEE": "معين له",
"ASSIGNEE_DEFAULT": "لا يوجد معين له",
"PRIORITY": "أولوية",
"DUE_DATE": "تاريخ الاستحقاق",
"DUE_DATE_DEFAULT": "لا يوجد تاريخ",
"STATUS": "الحالة",
"CATEGORY": "الفئة",
"CATEGORY_DEFAULT": "لا توجد فئة",
"PARENT_NAME": "اسم العنصر الأصلي",
"PARENT_NAME_DEFAULT": "لا يوجد عنصر أصلي",
"CREATED_BY": "تم الإنشاء بواسطة",
"CREATED": "تم الإنشاء",
"END_DATE": "تاريخ الانتهاء",
"ID": "المعرف",
"DESCRIPTION": "الوصف",
"DESCRIPTION_DEFAULT": "لا يوجد وصف",
"FORM_NAME": "اسم النموذج",
"FORM_NAME_DEFAULT": "لا يوجد نموذج"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "عرض",
"REMOVE_CONTENT": "إزالة",
"DOWNLOAD_CONTENT": "تنزيل",
"DOWNLOAD_AUDIT": "تنزيل التدقيق"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "أنشطة",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "نشاط",
"INFO_DRAWER_TAB_DETAILS_TITLE": "التفاصيل",
"ASSIGNEE": "معين له",
"DUE": "مستحق",
"FORM": "نموذج",
"PEOPLE": "الأشخاص هذه المهمة مشتركة مع",
"COMMENTS": "تعليقات",
"CHECKLIST": "قائمة الاختيار",
"INVOLVED_PEOPLE": "الأشخاص المشتركون",
"ADD_PEOPLE": "إضافة أشخاص ومجموعات",
"ADD_ASSIGNEE": "إضافة معين له جديد"
},
"BUTTON": {
"COMPLETE": "تم",
"CLAIM": "مطالبة",
"UNCLAIM": "تحرير",
"DRAG-ATTACHMENT": "إفلات الملفات لتحميلها",
"UPLOAD-ATTACHMENT": "تحميل المرفق"
},
"MESSAGES": {
"NONE": "لم يتم العثور على تفاصيل المهمة",
"CLAIM": "انقر فوق مطالبة للعمل على هذه المهمة"
},
"FORM": {
"NONE": "لا يوجد نموذج"
},
"DUE": {
"NONE": "لا يوجد تاريخ استحقاق"
},
"ASSIGNEE": {
"NONE": "لا يوجد معين له"
},
"PEOPLE": {
"NONE": "لا يوجد شخص مشترك"
},
"CHECKLIST": {
"NONE": "لا توجد قائمة اختيار",
"DIALOG": {
"TITLE": "اختيار جديد",
"CANCEL-BUTTON": "إلغاء",
"ADD-BUTTON": "إضافة قائمة اختيار",
"PLACEHOLDER": "الاسم"
}
},
"ERROR": {
"TITLE": "تعذر إتمام الإجراء",
"DESCRIPTION": "حاول مرة أخرى أو تحقق من أن لديك حق الوصول.",
"CLOSE": "إغلاق"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "لم يتم تحديد عامل تصفية للمهمة"
}
},
"START_TASK": {
"DEFAULT_NAME": "مهمتي الافتراضية",
"BUTTON": "إنشاء مهمة",
"FORM": {
"TITLE": "بدء مهمة",
"LABEL": {
"NONE": "بلا",
"NAME": "الاسم",
"DESCRIPTION": "الوصف",
"ATTACHFORM": "إرفاق نموذج",
"ASSIGNEE": "معين له",
"FORM": "نموذج",
"DATE": "اختيار تاريخ"
},
"ACTION": {
"START": "بدء",
"CANCEL": "إلغاء"
},
"ERROR": {
"REQUIRED": "حقل مطلوب",
"DATE": "تنسيق التاريخ ي‎ي/ش‎ش/س‎س‎س‎س",
"MAXIMUM_LENGTH": "تم تجاوز الطول، {{characters}} من الحد الأقصى للحروف.",
"MESSAGE": "أدخل قيمة مختلفة"
}
}
},
"PEOPLE": {
"ASSIGNEE": "معين له",
"DIALOG_CLOSE": "إغلاق",
"ADD_USER": "إضافة",
"ADD_ASSIGNEE": "تعيين",
"SEARCH_USER": "بحث عن مستخدم",
"SEARCH": {
"NO_USERS": "لم يتم العثور على شخص للاشتراك"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "هذه القائمة فارغة",
"DRAG-AND-DROP": {
"TITLE": "سحب وإفلات",
"SUBTITLE": "لتحميل الملفات"
}
},
"EMPTY-LIST": {
"HEADER": "لا توجد ملفات متاحة"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "لا توجد نماذج مرفقة",
"COMPLETE_TASK_MESSAGE": "اكتملت المهمة {{taskName}}",
"COMPLETE_TASK_SUB_MESSAGE": "لا توجد نماذج لإضافتها"
},
"ATTACH_FORM": {
"SELECT_FORM": "حدد نموذجًا لإرفاقه",
"REMOVE_FORM": "إزالة النموذج",
"SELECT_OPTION": "حدد خيارًا"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "لم يتم العثور على عمليات",
"SUBTITLE": "إنشاء عملية جديدة تريد العثور عليها بسهولة لاحقًا",
"SUMMARY": "تم العثور على {{total}} من مثيلات العملية",
"ERROR": "تعذر تحميل مثيلات العمليات. حاول مرة أخرى أو شارك الرسالة التالية مع فريق تكنولوجيا المعلومات لديك: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "لم يتم تحديد عامل تصفية مثيل العملية."
}
},
"PROPERTIES": {
"PROCESS_NAME": "العملية",
"NAME": "الاسم",
"THUMBNAIL": "صورة مصغرة",
"STATUS": "الحالة",
"END_DATE": "تاريخ الانتهاء",
"END_DATE_DEFAULT": "لا يوجد تاريخ",
"CATEGORY": "الفئة",
"CATEGORY_DEFAULT": "لا توجد فئة",
"CREATED_BY": "تم الإنشاء بواسطة",
"CREATED_BY_DEFAULT": "لا يوجد معين له",
"CREATED": "تم الإنشاء",
"BUSINESS_KEY": "مفتاح أعمال",
"BUSINESS_KEY_DEFAULT": "بلا",
"DESCRIPTION": "الوصف",
"DESCRIPTION_DEFAULT": "لا يوجد وصف",
"ID": "المعرف"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "عرض",
"REMOVE_CONTENT": "إزالة",
"DOWNLOAD_CONTENT": "تنزيل",
"DOWNLOAD_AUDIT": "تنزيل التدقيق",
"VIEW_TASK": "عرض المهمة"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "بدأ حسب",
"STARTED": "بدأ",
"ENDED": "انتهى",
"COMMENTS": "تعليقات",
"START_FORM": "نموذج البدء",
"TASKS_ACTIVE": "مهام نشطة",
"TASKS_COMPLETED": "مهام مكتملة",
"TASK_SUBTITLE": "تم التعيين إلى {{user}}، تم إنشاء {{created}}"
},
"BUTTON": {
"CANCEL": "إلغاء العملية",
"CLOSE": "إغلاق",
"SHOW_DIAGRAM": "إظهار المخطط",
"DRAG-ATTACHMENT": "إفلات الملفات لتحميلها",
"UPLOAD-ATTACHMENT": "تحميل المرفق"
},
"MESSAGES": {
"NONE": "لم يتم العثور على تفاصيل العملية"
},
"TASKS": {
"NO_ACTIVE": "لا توجد مهام نشطة حاليًا",
"NO_COMPLETED": "لم تكتمل أي مهام بعد",
"TASK_DETAILS": "تفاصيل المهمة",
"TASK_CLOSE": "إغلاق"
},
"COMMENTS": {
"ADD": "إضافة تعليق",
"HEADER": "التعليقات ({{ count }})",
"NONE": "لا تعليقات",
"BUTTON": {
"ADD": "إضافة تعليق"
},
"ADD_DIALOG": {
"TITLE": "تعليق جديد",
"LABEL": {
"MESSAGE": "رسالة"
},
"BUTTON": {
"ADD": "إضافة تعليق",
"CANCEL": "إلغاء"
}
}
},
"ADD_DIALOG": {
"TITLE": "تعيين متغير العملية",
"LABEL": {
"NAME": "الاسم",
"VALUE": "القيمة",
"SCOPE": "نطاق"
}
},
"EDIT_DIALOG": {
"TITLE": "تحرير متغير العملية"
},
"ERROR_DIALOG": {
"TITLE": "تعذر إتمام الإجراء",
"DESCRIPTION": "قد لا يكون لديك مستوى الوصول المطلوب، تحقق الأمر مع فريق تكنولوجيا المعلومات لديك."
}
},
"START_PROCESS": {
"BUTTON": "بدء العملية",
"NO_PROCESS_DEFINITIONS": "لا يمكنك بدء عملية حيث لا توجد تعريفات عملية متاحة",
"FORM": {
"TITLE": "بدء العملية",
"LABEL": {
"TYPE": "تحديد عملية",
"NAME": "اسم العملية"
},
"TYPE_PLACEHOLDER": "اختر واحدة...",
"ACTION": {
"START": "بدء العملية",
"CANCEL": "إلغاء"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "تعذر تحميل تعريفات العملية، تأكد أن لديك حق الوصول.",
"START": "تعذر بدء مثيل عملية جديد، تأكد أن لديك حق الوصول.",
"MAXIMUM_LENGTH": "تم تجاوز الطول، {{characters}} من الحد الأقصى للحروف."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "هذه القائمة فارغة",
"DRAG-AND-DROP": {
"TITLE": "سحب وإفلات",
"SUBTITLE": "لتحميل الملفات"
}
},
"EMPTY-LIST": {
"HEADER": "لا توجد ملفات متاحة"
},
"COLUMNS": {
"NAME": "الاسم",
"CREATED-ON": "تم الإنشاء في"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "إنشاء",
"NEW_TASK": "مهمة جديدة",
"NEW_PROCESS": "عملية جديدة"
}
},
"APP": {
"DIALOG": {
"START": "متابعة",
"TITLE": "تحديد تطبيق عملية",
"LIST": "قائمة تطبيقات العمليات",
"ERROR": "توجد مشكلة في الاتصال Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "دخول",
"CANCEL": "إلغاء",
"CHOOSE": "اختيار"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Kliknutím na tlačítko Uložit přidáte zprávu se současným nastavením do svého seznamu zpráv.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Datum zahájení",
"END-DATE": "Datum ukončení",
"MESSAGES": {
"START-DATE-REQUIRED": "Je třeba zadat datum zahájení",
"START-LESS-THAN-END-DATE": "Datum zahájení musí předcházet datu ukončení"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Nenalezeny žádné aplikace",
"SUBTITLE": "Pro lepší přehlednost vytvořte novou aplikaci",
"TASK_APP_NAME": "Aplikace úkolů"
},
"LIST": {
"MESSAGES": {
"TITLE": "Nenalezeny žádné úkoly",
"SUBTITLE": "Pro lepší přehlednost vytvořte nový úkol",
"NONE": "Nenalezeny žádné seznamy úkolů"
}
},
"PROPERTIES": {
"TASK_NAME": "Úkol",
"THUMBNAIL": "Miniatura",
"DURATION": "Trvání",
"PARENT_TASK_ID": "ID nadřazeného úkolu",
"NAME": "Název",
"ASSIGNEE": "Pověřená osoba",
"ASSIGNEE_DEFAULT": "Žádná pověřená osoba",
"PRIORITY": "Priorita",
"DUE_DATE": "Termín",
"DUE_DATE_DEFAULT": "Žádné datum",
"STATUS": "Stav",
"CATEGORY": "Kategorie",
"CATEGORY_DEFAULT": "Žádná kategorie",
"PARENT_NAME": "Název nadřazené složky",
"PARENT_NAME_DEFAULT": "Žádná nadřazená složka",
"CREATED_BY": "Vytvořil(a)",
"CREATED": "Vytvořeno",
"END_DATE": "Datum ukončení",
"ID": "ID",
"DESCRIPTION": "Popis",
"DESCRIPTION_DEFAULT": "Žádný popis",
"FORM_NAME": "Název formuláře",
"FORM_NAME_DEFAULT": "Žádný formulář"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Zobrazit",
"REMOVE_CONTENT": "Odstranit",
"DOWNLOAD_CONTENT": "Stáhnout",
"DOWNLOAD_AUDIT": "Stáhnout audit"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktivity",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivita",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Podrobnosti",
"ASSIGNEE": "Pověřená osoba",
"DUE": "Termín",
"FORM": "Formulář",
"PEOPLE": "Osoby, se kterými je tento úkol sdílený",
"COMMENTS": "Poznámky",
"CHECKLIST": "Kontrolní seznam",
"INVOLVED_PEOPLE": "Zapojené osoby",
"ADD_PEOPLE": "Přidat osoby a skupiny",
"ADD_ASSIGNEE": "Přidat novou pověřenou osobu"
},
"BUTTON": {
"COMPLETE": "Dokončit",
"CLAIM": "Převzít",
"UNCLAIM": "Vzdát se",
"DRAG-ATTACHMENT": "Přetáhněte soubory, které chcete odeslat",
"UPLOAD-ATTACHMENT": "Odeslat přílohu"
},
"MESSAGES": {
"NONE": "Nenalezeny žádné podrobnosti o úkolu",
"CLAIM": "Po kliknutí na tlačítko Převzít můžete začít pracovat na tomto úkolu"
},
"FORM": {
"NONE": "Žádný formulář"
},
"DUE": {
"NONE": "Žádný termín"
},
"ASSIGNEE": {
"NONE": "Žádná pověřená osoba"
},
"PEOPLE": {
"NONE": "Nikdo není zapojen"
},
"CHECKLIST": {
"NONE": "Žádný kontrolní seznam",
"DIALOG": {
"TITLE": "Nová kontrola",
"CANCEL-BUTTON": "Zrušit",
"ADD-BUTTON": "Přidat kontrolní seznam",
"PLACEHOLDER": "Název"
}
},
"ERROR": {
"TITLE": "Akci se nepodařilo dokončit",
"DESCRIPTION": "Zkuste to znovu nebo se ujistěte, že máte potřebná přístupová oprávnění.",
"CLOSE": "Zavřít"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nebyl vybrán žádný filtr úkolů"
}
},
"START_TASK": {
"DEFAULT_NAME": "Můj výchozí úkol",
"BUTTON": "Vytvořit úkol",
"FORM": {
"TITLE": "Zahájit úkol",
"LABEL": {
"NONE": "Žádný",
"NAME": "Název",
"DESCRIPTION": "Popis",
"ATTACHFORM": "Připojit formulář",
"ASSIGNEE": "Pověřená osoba",
"FORM": "Formulář",
"DATE": "Zvolit datum"
},
"ACTION": {
"START": "Spustit",
"CANCEL": "Zrušit"
},
"ERROR": {
"REQUIRED": "Povinné pole",
"DATE": "Formát data je DD/MM/RRRR",
"MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků).",
"MESSAGE": "Zadejte jinou hodnotu"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Pověřená osoba",
"DIALOG_CLOSE": "Zavřít",
"ADD_USER": "Přidat",
"ADD_ASSIGNEE": "Přiřadit",
"SEARCH_USER": "Hledat uživatele",
"SEARCH": {
"NO_USERS": "Nenalezen nikdo, koho by bylo možné zapojit"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Tento seznam je prázdný",
"DRAG-AND-DROP": {
"TITLE": "Přetažením",
"SUBTITLE": "odešlete soubory"
}
},
"EMPTY-LIST": {
"HEADER": "Nejsou k dispozici žádné soubory"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Nepřipojeny žádné formuláře",
"COMPLETE_TASK_MESSAGE": "Úkol {{taskName}} dokončen",
"COMPLETE_TASK_SUB_MESSAGE": "Žádné formuláře určené k připojení"
},
"ATTACH_FORM": {
"SELECT_FORM": "Vyberte formulář, který chcete připojit",
"REMOVE_FORM": "Odebrat formulář",
"SELECT_OPTION": "Vybrat možnost"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Nenalezeny žádné procesy",
"SUBTITLE": "Pro lepší přehlednost vytvořte nový proces",
"SUMMARY": "Nalezené instance procesu: {{total}}",
"ERROR": "Instance procesu se nepodařilo načíst. Zkuste to znovu nebo oddělení IT předejte následující zprávu: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nebyl zvolen žádný filtr instancí."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Proces",
"NAME": "Název",
"THUMBNAIL": "Miniatura",
"STATUS": "Stav",
"END_DATE": "Datum ukončení",
"END_DATE_DEFAULT": "Žádné datum",
"CATEGORY": "Kategorie",
"CATEGORY_DEFAULT": "Žádná kategorie",
"CREATED_BY": "Vytvořil(a)",
"CREATED_BY_DEFAULT": "Žádná pověřená osoba",
"CREATED": "Vytvořeno",
"BUSINESS_KEY": "Obchodní klíč",
"BUSINESS_KEY_DEFAULT": "Žádný",
"DESCRIPTION": "Popis",
"DESCRIPTION_DEFAULT": "Žádný popis",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Zobrazit",
"REMOVE_CONTENT": "Odstranit",
"DOWNLOAD_CONTENT": "Stáhnout",
"DOWNLOAD_AUDIT": "Stáhnout audit",
"VIEW_TASK": "Zobrazit úkol"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Zahájil(a)",
"STARTED": "Zahájeno",
"ENDED": "Ukončeno",
"COMMENTS": "Poznámky",
"START_FORM": "Spustit formulář",
"TASKS_ACTIVE": "Aktivní úkoly",
"TASKS_COMPLETED": "Dokončené úkoly",
"TASK_SUBTITLE": "Přiřazeno: {{user}}. Vytvořeno k {{created}}"
},
"BUTTON": {
"CANCEL": "Zrušit proces",
"CLOSE": "Zavřít",
"SHOW_DIAGRAM": "Zobrazit diagram",
"DRAG-ATTACHMENT": "Přetáhněte soubory, které chcete odeslat",
"UPLOAD-ATTACHMENT": "Odeslat přílohu"
},
"MESSAGES": {
"NONE": "Nenalezeny žádné podrobnosti o procesu"
},
"TASKS": {
"NO_ACTIVE": "Momentálně nejsou aktivní žádné úkoly",
"NO_COMPLETED": "Nebyly zatím dokončeny žádné úkoly",
"TASK_DETAILS": "Podrobnosti o úkolu",
"TASK_CLOSE": "Zavřít"
},
"COMMENTS": {
"ADD": "Přidat komentář",
"HEADER": "Komentáře ({{ count }})",
"NONE": "Žádné komentáře",
"BUTTON": {
"ADD": "Přidat komentář"
},
"ADD_DIALOG": {
"TITLE": "Nový komentář",
"LABEL": {
"MESSAGE": "Zpráva"
},
"BUTTON": {
"ADD": "Přidat komentář",
"CANCEL": "Zrušit"
}
}
},
"ADD_DIALOG": {
"TITLE": "Nastavit proměnnou procesu",
"LABEL": {
"NAME": "Název",
"VALUE": "Hodnota",
"SCOPE": "Rozsah"
}
},
"EDIT_DIALOG": {
"TITLE": "Upravit proměnnou procesu"
},
"ERROR_DIALOG": {
"TITLE": "Akci se nepodařilo dokončit",
"DESCRIPTION": "Nemáte pravděpodobně potřebná přístupová oprávněni. Obraťte se na oddělení IT."
}
},
"START_PROCESS": {
"BUTTON": "Zahájit proces",
"NO_PROCESS_DEFINITIONS": "Proces nelze zahájit, protože nejsou k dispozici žádné definice procesu",
"FORM": {
"TITLE": "Zahájit proces",
"LABEL": {
"TYPE": "Vybrat proces",
"NAME": "Název procesu"
},
"TYPE_PLACEHOLDER": "Vyberte...",
"ACTION": {
"START": "Zahájit proces",
"CANCEL": "Zrušit"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Definice procesu se nepodařilo načíst. Zkontrolujte svá přístupová oprávnění.",
"START": "Nepodařilo se spustit novou instanci procesu. Zkontrolujte svá přístupová oprávnění.",
"MAXIMUM_LENGTH": "Přesáhli jste délku (maximálně lze zadat {{characters}} znaků)."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Tento seznam je prázdný",
"DRAG-AND-DROP": {
"TITLE": "Přetažením",
"SUBTITLE": "odešlete soubory"
}
},
"EMPTY-LIST": {
"HEADER": "Nejsou k dispozici žádné soubory"
},
"COLUMNS": {
"NAME": "Název",
"CREATED-ON": "Vytvořeno"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Vytvořit",
"NEW_TASK": "Nový úkol",
"NEW_PROCESS": "Nový proces"
}
},
"APP": {
"DIALOG": {
"START": "Pokračovat",
"TITLE": "Vyberte procesní aplikaci",
"LIST": "Seznam procesních aplikací",
"ERROR": "Při pokusu připojit se k aplikaci Process Services došlo k problému"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Přihlášení",
"CANCEL": "Zrušit",
"CHOOSE": "Vybrat"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Klik på Gem for at tilføje en rapport med de aktuelle indstillinger på din rapportliste.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Startdato",
"END-DATE": "Slutdato",
"MESSAGES": {
"START-DATE-REQUIRED": "Startdatoen er påkrævet",
"START-LESS-THAN-END-DATE": "Startdatoen skal være før slutdatoen"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Der blev ikke fundet nogen programmer",
"SUBTITLE": "Opret et nyt program, som skal være nemt at finde senere",
"TASK_APP_NAME": "Opgaveapp"
},
"LIST": {
"MESSAGES": {
"TITLE": "Der blev ikke fundet nogen opgaver",
"SUBTITLE": "Opret en ny opgave, som skal være nem at finde senere",
"NONE": "Der blev ikke fundet nogen opgavelister"
}
},
"PROPERTIES": {
"TASK_NAME": "Opgave",
"THUMBNAIL": "Miniaturevisning",
"DURATION": "Varighed",
"PARENT_TASK_ID": "Id for overordnet opgave",
"NAME": "Navn",
"ASSIGNEE": "Modtager",
"ASSIGNEE_DEFAULT": "Ingen modtager",
"PRIORITY": "Prioritet",
"DUE_DATE": "Forfaldsdato",
"DUE_DATE_DEFAULT": "Ingen dato",
"STATUS": "Status",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"PARENT_NAME": "Overordnet navn",
"PARENT_NAME_DEFAULT": "Ingen overordnet",
"CREATED_BY": "Oprettet af",
"CREATED": "Oprettet",
"END_DATE": "Slutdato",
"ID": "Id",
"DESCRIPTION": "Beskrivelse",
"DESCRIPTION_DEFAULT": "Ingen beskrivelse",
"FORM_NAME": "Formularnavn",
"FORM_NAME_DEFAULT": "Ingen formular"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Vis",
"REMOVE_CONTENT": "Fjern",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Download overvågning"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktiviteter",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivitet",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Detaljer",
"ASSIGNEE": "Modtager",
"DUE": "Forfalder",
"FORM": "Formular",
"PEOPLE": "Personer, som denne opgave er delt med",
"COMMENTS": "Kommentarer",
"CHECKLIST": "Tjekliste",
"INVOLVED_PEOPLE": "Involverede personer",
"ADD_PEOPLE": "Tilføj personer og grupper",
"ADD_ASSIGNEE": "Tilføj ny modtager"
},
"BUTTON": {
"COMPLETE": "Fuldført",
"CLAIM": "Gør krav på",
"UNCLAIM": "Frigiv",
"DRAG-ATTACHMENT": "Slip filer for at uploade dem",
"UPLOAD-ATTACHMENT": "Upload vedhæftet fil"
},
"MESSAGES": {
"NONE": "Der blev ikke fundet nogen opgavedetaljer",
"CLAIM": "Klik på Gør krav på for at arbejde på denne opgave"
},
"FORM": {
"NONE": "Ingen formular"
},
"DUE": {
"NONE": "Ingen forfaldsdato"
},
"ASSIGNEE": {
"NONE": "Ingen modtager"
},
"PEOPLE": {
"NONE": "Der er ingen involverede"
},
"CHECKLIST": {
"NONE": "Ingen tjekliste",
"DIALOG": {
"TITLE": "Nyt tjek",
"CANCEL-BUTTON": "Annuller",
"ADD-BUTTON": "Tilføj kontrolliste",
"PLACEHOLDER": "Navn"
}
},
"ERROR": {
"TITLE": "Handlingen kunne ikke fuldføres",
"DESCRIPTION": "Prøv igen, eller kontrollér, om du har adgang.",
"CLOSE": "Luk"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Der er ikke valgt noget opgavefilter"
}
},
"START_TASK": {
"DEFAULT_NAME": "Min standardopgave",
"BUTTON": "Opret opgave",
"FORM": {
"TITLE": "Start opgave",
"LABEL": {
"NONE": "Ingen",
"NAME": "Navn",
"DESCRIPTION": "Beskrivelse",
"ATTACHFORM": "Vedhæft formular",
"ASSIGNEE": "Modtager",
"FORM": "Formular",
"DATE": "Vælg dato"
},
"ACTION": {
"START": "Start",
"CANCEL": "Annuller"
},
"ERROR": {
"REQUIRED": "Obligatorisk felt",
"DATE": "Datoformat DD/MM/ÅÅÅÅ",
"MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn",
"MESSAGE": "Angiv en anden værdi"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Modtager",
"DIALOG_CLOSE": "Luk",
"ADD_USER": "Tilføj",
"ADD_ASSIGNEE": "Tildel",
"SEARCH_USER": "Søg efter bruger",
"SEARCH": {
"NO_USERS": "Der blev ikke fundet nogen involverede"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Denne liste er tom",
"DRAG-AND-DROP": {
"TITLE": "Træk og slip",
"SUBTITLE": "for at uploade filer"
}
},
"EMPTY-LIST": {
"HEADER": "Der er ingen tilgængelige filer"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Der er ikke vedhæftet en formular",
"COMPLETE_TASK_MESSAGE": "Opgaven {{taskName}} er fuldført",
"COMPLETE_TASK_SUB_MESSAGE": "Der er ikke tilføjet nogen formularer"
},
"ATTACH_FORM": {
"SELECT_FORM": "Vælg den formular, du vil vedhæfte",
"REMOVE_FORM": "Fjern formular",
"SELECT_OPTION": "Vælg en valgmulighed"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Der blev ikke fundet nogen processer",
"SUBTITLE": "Opret en ny proces, som skal være nem at finde senere",
"SUMMARY": "{{total}} procesforekomster fundet",
"ERROR": "Procesforekomsterne kunne ikke indlæses. Prøv igen, eller giv følgende meddelelse til din it-afdeling: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Der er ikke valgt et filter for procesforekomster."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Proces",
"NAME": "Navn",
"THUMBNAIL": "Miniaturevisning",
"STATUS": "Status",
"END_DATE": "Slutdato",
"END_DATE_DEFAULT": "Ingen dato",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"CREATED_BY": "Oprettet af",
"CREATED_BY_DEFAULT": "Ingen modtager",
"CREATED": "Oprettet",
"BUSINESS_KEY": "Forretningsnøgle",
"BUSINESS_KEY_DEFAULT": "Ingen",
"DESCRIPTION": "Beskrivelse",
"DESCRIPTION_DEFAULT": "Ingen beskrivelse",
"ID": "Id"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Vis",
"REMOVE_CONTENT": "Fjern",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Download overvågning",
"VIEW_TASK": "Vis opgave"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Startet af",
"STARTED": "Startet",
"ENDED": "Sluttet",
"COMMENTS": "Kommentarer",
"START_FORM": "Åbn formular",
"TASKS_ACTIVE": "Aktive opgaver",
"TASKS_COMPLETED": "Fuldførte opgaver",
"TASK_SUBTITLE": "Tildelt til {{user}}, oprettet {{created}}"
},
"BUTTON": {
"CANCEL": "Annuller proces",
"CLOSE": "Luk",
"SHOW_DIAGRAM": "Vis diagram",
"DRAG-ATTACHMENT": "Slip filer for at uploade dem",
"UPLOAD-ATTACHMENT": "Upload vedhæftet fil"
},
"MESSAGES": {
"NONE": "Der blev ikke fundet nogen procesdetaljer"
},
"TASKS": {
"NO_ACTIVE": "Der er ikke nogen aktive opgaver",
"NO_COMPLETED": "Der er endnu ikke fuldført nogen opgaver",
"TASK_DETAILS": "Opgavedetaljer",
"TASK_CLOSE": "Luk"
},
"COMMENTS": {
"ADD": "Tilføj en kommentar",
"HEADER": "Kommentarer ({{ count }})",
"NONE": "Ingen kommentarer",
"BUTTON": {
"ADD": "Tilføj en kommentar"
},
"ADD_DIALOG": {
"TITLE": "Ny kommentar",
"LABEL": {
"MESSAGE": "Meddelelse"
},
"BUTTON": {
"ADD": "Tilføj kommentar",
"CANCEL": "Annuller"
}
}
},
"ADD_DIALOG": {
"TITLE": "Angiv procesvariabel",
"LABEL": {
"NAME": "Navn",
"VALUE": "Værdi",
"SCOPE": "Omfang"
}
},
"EDIT_DIALOG": {
"TITLE": "Rediger procesvariabel"
},
"ERROR_DIALOG": {
"TITLE": "Handlingen kunne ikke fuldføres",
"DESCRIPTION": "Du har muligvis ikke det påkrævede adgangsniveau. Kontakt din it-afdeling."
}
},
"START_PROCESS": {
"BUTTON": "Start proces",
"NO_PROCESS_DEFINITIONS": "Du kan ikke starte en proces, da der ikke er nogen tilgængelige procesdefinitioner",
"FORM": {
"TITLE": "Start proces",
"LABEL": {
"TYPE": "Vælg proces",
"NAME": "Procesnavn"
},
"TYPE_PLACEHOLDER": "Vælg en...",
"ACTION": {
"START": "Start proces",
"CANCEL": "Annuller"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Der kunne ikke indlæses nogen procesdefinitioner. Kontrollér, om du har adgang til dem.",
"START": "Der kunne ikke startes en ny procesforekomst. Kontrollér, om du har adgang.",
"MAXIMUM_LENGTH": "Længden er overskredet, maks. {{characters}} tegn."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Denne liste er tom",
"DRAG-AND-DROP": {
"TITLE": "Træk og slip",
"SUBTITLE": "for at uploade filer"
}
},
"EMPTY-LIST": {
"HEADER": "Der er ingen tilgængelige filer"
},
"COLUMNS": {
"NAME": "Navn",
"CREATED-ON": "Oprettet den"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Opret",
"NEW_TASK": "Ny opgave",
"NEW_PROCESS": "Ny proces"
}
},
"APP": {
"DIALOG": {
"START": "Fortsæt",
"TITLE": "Vælg en procesapp",
"LIST": "Liste over procesapps",
"ERROR": "Der kan ikke oprettes forbindelse til Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Log ind",
"CANCEL": "Annuller",
"CHOOSE": "Vælg"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Klicken Sie auf 'Speichern', um einen Bericht mit den derzeitigen Einstellungen zu Ihrer Berichteliste hinzuzufügen.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Startdatum",
"END-DATE": "Enddatum",
"MESSAGES": {
"START-DATE-REQUIRED": "Startdatum ist erforderlich",
"START-LESS-THAN-END-DATE": "Das Startdatum muss vor dem Enddatum liegen"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Keine Anwendungen gefunden",
"SUBTITLE": "Erstellen Sie eine neue Anwendung, die sich später leicht wiederfinden lässt",
"TASK_APP_NAME": "Aufgabenanwendung"
},
"LIST": {
"MESSAGES": {
"TITLE": "Keine Aufgaben gefunden",
"SUBTITLE": "Erstellen Sie eine neue Aufgabe, die sich später leicht wiederfinden lässt",
"NONE": "Keine Aufgabenliste gefunden"
}
},
"PROPERTIES": {
"TASK_NAME": "Aufgabe",
"THUMBNAIL": "Miniaturansicht",
"DURATION": "Dauer",
"PARENT_TASK_ID": "Übergeordnete Aufgaben-ID",
"NAME": "Name",
"ASSIGNEE": "Zugewiesener Benutzer",
"ASSIGNEE_DEFAULT": "Kein zugewiesener Benutzer",
"PRIORITY": "Priorität",
"DUE_DATE": "Fälligkeitsdatum",
"DUE_DATE_DEFAULT": "Kein Datum",
"STATUS": "Status",
"CATEGORY": "Kategorie",
"CATEGORY_DEFAULT": "Keine Kategorie",
"PARENT_NAME": "Name übergeordnetes Element",
"PARENT_NAME_DEFAULT": "Kein übergeordnetes Element",
"CREATED_BY": "Erstellt von",
"CREATED": "Erstellt",
"END_DATE": "Enddatum",
"ID": "ID",
"DESCRIPTION": "Beschreibung",
"DESCRIPTION_DEFAULT": "Keine Beschreibung",
"FORM_NAME": "Formularname",
"FORM_NAME_DEFAULT": "Kein Formular"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Anzeigen",
"REMOVE_CONTENT": "Entfernen",
"DOWNLOAD_CONTENT": "Herunterladen",
"DOWNLOAD_AUDIT": "Audit herunterladen"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktivitäten",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivität",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Details",
"ASSIGNEE": "Zugewiesener Benutzer",
"DUE": "Fällig",
"FORM": "Formular",
"PEOPLE": "Personen, für die diese Aufgabe freigegeben wurde",
"COMMENTS": "Kommentare",
"CHECKLIST": "Prüfliste",
"INVOLVED_PEOPLE": "Beteiligte Personen",
"ADD_PEOPLE": "Personen und Gruppen hinzufügen",
"ADD_ASSIGNEE": "Neuen zugewiesenen Benutzer hinzufügen"
},
"BUTTON": {
"COMPLETE": "Abschließen",
"CLAIM": "Beanspruchen",
"UNCLAIM": "Anspruch aufheben",
"DRAG-ATTACHMENT": "Dateien zum Hochladen ablegen",
"UPLOAD-ATTACHMENT": "Anhang hochladen"
},
"MESSAGES": {
"NONE": "Keine Aufgabendetails gefunden",
"CLAIM": "Klicken Sie auf 'Beanspruchen', um diese Aufgabe zu bearbeiten"
},
"FORM": {
"NONE": "Kein Formular"
},
"DUE": {
"NONE": "Kein Fälligkeitsdatum"
},
"ASSIGNEE": {
"NONE": "Kein zugewiesener Benutzer"
},
"PEOPLE": {
"NONE": "Niemand beteiligt"
},
"CHECKLIST": {
"NONE": "Keine Prüfliste",
"DIALOG": {
"TITLE": "Neue Auswahl",
"CANCEL-BUTTON": "Abbrechen",
"ADD-BUTTON": "Prüfliste hinzufügen",
"PLACEHOLDER": "Name"
}
},
"ERROR": {
"TITLE": "Vorgang konnte nicht durchgeführt werden",
"DESCRIPTION": "Versuchen Sie es noch einmal oder überprüfen Sie, ob Sie Zugriff haben.",
"CLOSE": "Schließen"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Kein Aufgabenfilter ausgewählt"
}
},
"START_TASK": {
"DEFAULT_NAME": "Meine Standardaufgabe",
"BUTTON": "Aufgabe erstellen",
"FORM": {
"TITLE": "Aufgabe starten",
"LABEL": {
"NONE": "Keine",
"NAME": "Name",
"DESCRIPTION": "Beschreibung",
"ATTACHFORM": "Formular anhängen",
"ASSIGNEE": "Zugewiesener Benutzer",
"FORM": "Formular",
"DATE": "Datum auswählen"
},
"ACTION": {
"START": "Start",
"CANCEL": "Abbrechen"
},
"ERROR": {
"REQUIRED": "Feld erforderlich",
"DATE": "Datumsformat TT.MM.JJJJ",
"MAXIMUM_LENGTH": "Max. Länge überschritten, max. {{characters}} Zeichen",
"MESSAGE": "Geben Sie einen anderen Wert ein"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Zugewiesener Benutzer",
"DIALOG_CLOSE": "Schließen",
"ADD_USER": "Hinzufügen",
"ADD_ASSIGNEE": "Zuweisen",
"SEARCH_USER": "Benutzer suchen",
"SEARCH": {
"NO_USERS": "Niemand gefunden, der beteiligt werden kann"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Diese Liste ist leer",
"DRAG-AND-DROP": {
"TITLE": "Ziehen und ablegen",
"SUBTITLE": "um Dateien hochzuladen"
}
},
"EMPTY-LIST": {
"HEADER": "Keine Dateien verfügbar"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Keine Formulare angehängt",
"COMPLETE_TASK_MESSAGE": "Aufgabe {{taskName}} abgeschlossen",
"COMPLETE_TASK_SUB_MESSAGE": "Keine Formulare, die hinzugefügt werden können"
},
"ATTACH_FORM": {
"SELECT_FORM": "Abzuhängendes Formular auswählen",
"REMOVE_FORM": "Formular entfernen",
"SELECT_OPTION": "Option auswählen"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Keine Prozesse gefunden",
"SUBTITLE": "Erstellen Sie einen neuen Prozess, der sich später leicht wiederfinden lässt",
"SUMMARY": "{{total}} Prozessinstanzen gefunden",
"ERROR": "Prozessesinstanzen konnten nicht geladen werden. Versuchen Sie es noch einmal oder geben Sie die folgende Meldung an Ihr IT-Team weiter: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Kein Prozessinstanzfilter ausgewählt."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Prozess",
"NAME": "Name",
"THUMBNAIL": "Miniaturansicht",
"STATUS": "Status",
"END_DATE": "Enddatum",
"END_DATE_DEFAULT": "Kein Datum",
"CATEGORY": "Kategorie",
"CATEGORY_DEFAULT": "Keine Kategorie",
"CREATED_BY": "Erstellt von",
"CREATED_BY_DEFAULT": "Kein zugewiesener Benutzer",
"CREATED": "Erstellt",
"BUSINESS_KEY": "Geschäftsschlüssel",
"BUSINESS_KEY_DEFAULT": "Keine",
"DESCRIPTION": "Beschreibung",
"DESCRIPTION_DEFAULT": "Keine Beschreibung",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Anzeigen",
"REMOVE_CONTENT": "Entfernen",
"DOWNLOAD_CONTENT": "Herunterladen",
"DOWNLOAD_AUDIT": "Audit herunterladen",
"VIEW_TASK": "Aufgabe anzeigen"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Gestartet von",
"STARTED": "Gestartet",
"ENDED": "Beendet",
"COMMENTS": "Kommentare",
"START_FORM": "Startformular",
"TASKS_ACTIVE": "Aktive Aufgaben",
"TASKS_COMPLETED": "Abgeschlossene Aufgaben",
"TASK_SUBTITLE": "Zugewiesen: {{user}}. Erstellt: {{created}}"
},
"BUTTON": {
"CANCEL": "Prozess abbrechen",
"CLOSE": "Schließen",
"SHOW_DIAGRAM": "Diagramm anzeigen",
"DRAG-ATTACHMENT": "Dateien zum Hochladen ablegen",
"UPLOAD-ATTACHMENT": "Anhang hochladen"
},
"MESSAGES": {
"NONE": "Keine Prozessdetails gefunden"
},
"TASKS": {
"NO_ACTIVE": "Keine derzeit aktiven Aufgaben",
"NO_COMPLETED": "Noch keine Aufgaben abgeschlossen",
"TASK_DETAILS": "Aufgabendetails",
"TASK_CLOSE": "Schließen"
},
"COMMENTS": {
"ADD": "Kommentar hinzufügen",
"HEADER": "Kommentare ({{ count }})",
"NONE": "Keine Kommentare vorhanden",
"BUTTON": {
"ADD": "Kommentar hinzufügen"
},
"ADD_DIALOG": {
"TITLE": "Neuer Kommentar",
"LABEL": {
"MESSAGE": "Fehlermeldung"
},
"BUTTON": {
"ADD": "Kommentar hinzufügen",
"CANCEL": "Abbrechen"
}
}
},
"ADD_DIALOG": {
"TITLE": "Prozessvariable festlegen",
"LABEL": {
"NAME": "Name",
"VALUE": "Wert",
"SCOPE": "Bereich"
}
},
"EDIT_DIALOG": {
"TITLE": "Prozessvariable bearbeiten"
},
"ERROR_DIALOG": {
"TITLE": "Vorgang konnte nicht durchgeführt werden",
"DESCRIPTION": "Unter Umständen verfügen Sie nicht über die erforderlichen Zugriffsrechte. Wenden Sie sich an Ihr IT-Team."
}
},
"START_PROCESS": {
"BUTTON": "Prozess starten",
"NO_PROCESS_DEFINITIONS": "Sie können keinen Prozess starten, weil es keine Prozessdefinitionen gibt",
"FORM": {
"TITLE": "Prozess starten",
"LABEL": {
"TYPE": "Prozess auswählen",
"NAME": "Prozessname"
},
"TYPE_PLACEHOLDER": "Eine auswählen...",
"ACTION": {
"START": "Prozess starten",
"CANCEL": "Abbrechen"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Prozessdefinitionen konnten nicht geladen werden. Überprüfen Sie, ob Sie über die nötigen Zugriffsrechte verfügen.",
"START": "Neue Prozessinstanz konnte nicht gestartet werden. Überprüfen Sie, ob Sie über die nötigen Zugriffsrechte verfügen.",
"MAXIMUM_LENGTH": "Max. Länge überschritten, max. {{characters}} Zeichen."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Diese Liste ist leer",
"DRAG-AND-DROP": {
"TITLE": "Ziehen und ablegen",
"SUBTITLE": "um Dateien hochzuladen"
}
},
"EMPTY-LIST": {
"HEADER": "Keine Dateien verfügbar"
},
"COLUMNS": {
"NAME": "Name",
"CREATED-ON": "Erstellt am"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Erstellen",
"NEW_TASK": "Neue Aufgabe",
"NEW_PROCESS": "Neuer Prozess"
}
},
"APP": {
"DIALOG": {
"START": "Weiter",
"TITLE": "App auswählen",
"LIST": "App-Übersicht",
"ERROR": "Bei der Verbindung zu Process Services ist ein Fehler aufgetreten"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Anmelden",
"CANCEL": "Abbrechen",
"CHOOSE": "Auswählen"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Click Save to add a report with the current settings to your reports list.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Start date",
"END-DATE": "End date",
"MESSAGES": {
"START-DATE-REQUIRED": "Start date is required",
"START-LESS-THAN-END-DATE": "Start date must be before end date"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "No Applications Found",
"SUBTITLE":"Create a new application that you want to easily find later",
"TASK_APP_NAME": "Task App"
},
"LIST": {
"MESSAGES": {
"TITLE": "No Tasks Found",
"SUBTITLE":"Create a new task that you want to easily find later",
"NONE": "No task lists found"
}
},
"PROPERTIES": {
"TASK_NAME": "Task",
"THUMBNAIL": "Thumbnail",
"DURATION": "Duration",
"PARENT_TASK_ID": "Parent task id",
"NAME": "Name",
"ASSIGNEE": "Assignee",
"ASSIGNEE_DEFAULT": "No assignee",
"PRIORITY": "Priority",
"DUE_DATE": "Due Date",
"DUE_DATE_DEFAULT": "No date",
"STATUS": "Status",
"CATEGORY": "Category",
"CATEGORY_DEFAULT": "No category",
"PARENT_NAME": "Parent name",
"PARENT_NAME_DEFAULT": "No parent",
"CREATED_BY": "Created By",
"CREATED": "Created",
"END_DATE": "End date",
"ID": "ID",
"DESCRIPTION": "Description",
"DESCRIPTION_DEFAULT": "No description",
"FORM_NAME": "Form Name",
"FORM_NAME_DEFAULT": "No form"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "View",
"REMOVE_CONTENT": "Remove",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Download Audit"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Activities",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Activity",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Details",
"ASSIGNEE": "Assignee",
"DUE": "Due",
"FORM": "Form",
"PEOPLE": "People this task is shared with",
"COMMENTS": "Comments",
"CHECKLIST": "Checklist",
"INVOLVED_PEOPLE": "People Involved",
"ADD_PEOPLE": "Add people and groups",
"ADD_ASSIGNEE": "Add new assignee"
},
"BUTTON": {
"COMPLETE": "Complete",
"CLAIM": "Claim",
"UNCLAIM": "Release",
"DRAG-ATTACHMENT": "Drop files to upload",
"UPLOAD-ATTACHMENT": "Upload Attachment"
},
"MESSAGES": {
"NONE": "No task details found",
"CLAIM": "Click Claim to work on this task"
},
"FORM": {
"NONE": "No form"
},
"DUE": {
"NONE": "No due date"
},
"ASSIGNEE": {
"NONE": "No assignee"
},
"PEOPLE": {
"NONE": "Nobody involved"
},
"CHECKLIST": {
"NONE": "No checklist",
"DIALOG" : {
"TITLE": "New Check",
"CANCEL-BUTTON": "Cancel",
"ADD-BUTTON": "Add Checklist",
"PLACEHOLDER": "Name"
}
},
"ERROR": {
"TITLE": "Couldn't complete the action",
"DESCRIPTION": "Try again or check that you have access.",
"CLOSE": "Close"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "No task filter selected"
}
},
"START_TASK": {
"DEFAULT_NAME": "My Default Task",
"BUTTON": "CREATE TASK",
"FORM": {
"TITLE": "Start Task",
"LABEL": {
"NONE": "None",
"NAME": "Name",
"DESCRIPTION": "Description",
"ATTACHFORM": "Attach Form",
"ASSIGNEE": "Assignee",
"FORM": "Form",
"DATE": "Choose Date"
},
"ACTION": {
"START": "Start",
"CANCEL": "Cancel"
},
"ERROR": {
"REQUIRED": "Field required",
"DATE": "Date format DD/MM/YYYY",
"MAXIMUM_LENGTH": "Length exceeded, {{characters}} characters max.",
"MESSAGE": "Enter a different value"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Assignee",
"DIALOG_CLOSE": "CLOSE",
"ADD_USER": "ADD",
"ADD_ASSIGNEE": "ASSIGN",
"SEARCH_USER": "Search user",
"SEARCH": {
"NO_USERS": "Nobody found to involve"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "This list is empty",
"DRAG-AND-DROP": {
"TITLE": "Drag and drop",
"SUBTITLE": "to upload files"
}
},
"EMPTY-LIST": {
"HEADER": "No files are available"
}
},
"STANDALONE_TASK":{
"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",
"REMOVE_FORM": "Remove Form",
"SELECT_OPTION": "Select an option"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "No Processes Found",
"SUBTITLE":"Create a new process that you want to easily find later",
"SUMMARY": "{{total}} process instances found",
"ERROR": "Couldn't load processes instances. Try again or share the following message with your IT Team: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "No process instance filter selected."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Process",
"NAME": "Name",
"THUMBNAIL": "Thumbnail",
"STATUS": "Status",
"END_DATE": "End Date",
"END_DATE_DEFAULT": "No date",
"CATEGORY": "Category",
"CATEGORY_DEFAULT": "No category",
"CREATED_BY": "Created By",
"CREATED_BY_DEFAULT": "No assignee",
"CREATED": "Created",
"BUSINESS_KEY": "Business key",
"BUSINESS_KEY_DEFAULT": "None",
"DESCRIPTION": "Description",
"DESCRIPTION_DEFAULT": "No description",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "View",
"REMOVE_CONTENT": "Remove",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Download audit",
"VIEW_TASK": "View Task"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Started by",
"STARTED": "Started",
"ENDED": "Ended",
"COMMENTS": "Comments",
"START_FORM": "Start Form",
"TASKS_ACTIVE": "Active Tasks",
"TASKS_COMPLETED": "Completed Tasks",
"TASK_SUBTITLE": "Assigned to {{user}}, created {{created}}"
},
"BUTTON": {
"CANCEL": "Cancel Process",
"CLOSE": "Close",
"SHOW_DIAGRAM": "Show Diagram",
"DRAG-ATTACHMENT": "Drop files to upload",
"UPLOAD-ATTACHMENT": "Upload Attachment"
},
"MESSAGES": {
"NONE": "No process details found"
},
"TASKS": {
"NO_ACTIVE": "No currently active tasks",
"NO_COMPLETED": "No tasks completed yet",
"TASK_DETAILS": "Task details",
"TASK_CLOSE": "Close"
},
"COMMENTS": {
"ADD": "Add a comment",
"HEADER": "Comments ({{ count }})",
"NONE": "No comments",
"BUTTON": {
"ADD": "Add a comment"
},
"ADD_DIALOG": {
"TITLE": "New comment",
"LABEL": {
"MESSAGE": "Message"
},
"BUTTON": {
"ADD": "Add Comment",
"CANCEL": "Cancel"
}
}
},
"ADD_DIALOG": {
"TITLE": "Set process variable",
"LABEL": {
"NAME": "Name",
"VALUE": "Value",
"SCOPE": "Scope"
}
},
"EDIT_DIALOG": {
"TITLE": "Edit process variable"
},
"ERROR_DIALOG": {
"TITLE": "Couldn't complete the action",
"DESCRIPTION": "You might not have the required access level, check with your IT Team."
}
},
"START_PROCESS": {
"BUTTON": "Start Process",
"NO_PROCESS_DEFINITIONS": "You can't start a process as there are no process definitions available",
"FORM": {
"TITLE": "Start Process",
"LABEL": {
"TYPE": "Select Process",
"NAME": "Process Name"
},
"TYPE_PLACEHOLDER": "Choose one...",
"ACTION": {
"START": "Start Process",
"CANCEL": "Cancel"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Couldn't load process definitions, check you have access.",
"START": "Couldn't start new process instance, check you have access.",
"MAXIMUM_LENGTH": "Length exceeded, {{characters}} characters max."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "This list is empty",
"DRAG-AND-DROP": {
"TITLE": "Drag and drop",
"SUBTITLE": "to upload files"
}
},
"EMPTY-LIST": {
"HEADER": "No files are available"
},
"COLUMNS": {
"NAME": "Name",
"CREATED-ON": "Created on"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "CREATE",
"NEW_TASK": "New Task",
"NEW_PROCESS": "New Process"
}
},
"APP":{
"DIALOG" :{
"START" : "Continue",
"TITLE" : "Select a process app",
"LIST": "Process App list",
"ERROR" : "There is a problem connecting to Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Login",
"CANCEL": "Cancel",
"CHOOSE": "Choose"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Haga clic en Guardar para añadir un informe con los ajustes actuales a su lista de informes.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Fecha de inicio",
"END-DATE": "Fecha de fin",
"MESSAGES": {
"START-DATE-REQUIRED": "Se necesita fecha de inicio",
"START-LESS-THAN-END-DATE": "La fecha de inicio debe ser anterior a la fecha de finalización"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "No se han encontrado aplicaciones",
"SUBTITLE": "Cree una nueva aplicación que desee encontrar fácilmente después",
"TASK_APP_NAME": "Aplicación de tareas"
},
"LIST": {
"MESSAGES": {
"TITLE": "Ninguna tarea encontrada",
"SUBTITLE": "Crear una nueva tarea que desee encontrar fácilmente después",
"NONE": "No se han encontrado listas de tareas"
}
},
"PROPERTIES": {
"TASK_NAME": "Tarea",
"THUMBNAIL": "Miniatura",
"DURATION": "Duración",
"PARENT_TASK_ID": "ID de tarea primaria",
"NAME": "Nombre",
"ASSIGNEE": "Asignado a",
"ASSIGNEE_DEFAULT": "Sin asignado",
"PRIORITY": "Prioridad",
"DUE_DATE": "Fecha de vencimiento",
"DUE_DATE_DEFAULT": "Sin fecha",
"STATUS": "Estado",
"CATEGORY": "Categoría",
"CATEGORY_DEFAULT": "Sin categoría",
"PARENT_NAME": "Nombre del elemento primario",
"PARENT_NAME_DEFAULT": "Sin elemento primario",
"CREATED_BY": "Creado por",
"CREATED": "Creado",
"END_DATE": "Fecha de fin",
"ID": "ID",
"DESCRIPTION": "Descripción",
"DESCRIPTION_DEFAULT": "Sin descripción",
"FORM_NAME": "Nombre del formulario",
"FORM_NAME_DEFAULT": "No hay formulario"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Ver",
"REMOVE_CONTENT": "Eliminar",
"DOWNLOAD_CONTENT": "Descargar",
"DOWNLOAD_AUDIT": "Descargar auditoría"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Actividades",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Actividad",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Detalles",
"ASSIGNEE": "Asignado a",
"DUE": "Vencimiento",
"FORM": "Formulario",
"PEOPLE": "Personas con las que se comparte esta tarea",
"COMMENTS": "Comentarios",
"CHECKLIST": "Lista de comprobación",
"INVOLVED_PEOPLE": "Personas participantes",
"ADD_PEOPLE": "Añadir personas y grupos",
"ADD_ASSIGNEE": "Añadir nuevo asignado"
},
"BUTTON": {
"COMPLETE": "Completar",
"CLAIM": "Pedir",
"UNCLAIM": "Liberar",
"DRAG-ATTACHMENT": "Arrastrar ficheros a cargar",
"UPLOAD-ATTACHMENT": "Cargar adjunto"
},
"MESSAGES": {
"NONE": "No se han encontrado detalles de la tarea",
"CLAIM": "Haga clic en Pedir para trabajar en esta tarea"
},
"FORM": {
"NONE": "No hay formulario"
},
"DUE": {
"NONE": "No hay fecha de vencimiento"
},
"ASSIGNEE": {
"NONE": "Sin asignado"
},
"PEOPLE": {
"NONE": "Ningún participante"
},
"CHECKLIST": {
"NONE": "No hay lista de comprobación",
"DIALOG": {
"TITLE": "Nueva comprobación",
"CANCEL-BUTTON": "Cancelar",
"ADD-BUTTON": "Añadir lista de comprobación",
"PLACEHOLDER": "Nombre"
}
},
"ERROR": {
"TITLE": "No se ha podido finalizar la acción",
"DESCRIPTION": "Vuelva a intentarlo o compruebe que tiene acceso.",
"CLOSE": "Cerrar"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "No se ha seleccionado ningún filtro de tareas"
}
},
"START_TASK": {
"DEFAULT_NAME": "Mi tarea predeterminada",
"BUTTON": "Crear tarea",
"FORM": {
"TITLE": "Iniciar tarea",
"LABEL": {
"NONE": "Ninguna",
"NAME": "Nombre",
"DESCRIPTION": "Descripción",
"ATTACHFORM": "Adjuntar formulario",
"ASSIGNEE": "Asignado a",
"FORM": "Formulario",
"DATE": "Elegir fecha"
},
"ACTION": {
"START": "Comenzar",
"CANCEL": "Cancelar"
},
"ERROR": {
"REQUIRED": "Campo obligatorio",
"DATE": "Formato de fecha DD/MM/AAAA",
"MAXIMUM_LENGTH": "Longitud excedida, {{characters}} caracteres como máx.",
"MESSAGE": "Introducir un valor diferente"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Asignado a",
"DIALOG_CLOSE": "Cerrar",
"ADD_USER": "Añadir",
"ADD_ASSIGNEE": "Asignar",
"SEARCH_USER": "Buscar usuario",
"SEARCH": {
"NO_USERS": "No se ha encontrado a nadie para participar"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Esta lista está vacía",
"DRAG-AND-DROP": {
"TITLE": "Arrastrar y soltar",
"SUBTITLE": "para cargar ficheros"
}
},
"EMPTY-LIST": {
"HEADER": "No hay ficheros disponibles"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "No se han adjuntado formularios",
"COMPLETE_TASK_MESSAGE": "Tarea {{taskName}} finalizada",
"COMPLETE_TASK_SUB_MESSAGE": "No se han añadido formularios"
},
"ATTACH_FORM": {
"SELECT_FORM": "Seleccionar formulario para adjuntar",
"REMOVE_FORM": "Eliminar formulario",
"SELECT_OPTION": "Seleccionar una opción"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "No se han encontrado procesos",
"SUBTITLE": "Cree un nuevo proceso que desee encontrar fácilmente después",
"SUMMARY": "Se han encontrado {{total}} instancias de procesos",
"ERROR": "No se han podido cargar las instancias de procesos. Vuelva a intentarlo o comparta el mensaje siguiente con el equipo de TI: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "No se ha seleccionado ningún filtro de instancias."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Proceso",
"NAME": "Nombre",
"THUMBNAIL": "Miniatura",
"STATUS": "Estado",
"END_DATE": "Fecha de fin",
"END_DATE_DEFAULT": "Sin fecha",
"CATEGORY": "Categoría",
"CATEGORY_DEFAULT": "Sin categoría",
"CREATED_BY": "Creado por",
"CREATED_BY_DEFAULT": "Sin asignado",
"CREATED": "Creado",
"BUSINESS_KEY": "Clave de negocio",
"BUSINESS_KEY_DEFAULT": "Ninguna",
"DESCRIPTION": "Descripción",
"DESCRIPTION_DEFAULT": "Sin descripción",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Ver",
"REMOVE_CONTENT": "Eliminar",
"DOWNLOAD_CONTENT": "Descargar",
"DOWNLOAD_AUDIT": "Descargar auditoría",
"VIEW_TASK": "Ver tarea"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Iniciado por",
"STARTED": "Iniciado",
"ENDED": "Finalizado",
"COMMENTS": "Comentarios",
"START_FORM": "Iniciar formulario",
"TASKS_ACTIVE": "Tareas activas",
"TASKS_COMPLETED": "Tareas completadas",
"TASK_SUBTITLE": "Asignado a {{user}}, creado {{created}}"
},
"BUTTON": {
"CANCEL": "Cancelar proceso",
"CLOSE": "Cerrar",
"SHOW_DIAGRAM": "Mostrar diagrama",
"DRAG-ATTACHMENT": "Arrastrar los ficheros a cargar",
"UPLOAD-ATTACHMENT": "Cargar adjunto"
},
"MESSAGES": {
"NONE": "No se han encontrado detalles del proceso"
},
"TASKS": {
"NO_ACTIVE": "No hay tareas activas en estos momentos",
"NO_COMPLETED": "No hay tareas finalizadas todavía",
"TASK_DETAILS": "Detalles de la tarea",
"TASK_CLOSE": "Cerrar"
},
"COMMENTS": {
"ADD": "Añadir comentario",
"HEADER": "Comentarios ({{ count }})",
"NONE": "No hay comentarios",
"BUTTON": {
"ADD": "Añadir comentario"
},
"ADD_DIALOG": {
"TITLE": "Nuevo comentario",
"LABEL": {
"MESSAGE": "Mensaje"
},
"BUTTON": {
"ADD": "Añadir comentario",
"CANCEL": "Cancelar"
}
}
},
"ADD_DIALOG": {
"TITLE": "Establecer variable del proceso",
"LABEL": {
"NAME": "Nombre",
"VALUE": "Valor",
"SCOPE": "Ámbito"
}
},
"EDIT_DIALOG": {
"TITLE": "Editar variable del proceso"
},
"ERROR_DIALOG": {
"TITLE": "No se ha podido finalizar la acción",
"DESCRIPTION": "Puede que no tenga el nivel de acceso requerido; consúltelo con el equipo de TI."
}
},
"START_PROCESS": {
"BUTTON": "Iniciar proceso",
"NO_PROCESS_DEFINITIONS": "No puede iniciar un proceso porque no hay definiciones de procesos disponibles",
"FORM": {
"TITLE": "Iniciar proceso",
"LABEL": {
"TYPE": "Seleccionar proceso",
"NAME": "Nombre del proceso"
},
"TYPE_PLACEHOLDER": "Elegir una...",
"ACTION": {
"START": "Iniciar proceso",
"CANCEL": "Cancelar"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "No se han podido cargar las definiciones de procesos; compruebe que tiene acceso.",
"START": "No se ha podido iniciar una nueva instancia de proceso; compruebe que tiene acceso.",
"MAXIMUM_LENGTH": "Longitud excedida, {{characters}} caracteres como máx."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Esta lista está vacía",
"DRAG-AND-DROP": {
"TITLE": "Arrastrar y soltar",
"SUBTITLE": "para cargar ficheros"
}
},
"EMPTY-LIST": {
"HEADER": "No hay ficheros disponibles"
},
"COLUMNS": {
"NAME": "Nombre",
"CREATED-ON": "Creado"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Crear",
"NEW_TASK": "Nueva tarea",
"NEW_PROCESS": "Nuevo proceso"
}
},
"APP": {
"DIALOG": {
"START": "Continuar",
"TITLE": "Seleccionar una aplicación",
"LIST": "Lista de aplicaciones",
"ERROR": "Hay un problema con la conexión a Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Iniciar sesión",
"CANCEL": "Cancelar",
"CHOOSE": "Elegir"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Jos haluat tallentaa raportin nykyisillä asetuksilla raporttiluetteloosi, napsauta Tallenna.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Alkamispäivä",
"END-DATE": "Päättymispäivä",
"MESSAGES": {
"START-DATE-REQUIRED": "Alkamispäivä on pakollinen",
"START-LESS-THAN-END-DATE": "Alkamispäivän täytyy olla ennen päättymispäivää"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Yhtään sovellusta ei löydy",
"SUBTITLE": "Luo uusi sovellus, jonka löydät helposti myöhemmin",
"TASK_APP_NAME": "Tehtäväsovellus"
},
"LIST": {
"MESSAGES": {
"TITLE": "Yhtään tehtävää ei löydy",
"SUBTITLE": "Luo uusi tehtävä, jonka löydät helposti myöhemmin",
"NONE": "Yhtään tehtäväluetteloa ei löydy"
}
},
"PROPERTIES": {
"TASK_NAME": "Tehtävä",
"THUMBNAIL": "Pikkukuva",
"DURATION": "Kesto",
"PARENT_TASK_ID": "Ylätason tehtävän tunnus",
"NAME": "Nimi",
"ASSIGNEE": "Vastuuhenkilö",
"ASSIGNEE_DEFAULT": "Ei vastuuhenkilöä",
"PRIORITY": "Prioriteetti",
"DUE_DATE": "Määräpäivä",
"DUE_DATE_DEFAULT": "Ei päivämäärää",
"STATUS": "Tila",
"CATEGORY": "Luokka",
"CATEGORY_DEFAULT": "Ei luokkaa",
"PARENT_NAME": "Ylätason nimi",
"PARENT_NAME_DEFAULT": "Ei ylätasoa",
"CREATED_BY": "Tekijä:",
"CREATED": "Luotu",
"END_DATE": "Päättymispäivä",
"ID": "Tunnus",
"DESCRIPTION": "Kuvaus",
"DESCRIPTION_DEFAULT": "Ei kuvausta",
"FORM_NAME": "Lomakkeen nimi",
"FORM_NAME_DEFAULT": "Ei lomaketta"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Näytä",
"REMOVE_CONTENT": "Poista",
"DOWNLOAD_CONTENT": "Lataa",
"DOWNLOAD_AUDIT": "Lataa tarkastus"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Toiminnot",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Toiminto",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Tiedot",
"ASSIGNEE": "Vastuuhenkilö",
"DUE": "Määräpäivä",
"FORM": "Lomake",
"PEOPLE": "Käyttäjät, joille tämä tehtävä on jaettu",
"COMMENTS": "Kommentit",
"CHECKLIST": "Tarkistuslista",
"INVOLVED_PEOPLE": "Mukana olevat käyttäjät",
"ADD_PEOPLE": "Lisää ihmisiä ja ryhmiä",
"ADD_ASSIGNEE": "Lisää uusi vastuuhenkilö"
},
"BUTTON": {
"COMPLETE": "Merkitse valmiiksi",
"CLAIM": "Varaa",
"UNCLAIM": "Vapauta",
"DRAG-ATTACHMENT": "Lataa tiedostoja pudottamalla niitä",
"UPLOAD-ATTACHMENT": "Lataa liite"
},
"MESSAGES": {
"NONE": "Tehtävätietoja ei löydy",
"CLAIM": "Jos haluat työstää tätä tehtävää, napsauta Varaa"
},
"FORM": {
"NONE": "Ei lomaketta"
},
"DUE": {
"NONE": "Ei määräpäivää"
},
"ASSIGNEE": {
"NONE": "Ei vastuuhenkilöä"
},
"PEOPLE": {
"NONE": "Ei ketään mukana"
},
"CHECKLIST": {
"NONE": "Ei tarkistuslistaa",
"DIALOG": {
"TITLE": "Uusi tarkistus",
"CANCEL-BUTTON": "Peruuta",
"ADD-BUTTON": "Lisää tarkistuslista",
"PLACEHOLDER": "Nimi"
}
},
"ERROR": {
"TITLE": "Toiminnon suorittaminen ei onnistu",
"DESCRIPTION": "Yritä uudelleen tai tarkista, että sinulla on tarvittavat oikeudet.",
"CLOSE": "Sulje"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Ei valittua tehtäväsuodatinta"
}
},
"START_TASK": {
"DEFAULT_NAME": "Oma oletustehtävä",
"BUTTON": "Luo tehtävä",
"FORM": {
"TITLE": "Aloita tehtävä",
"LABEL": {
"NONE": "Ei mitään",
"NAME": "Nimi",
"DESCRIPTION": "Kuvaus",
"ATTACHFORM": "Liitä lomake",
"ASSIGNEE": "Vastuuhenkilö",
"FORM": "Lomake",
"DATE": "Valitse päivämäärä"
},
"ACTION": {
"START": "Aloita",
"CANCEL": "Peruuta"
},
"ERROR": {
"REQUIRED": "Pakollinen kenttä",
"DATE": "Päivämäärämuoto: PP/KK/VVVV",
"MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä.",
"MESSAGE": "Anna toinen arvo"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Vastuuhenkilö",
"DIALOG_CLOSE": "Sulje",
"ADD_USER": "Lisää",
"ADD_ASSIGNEE": "Määritä",
"SEARCH_USER": "Hae käyttäjää",
"SEARCH": {
"NO_USERS": "Ei löydy ketään mukaan lisättäväksi"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Tämä luettelo on tyhjä",
"DRAG-AND-DROP": {
"TITLE": "Lataa tiedostoja",
"SUBTITLE": "vetämällä ja pudottamalla"
}
},
"EMPTY-LIST": {
"HEADER": "Yhtään tiedostoa ei ole saatavilla"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Ei liitettyjä lomakkeita",
"COMPLETE_TASK_MESSAGE": "Tehtävä {{taskName}} suoritettu",
"COMPLETE_TASK_SUB_MESSAGE": "Ei lisättäviä lomakkeita"
},
"ATTACH_FORM": {
"SELECT_FORM": "Valitse liitettävä lomake",
"REMOVE_FORM": "Poista lomake",
"SELECT_OPTION": "Valitse asetus"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Yhtään prosessia ei löydy",
"SUBTITLE": "Luo uusi prosessi, jonka löydät helposti myöhemmin",
"SUMMARY": "Löytyi {{total}} prosessiesiintymää",
"ERROR": "Prosessiesiintymien lataaminen ei onnistu. Yritä uudelleen tai ilmoita seuraava virheilmoitus IT-tuelle: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Prosessiesiintymäsuodatinta ei ole valittu."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Prosessi",
"NAME": "Nimi",
"THUMBNAIL": "Pikkukuva",
"STATUS": "Tila",
"END_DATE": "Päättymispäivä",
"END_DATE_DEFAULT": "Ei päivämäärää",
"CATEGORY": "Luokka",
"CATEGORY_DEFAULT": "Ei luokkaa",
"CREATED_BY": "Tekijä:",
"CREATED_BY_DEFAULT": "Ei vastuuhenkilöä",
"CREATED": "Luotu",
"BUSINESS_KEY": "Liiketoiminta-avain",
"BUSINESS_KEY_DEFAULT": "Ei mitään",
"DESCRIPTION": "Kuvaus",
"DESCRIPTION_DEFAULT": "Ei kuvausta",
"ID": "Tunnus"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Näytä",
"REMOVE_CONTENT": "Poista",
"DOWNLOAD_CONTENT": "Lataa",
"DOWNLOAD_AUDIT": "Lataa tarkastus",
"VIEW_TASK": "Näytä tehtävä"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Aloittaja:",
"STARTED": "Aloitettu",
"ENDED": "Lopetettu",
"COMMENTS": "Kommentit",
"START_FORM": "Aloita lomake",
"TASKS_ACTIVE": "Aktiiviset tehtävät",
"TASKS_COMPLETED": "Suoritetut tehtävät",
"TASK_SUBTITLE": "Määritetty käyttäjälle {{user}}, luotu {{created}}"
},
"BUTTON": {
"CANCEL": "Peruuta prosessi",
"CLOSE": "Sulje",
"SHOW_DIAGRAM": "Näytä kaavio",
"DRAG-ATTACHMENT": "Lataa tiedostoja pudottamalla niitä",
"UPLOAD-ATTACHMENT": "Lataa liite"
},
"MESSAGES": {
"NONE": "Prosessitietoja ei löydy"
},
"TASKS": {
"NO_ACTIVE": "Ei tällä hetkellä aktiivisia tehtäviä",
"NO_COMPLETED": "Ei vielä yhtään suoritettua tehtävää",
"TASK_DETAILS": "Tehtävätiedot",
"TASK_CLOSE": "Sulje"
},
"COMMENTS": {
"ADD": "Lisää kommentti",
"HEADER": "Kommentit ({{ count }})",
"NONE": "Ei kommentteja",
"BUTTON": {
"ADD": "Lisää kommentti"
},
"ADD_DIALOG": {
"TITLE": "Uusi kommentti",
"LABEL": {
"MESSAGE": "Viesti"
},
"BUTTON": {
"ADD": "Lisää kommentti",
"CANCEL": "Peruuta"
}
}
},
"ADD_DIALOG": {
"TITLE": "Määritä prosessimuuttuja",
"LABEL": {
"NAME": "Nimi",
"VALUE": "Arvo",
"SCOPE": "Laajuus"
}
},
"EDIT_DIALOG": {
"TITLE": "Muokkaa prosessimuuttujaa"
},
"ERROR_DIALOG": {
"TITLE": "Toiminnon suorittaminen ei onnistu",
"DESCRIPTION": "Sinulla ei ehkä ole riittäviä oikeuksia. Tarkista asia IT-tuesta."
}
},
"START_PROCESS": {
"BUTTON": "Käynnistä prosessi",
"NO_PROCESS_DEFINITIONS": "Et voi käynnistää prosessia, koska prosessimääritelmiä ei ole saatavilla",
"FORM": {
"TITLE": "Käynnistä prosessi",
"LABEL": {
"TYPE": "Valitse prosessi",
"NAME": "Prosessin nimi"
},
"TYPE_PLACEHOLDER": "Valitse yksi...",
"ACTION": {
"START": "Käynnistä prosessi",
"CANCEL": "Peruuta"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Prosessimääritelmien lataaminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.",
"START": "Uuden prosessiesiintymän käynnistäminen ei onnistu. Tarkista, että sinulla on tarvittavat oikeudet.",
"MAXIMUM_LENGTH": "Liian pitkä: voit käyttää enintään {{characters}} merkkiä."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Tämä luettelo on tyhjä",
"DRAG-AND-DROP": {
"TITLE": "Lataa tiedostoja",
"SUBTITLE": "vetämällä ja pudottamalla"
}
},
"EMPTY-LIST": {
"HEADER": "Yhtään tiedostoa ei ole saatavilla"
},
"COLUMNS": {
"NAME": "Nimi",
"CREATED-ON": "Luotu"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Luo",
"NEW_TASK": "Uusi tehtävä",
"NEW_PROCESS": "Uusi prosessi"
}
},
"APP": {
"DIALOG": {
"START": "Jatka",
"TITLE": "Valitse prosessisovellus",
"LIST": "Prosessisovellusluettelo",
"ERROR": "Process Services -yhteyden muodostamisessa on ongelma"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Kirjaudu sisään",
"CANCEL": "Peruuta",
"CHOOSE": "Valitse"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Cliquez sur Enregistrer pour ajouter un rapport avec les paramètres actuels à la liste des rapports.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Date de début",
"END-DATE": "Date de fin",
"MESSAGES": {
"START-DATE-REQUIRED": "La date de début est obligatoire",
"START-LESS-THAN-END-DATE": "La date de début doit être antérieure à la date de fin"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Aucune application trouvée",
"SUBTITLE": "Créer une nouvelle application à laquelle vous pourrez accéder facilement par la suite",
"TASK_APP_NAME": "Application Tâches"
},
"LIST": {
"MESSAGES": {
"TITLE": "Aucune tâche trouvée",
"SUBTITLE": "Créer une nouvelle tâche facilement accessible ultérieurement",
"NONE": "Aucune liste de tâches trouvée"
}
},
"PROPERTIES": {
"TASK_NAME": "Tâche",
"THUMBNAIL": "Miniature",
"DURATION": "Durée",
"PARENT_TASK_ID": "ID de la tâche parent",
"NAME": "Nom",
"ASSIGNEE": "Personne assignée",
"ASSIGNEE_DEFAULT": "Aucune personne assignée",
"PRIORITY": "Priorité",
"DUE_DATE": "Date d'échéance",
"DUE_DATE_DEFAULT": "Aucune date",
"STATUS": "Statut",
"CATEGORY": "Catégorie",
"CATEGORY_DEFAULT": "Aucune catégorie",
"PARENT_NAME": "Nom du parent",
"PARENT_NAME_DEFAULT": "Aucun parent",
"CREATED_BY": "Créé par",
"CREATED": "Créé",
"END_DATE": "Date de fin",
"ID": "ID",
"DESCRIPTION": "Description",
"DESCRIPTION_DEFAULT": "Aucune description",
"FORM_NAME": "Nom du formulaire",
"FORM_NAME_DEFAULT": "Aucun formulaire"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Afficher",
"REMOVE_CONTENT": "Supprimer",
"DOWNLOAD_CONTENT": "Télécharger",
"DOWNLOAD_AUDIT": "Télécharger l'audit"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Activités",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Activité",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Détails",
"ASSIGNEE": "Personne assignée",
"DUE": "Echéance",
"FORM": "Formulaire",
"PEOPLE": "Personnes avec lesquelles cette tâche est partagée",
"COMMENTS": "Commentaires",
"CHECKLIST": "Liste de contrôle",
"INVOLVED_PEOPLE": "Personnes impliquées",
"ADD_PEOPLE": "Ajouter des personnes et des groupes",
"ADD_ASSIGNEE": "Ajouter une nouvelle personne assignée"
},
"BUTTON": {
"COMPLETE": "Terminer",
"CLAIM": "S'attribuer",
"UNCLAIM": "Libérer",
"DRAG-ATTACHMENT": "Déposez des fichiers pour les importer",
"UPLOAD-ATTACHMENT": "Importer la pièce jointe"
},
"MESSAGES": {
"NONE": "Aucun détail de tâche trouvé",
"CLAIM": "Cliquez sur S'attribuer pour travailler sur cette tâche"
},
"FORM": {
"NONE": "Aucun formulaire"
},
"DUE": {
"NONE": "Pas de date prévue"
},
"ASSIGNEE": {
"NONE": "Aucune personne assignée"
},
"PEOPLE": {
"NONE": "Aucune personne impliquée"
},
"CHECKLIST": {
"NONE": "Aucune liste de contrôle",
"DIALOG": {
"TITLE": "Nouvelle tâche cochée",
"CANCEL-BUTTON": "Annuler",
"ADD-BUTTON": "Ajouter une liste de contrôle",
"PLACEHOLDER": "Nom"
}
},
"ERROR": {
"TITLE": "Impossible de terminer l'action",
"DESCRIPTION": "Réessayez ou vérifiez que vous avez les droits d'accès.",
"CLOSE": "Fermer"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Aucun filtre de tâches sélectionné"
}
},
"START_TASK": {
"DEFAULT_NAME": "Ma tâche par défaut",
"BUTTON": "Créer une tâche",
"FORM": {
"TITLE": "Démarrer la tâche",
"LABEL": {
"NONE": "Aucune",
"NAME": "Nom",
"DESCRIPTION": "Description",
"ATTACHFORM": "Joindre un formulaire",
"ASSIGNEE": "Personne assignée",
"FORM": "Formulaire",
"DATE": "Choisir la date"
},
"ACTION": {
"START": "Démarrer",
"CANCEL": "Annuler"
},
"ERROR": {
"REQUIRED": "Champ obligatoire",
"DATE": "Format de date JJ/MM/AAAA",
"MAXIMUM_LENGTH": "Longueur dépassée, {{characters}} caractères max.",
"MESSAGE": "Saisir une valeur différente"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Personne assignée",
"DIALOG_CLOSE": "Fermer",
"ADD_USER": "Ajouter",
"ADD_ASSIGNEE": "Assigner",
"SEARCH_USER": "Rechercher des utilisateurs",
"SEARCH": {
"NO_USERS": "Aucune personne à impliquer trouvée"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Cette liste est vide",
"DRAG-AND-DROP": {
"TITLE": "Glissez-déposez",
"SUBTITLE": "les fichiers à importer"
}
},
"EMPTY-LIST": {
"HEADER": "Aucun fichier disponible"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Aucun formulaire joint",
"COMPLETE_TASK_MESSAGE": "La tâche {{taskName}} est terminée",
"COMPLETE_TASK_SUB_MESSAGE": "Aucun formulaire à ajouter"
},
"ATTACH_FORM": {
"SELECT_FORM": "Sélectionner le formulaire à joindre",
"REMOVE_FORM": "Supprimer le formulaire",
"SELECT_OPTION": "Sélectionner une option"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Aucun processus trouvé",
"SUBTITLE": "Créer un nouveau processus auquel vous pourrez accéder facilement par la suite",
"SUMMARY": "{{total}} instances de processus trouvées",
"ERROR": "Impossible de charger les instances de processus. Réessayez ou transférez le message suivant au service informatique : {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Aucun filtre d'instances de processus sélectionné."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Processus",
"NAME": "Nom",
"THUMBNAIL": "Miniature",
"STATUS": "Statut",
"END_DATE": "Date de fin",
"END_DATE_DEFAULT": "Aucune date",
"CATEGORY": "Catégorie",
"CATEGORY_DEFAULT": "Aucune catégorie",
"CREATED_BY": "Créé par",
"CREATED_BY_DEFAULT": "Aucune personne assignée",
"CREATED": "Créé",
"BUSINESS_KEY": "Clé de processus métier",
"BUSINESS_KEY_DEFAULT": "Aucune",
"DESCRIPTION": "Description",
"DESCRIPTION_DEFAULT": "Aucune description",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Afficher",
"REMOVE_CONTENT": "Supprimer",
"DOWNLOAD_CONTENT": "Télécharger",
"DOWNLOAD_AUDIT": "Télécharger l'audit",
"VIEW_TASK": "Afficher la tâche"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Démarré par",
"STARTED": "Démarré",
"ENDED": "Terminé",
"COMMENTS": "Commentaires",
"START_FORM": "Démarrer le formulaire",
"TASKS_ACTIVE": "Tâches actives",
"TASKS_COMPLETED": "Tâches terminées",
"TASK_SUBTITLE": "Assigné à {{user}}, créé le {{created}}"
},
"BUTTON": {
"CANCEL": "Annuler le processus",
"CLOSE": "Fermer",
"SHOW_DIAGRAM": "Afficher le diagramme",
"DRAG-ATTACHMENT": "Déposez des fichiers pour les importer",
"UPLOAD-ATTACHMENT": "Importer la pièce jointe"
},
"MESSAGES": {
"NONE": "Aucun détail de processus trouvé"
},
"TASKS": {
"NO_ACTIVE": "Aucune tâche actuellement active",
"NO_COMPLETED": "Aucune tâche terminée pour l'instant",
"TASK_DETAILS": "Détails de la tâche",
"TASK_CLOSE": "Fermer"
},
"COMMENTS": {
"ADD": "Ajouter un commentaire",
"HEADER": "Commentaires ({{ count }})",
"NONE": "Pas de commentaire",
"BUTTON": {
"ADD": "Ajouter un commentaire"
},
"ADD_DIALOG": {
"TITLE": "Nouveau commentaire",
"LABEL": {
"MESSAGE": "Message"
},
"BUTTON": {
"ADD": "Ajouter un commentaire",
"CANCEL": "Annuler"
}
}
},
"ADD_DIALOG": {
"TITLE": "Définir une variable de processus",
"LABEL": {
"NAME": "Nom",
"VALUE": "Valeur",
"SCOPE": "Etendue"
}
},
"EDIT_DIALOG": {
"TITLE": "Modifier la variable de processus"
},
"ERROR_DIALOG": {
"TITLE": "Impossible de terminer l'action",
"DESCRIPTION": "Vous n'avez peut-être pas le niveau d'accès requis ; vérifiez auprès du service informatique."
}
},
"START_PROCESS": {
"BUTTON": "Démarrer le processus",
"NO_PROCESS_DEFINITIONS": "Impossible de démarrer un processus car aucune définition de processus n'est disponible",
"FORM": {
"TITLE": "Démarrer le processus",
"LABEL": {
"TYPE": "Sélectionner un processus",
"NAME": "Nom de processus"
},
"TYPE_PLACEHOLDER": "Choisissez une valeur...",
"ACTION": {
"START": "Démarrer le processus",
"CANCEL": "Annuler"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Impossible de charger les définitions de processus ; vérifiez que vous avez les droits d'accès.",
"START": "Impossible de démarrer la nouvelle instance de processus ; vérifiez que vous avez les droits d'accès.",
"MAXIMUM_LENGTH": "Longueur dépassée, {{characters}} caractères max."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Cette liste est vide",
"DRAG-AND-DROP": {
"TITLE": "Glissez-déposez",
"SUBTITLE": "les fichiers à importer"
}
},
"EMPTY-LIST": {
"HEADER": "Aucun fichier disponible"
},
"COLUMNS": {
"NAME": "Nom",
"CREATED-ON": "Créé le"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Créer",
"NEW_TASK": "Nouvelle tâche",
"NEW_PROCESS": "Nouveau processus"
}
},
"APP": {
"DIALOG": {
"START": "Continuer",
"TITLE": "Sélectionner une application",
"LIST": "Liste d'application",
"ERROR": "Nous rencontrons un problème de connexion à Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Connexion",
"CANCEL": "Annuler",
"CHOOSE": "Choisir"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Fai clic su Salva per aggiungere un rapporto con le impostazioni correnti all'elenco dei rapporti.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Data di inizio",
"END-DATE": "Data di fine",
"MESSAGES": {
"START-DATE-REQUIRED": "Data di inizio richiesta",
"START-LESS-THAN-END-DATE": "La data di inizio deve essere precedente alla data di fine"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Nessuna applicazione trovata",
"SUBTITLE": "Creare una nuova applicazione per trovarla facilmente più tardi",
"TASK_APP_NAME": "Applicazione compiti"
},
"LIST": {
"MESSAGES": {
"TITLE": "Nessuna attività trovata",
"SUBTITLE": "Crea una nuova attività da trovare facilmente più tardi",
"NONE": "Nessun elenco compiti trovato"
}
},
"PROPERTIES": {
"TASK_NAME": "Compito",
"THUMBNAIL": "Miniatura",
"DURATION": "Durata",
"PARENT_TASK_ID": "ID compito principale",
"NAME": "Nome",
"ASSIGNEE": "Assegnatario",
"ASSIGNEE_DEFAULT": "Nessun assegnatario",
"PRIORITY": "Priorità",
"DUE_DATE": "Scadenza",
"DUE_DATE_DEFAULT": "Nessuna data",
"STATUS": "Stato",
"CATEGORY": "Categoria",
"CATEGORY_DEFAULT": "Nessuna categoria",
"PARENT_NAME": "Nome genitore",
"PARENT_NAME_DEFAULT": "Nessun genitore",
"CREATED_BY": "Creato da",
"CREATED": "Creato",
"END_DATE": "Data di fine",
"ID": "ID",
"DESCRIPTION": "Descrizione",
"DESCRIPTION_DEFAULT": "Nessuna descrizione",
"FORM_NAME": "Nome modulo",
"FORM_NAME_DEFAULT": "Nessun modulo"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visualizza",
"REMOVE_CONTENT": "Rimuovi",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Scarica audit"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Attività",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Attività",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Dettagli",
"ASSIGNEE": "Assegnatario",
"DUE": "In scadenza",
"FORM": "Modulo",
"PEOPLE": "Persone con cui è condiviso questo compito",
"COMMENTS": "Commenti",
"CHECKLIST": "Elenco di controllo",
"INVOLVED_PEOPLE": "Persone coinvolte",
"ADD_PEOPLE": "Aggiungi persone e gruppi",
"ADD_ASSIGNEE": "Aggiungi nuovo assegnatario"
},
"BUTTON": {
"COMPLETE": "Completa",
"CLAIM": "Richiedi",
"UNCLAIM": "Restituisci",
"DRAG-ATTACHMENT": "Rilascia file da caricare",
"UPLOAD-ATTACHMENT": "Carica allegato"
},
"MESSAGES": {
"NONE": "Nessun dettaglio compito trovato",
"CLAIM": "Fare clic su Richiedi per lavorare su questo compito"
},
"FORM": {
"NONE": "Nessun modulo"
},
"DUE": {
"NONE": "Nessuna scadenza"
},
"ASSIGNEE": {
"NONE": "Nessun assegnatario"
},
"PEOPLE": {
"NONE": "Nessuno coinvolto"
},
"CHECKLIST": {
"NONE": "Nessun elenco di controllo",
"DIALOG": {
"TITLE": "Nuova verifica",
"CANCEL-BUTTON": "Annulla",
"ADD-BUTTON": "Aggiungi elenco di controllo",
"PLACEHOLDER": "Nome"
}
},
"ERROR": {
"TITLE": "Impossibile completare l'azione",
"DESCRIPTION": "Riprova o verifica di disporre dell'accesso.",
"CLOSE": "Chiudi"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nessun filtro compito selezionato"
}
},
"START_TASK": {
"DEFAULT_NAME": "Compito predefinito",
"BUTTON": "Crea compito",
"FORM": {
"TITLE": "Avvia compito",
"LABEL": {
"NONE": "Nessuno",
"NAME": "Nome",
"DESCRIPTION": "Descrizione",
"ATTACHFORM": "Allega modulo",
"ASSIGNEE": "Assegnatario",
"FORM": "Modulo",
"DATE": "Seleziona data"
},
"ACTION": {
"START": "Avvia",
"CANCEL": "Annulla"
},
"ERROR": {
"REQUIRED": "Campo obbligatorio",
"DATE": "Formato data GG/MM/AAAA",
"MAXIMUM_LENGTH": "Lunghezza superata, massimo {{characters}} caratteri.",
"MESSAGE": "Immettere un altro valore"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Assegnatario",
"DIALOG_CLOSE": "Chiudi",
"ADD_USER": "Aggiungi",
"ADD_ASSIGNEE": "Assegna",
"SEARCH_USER": "Cerca utente",
"SEARCH": {
"NO_USERS": "Nessuno trovato da coinvolgere"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Questo elenco è vuoto",
"DRAG-AND-DROP": {
"TITLE": "Trascinare e rilasciare",
"SUBTITLE": "per caricare i file"
}
},
"EMPTY-LIST": {
"HEADER": "Nessun file disponibile"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Nessun modulo allegato",
"COMPLETE_TASK_MESSAGE": "Compito {{taskName}} completato",
"COMPLETE_TASK_SUB_MESSAGE": "Nessun modulo da aggiungere"
},
"ATTACH_FORM": {
"SELECT_FORM": "Seleziona modulo da allegare",
"REMOVE_FORM": "Rimuovi modulo",
"SELECT_OPTION": "Seleziona un'opzione"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Nessun processo trovato",
"SUBTITLE": "Creare un nuovo processo per trovarlo facilmente più tardi",
"SUMMARY": "{{total}} istanze di processo trovate",
"ERROR": "Impossibile caricare le istanze di processo. Riprovare o condividere il messaggio seguente con il proprio team IT: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nessun filtro di istanze di processo selezionato."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Processo",
"NAME": "Nome",
"THUMBNAIL": "Miniatura",
"STATUS": "Stato",
"END_DATE": "Data di fine",
"END_DATE_DEFAULT": "Nessuna data",
"CATEGORY": "Categoria",
"CATEGORY_DEFAULT": "Nessuna categoria",
"CREATED_BY": "Creato da",
"CREATED_BY_DEFAULT": "Nessun assegnatario",
"CREATED": "Creato",
"BUSINESS_KEY": "Chiave di business",
"BUSINESS_KEY_DEFAULT": "Nessuno",
"DESCRIPTION": "Descrizione",
"DESCRIPTION_DEFAULT": "Nessuna descrizione",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visualizza",
"REMOVE_CONTENT": "Rimuovi",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Scarica audit",
"VIEW_TASK": "Visualizza compito"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Avviato da",
"STARTED": "Avviato",
"ENDED": "Terminato",
"COMMENTS": "Commenti",
"START_FORM": "Modulo di inizio",
"TASKS_ACTIVE": "Compiti attivi",
"TASKS_COMPLETED": "Compiti completati",
"TASK_SUBTITLE": "Assegnato a {{user}}, creazione {{created}}"
},
"BUTTON": {
"CANCEL": "Annulla processo",
"CLOSE": "Chiudi",
"SHOW_DIAGRAM": "Visualizza diagramma",
"DRAG-ATTACHMENT": "Rilascia file da caricare",
"UPLOAD-ATTACHMENT": "Carica allegato"
},
"MESSAGES": {
"NONE": "Nessun dettaglio di processo trovato"
},
"TASKS": {
"NO_ACTIVE": "Nessun compito attualmente attivo",
"NO_COMPLETED": "Nessun compito già completato",
"TASK_DETAILS": "Dettagli compito",
"TASK_CLOSE": "Chiudi"
},
"COMMENTS": {
"ADD": "Aggiungi commento",
"HEADER": "Commenti ({{ count }})",
"NONE": "Nessun commento",
"BUTTON": {
"ADD": "Aggiungi commento"
},
"ADD_DIALOG": {
"TITLE": "Nuovo commento",
"LABEL": {
"MESSAGE": "Messaggio"
},
"BUTTON": {
"ADD": "Aggiungi commento",
"CANCEL": "Annulla"
}
}
},
"ADD_DIALOG": {
"TITLE": "Imposta variabile di processo",
"LABEL": {
"NAME": "Nome",
"VALUE": "Valore",
"SCOPE": "Ambito"
}
},
"EDIT_DIALOG": {
"TITLE": "Modifica variabile di processo"
},
"ERROR_DIALOG": {
"TITLE": "Impossibile completare l'azione",
"DESCRIPTION": "Si potrebbe non disporre del livello di accesso necessario, rivolgersi al team IT."
}
},
"START_PROCESS": {
"BUTTON": "Avvia processo",
"NO_PROCESS_DEFINITIONS": "Impossibile avviare un processo poiché non vi sono definizioni di processo disponibili",
"FORM": {
"TITLE": "Avvia processo",
"LABEL": {
"TYPE": "Seleziona processo",
"NAME": "Nome processo"
},
"TYPE_PLACEHOLDER": "Effettuare una scelta...",
"ACTION": {
"START": "Avvia processo",
"CANCEL": "Annulla"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Impossibile caricare le definizioni di processo, verifica di disporre dell'accesso.",
"START": "Impossibile avviare nuova istanza di processo, verifica di disporre dell'accesso.",
"MAXIMUM_LENGTH": "Lunghezza superata, massimo {{characters}} caratteri."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Questo elenco è vuoto",
"DRAG-AND-DROP": {
"TITLE": "Trascinare e rilasciare",
"SUBTITLE": "per caricare i file"
}
},
"EMPTY-LIST": {
"HEADER": "Nessun file disponibile"
},
"COLUMNS": {
"NAME": "Nome",
"CREATED-ON": "Creato il"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Crea",
"NEW_TASK": "Nuovo compito",
"NEW_PROCESS": "Nuovo processo"
}
},
"APP": {
"DIALOG": {
"START": "Continuare",
"TITLE": "Seleziona un'app",
"LIST": "Elenco di applicazioni",
"ERROR": "Si è verificato un problema di connessione a Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Login",
"CANCEL": "Annulla",
"CHOOSE": "Scegli"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "レポートを現在の設定でレポートリストに追加するには、[保存] をクリックします。",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "開始日",
"END-DATE": "終了日",
"MESSAGES": {
"START-DATE-REQUIRED": "開始日を指定してください",
"START-LESS-THAN-END-DATE": "開始日は終了日より前の日付でなければなりません"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "アプリケーションが見つかりません",
"SUBTITLE": "後で簡単に見つけられるよう、新しいアプリケーションを作成してください",
"TASK_APP_NAME": "タスクアプリ"
},
"LIST": {
"MESSAGES": {
"TITLE": "タスクが見つかりません",
"SUBTITLE": "後で簡単に見つけられるよう、新しいタスクを作成してください",
"NONE": "タスクリストが見つかりません"
}
},
"PROPERTIES": {
"TASK_NAME": "タスク",
"THUMBNAIL": "サムネイル",
"DURATION": "期間",
"PARENT_TASK_ID": "親タスク ID",
"NAME": "名前",
"ASSIGNEE": "担当者",
"ASSIGNEE_DEFAULT": "担当者なし",
"PRIORITY": "優先度",
"DUE_DATE": "期限",
"DUE_DATE_DEFAULT": "期限なし",
"STATUS": "ステータス",
"CATEGORY": "カテゴリ",
"CATEGORY_DEFAULT": "カテゴリなし",
"PARENT_NAME": "親名",
"PARENT_NAME_DEFAULT": "親なし",
"CREATED_BY": "作成者",
"CREATED": "作成日",
"END_DATE": "終了日",
"ID": "ID",
"DESCRIPTION": "説明",
"DESCRIPTION_DEFAULT": "説明なし",
"FORM_NAME": "フォームの名前",
"FORM_NAME_DEFAULT": "フォームなし"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "表示",
"REMOVE_CONTENT": "削除",
"DOWNLOAD_CONTENT": "ダウンロード",
"DOWNLOAD_AUDIT": "監査のダウンロード"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "アクティビティ",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "アクティビティ",
"INFO_DRAWER_TAB_DETAILS_TITLE": "詳細",
"ASSIGNEE": "担当者",
"DUE": "期限",
"FORM": "フォーム",
"PEOPLE": "このタスクを共有しているメンバー",
"COMMENTS": "コメント",
"CHECKLIST": "チェックリスト",
"INVOLVED_PEOPLE": "タスクに関わっているメンバー",
"ADD_PEOPLE": "メンバーとグループの追加",
"ADD_ASSIGNEE": "新しい担当者の追加"
},
"BUTTON": {
"COMPLETE": "完了",
"CLAIM": "担当する",
"UNCLAIM": "担当解除",
"DRAG-ATTACHMENT": "アップロードするファイルをここにドロップしてください",
"UPLOAD-ATTACHMENT": "添付ファイルのアップロード"
},
"MESSAGES": {
"NONE": "タスクの詳細が見つかりません",
"CLAIM": "このタスクの作業を行うには、[担当する] をクリックします"
},
"FORM": {
"NONE": "フォームなし"
},
"DUE": {
"NONE": "期限なし"
},
"ASSIGNEE": {
"NONE": "担当者なし"
},
"PEOPLE": {
"NONE": "関わっているメンバーなし"
},
"CHECKLIST": {
"NONE": "チェックリストなし",
"DIALOG": {
"TITLE": "タスクの選択",
"CANCEL-BUTTON": "キャンセル",
"ADD-BUTTON": "チェックリストの追加",
"PLACEHOLDER": "名前"
}
},
"ERROR": {
"TITLE": "処理を完了できませんでした",
"DESCRIPTION": "もう一度操作をやり直すか、アクセス権があることを確認してください。",
"CLOSE": "閉じる"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "タスクのフィルタが選択されていません"
}
},
"START_TASK": {
"DEFAULT_NAME": "あなたのデフォルトのタスク",
"BUTTON": "タスクの作成",
"FORM": {
"TITLE": "タスクの開始",
"LABEL": {
"NONE": "なし",
"NAME": "名前",
"DESCRIPTION": "説明",
"ATTACHFORM": "フォームの添付",
"ASSIGNEE": "担当者",
"FORM": "フォーム",
"DATE": "日付を選択してください"
},
"ACTION": {
"START": "開始",
"CANCEL": "キャンセル"
},
"ERROR": {
"REQUIRED": "必須フィールドです",
"DATE": "日付形式: YYYY-MM-DD",
"MAXIMUM_LENGTH": "長すぎます。{{characters}} 文字以内で入力してください。",
"MESSAGE": "別の値を入力してください"
}
}
},
"PEOPLE": {
"ASSIGNEE": "担当者",
"DIALOG_CLOSE": "閉じる",
"ADD_USER": "追加",
"ADD_ASSIGNEE": "割り当て",
"SEARCH_USER": "ユーザーの検索",
"SEARCH": {
"NO_USERS": "タスクに関わっているメンバーが見つかりません"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "このリストは空です",
"DRAG-AND-DROP": {
"TITLE": "アップロードするファイルをドラッグ & ドロップしてください",
"SUBTITLE": ""
}
},
"EMPTY-LIST": {
"HEADER": "使用できるファイルがありません"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "フォームが添付されていません",
"COMPLETE_TASK_MESSAGE": "タスク {{taskName}} が完了しました",
"COMPLETE_TASK_SUB_MESSAGE": "フォームは追加されません"
},
"ATTACH_FORM": {
"SELECT_FORM": "添付するフォームを選択してください",
"REMOVE_FORM": "フォームの削除",
"SELECT_OPTION": "オプションを選択してください"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "プロセスが見つかりません",
"SUBTITLE": "後で簡単に見つけられるよう、新しいプロセスを作成してください",
"SUMMARY": "{{total}} 個のプロセスインスタンスが見つかりました",
"ERROR": "プロセスインスタンスを読み込めませんでした。操作をやり直すか、次のメッセージを IT 担当者に伝えてください: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "プロセスインスタンスのフィルタが選択されていません。"
}
},
"PROPERTIES": {
"PROCESS_NAME": "プロセス",
"NAME": "名前",
"THUMBNAIL": "サムネイル",
"STATUS": "ステータス",
"END_DATE": "終了日",
"END_DATE_DEFAULT": "期限なし",
"CATEGORY": "カテゴリ",
"CATEGORY_DEFAULT": "カテゴリなし",
"CREATED_BY": "作成者",
"CREATED_BY_DEFAULT": "担当者なし",
"CREATED": "作成日",
"BUSINESS_KEY": "ビジネスキー",
"BUSINESS_KEY_DEFAULT": "なし",
"DESCRIPTION": "説明",
"DESCRIPTION_DEFAULT": "説明なし",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "表示",
"REMOVE_CONTENT": "削除",
"DOWNLOAD_CONTENT": "ダウンロード",
"DOWNLOAD_AUDIT": "監査のダウンロード",
"VIEW_TASK": "タスクの表示"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "開始者",
"STARTED": "開始日",
"ENDED": "終了日",
"COMMENTS": "コメント",
"START_FORM": "開始フォーム",
"TASKS_ACTIVE": "アクティブなタスク",
"TASKS_COMPLETED": "完了済みタスク",
"TASK_SUBTITLE": "割り当て先: {{user}}, 作成日: {{created}}"
},
"BUTTON": {
"CANCEL": "プロセスのキャンセル",
"CLOSE": "閉じる",
"SHOW_DIAGRAM": "図の表示",
"DRAG-ATTACHMENT": "アップロードするファイルをここにドロップしてください",
"UPLOAD-ATTACHMENT": "添付ファイルのアップロード"
},
"MESSAGES": {
"NONE": "プロセスの詳細が見つかりません"
},
"TASKS": {
"NO_ACTIVE": "現在アクティブなタスクはありません",
"NO_COMPLETED": "完了済みのタスクはまだありません",
"TASK_DETAILS": "タスクの詳細",
"TASK_CLOSE": "閉じる"
},
"COMMENTS": {
"ADD": "コメントの追加",
"HEADER": "コメント ({{ count }} 件)",
"NONE": "コメントなし",
"BUTTON": {
"ADD": "コメントの追加"
},
"ADD_DIALOG": {
"TITLE": "新しいコメント",
"LABEL": {
"MESSAGE": "メッセージ"
},
"BUTTON": {
"ADD": "コメントの追加",
"CANCEL": "キャンセル"
}
}
},
"ADD_DIALOG": {
"TITLE": "プロセス変数の設定",
"LABEL": {
"NAME": "名前",
"VALUE": "値",
"SCOPE": "範囲"
}
},
"EDIT_DIALOG": {
"TITLE": "プロセス変数の編集"
},
"ERROR_DIALOG": {
"TITLE": "処理を完了できませんでした",
"DESCRIPTION": "必要なレベルのアクセス権がない可能性があります。IT 担当者に確認してください。"
}
},
"START_PROCESS": {
"BUTTON": "プロセスの開始",
"NO_PROCESS_DEFINITIONS": "使用できるプロセス定義がないため、プロセスを開始できません",
"FORM": {
"TITLE": "プロセスの開始",
"LABEL": {
"TYPE": "プロセスの選択",
"NAME": "プロセス名"
},
"TYPE_PLACEHOLDER": "1 つ選択してください...",
"ACTION": {
"START": "プロセスの開始",
"CANCEL": "キャンセル"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "プロセス定義を読み込めませんでした。アクセス権があることを確認してください。",
"START": "新しいプロセスインスタンスを開始できませんでした。アクセス権があることを確認してください。",
"MAXIMUM_LENGTH": "長すぎます。{{characters}} 文字以内で入力してください。"
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "このリストは空です",
"DRAG-AND-DROP": {
"TITLE": "アップロードするファイルをドラッグ & ドロップしてください",
"SUBTITLE": ""
}
},
"EMPTY-LIST": {
"HEADER": "使用できるファイルがありません"
},
"COLUMNS": {
"NAME": "名前",
"CREATED-ON": "作成日"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "作成",
"NEW_TASK": "新しいタスク",
"NEW_PROCESS": "新しいプロセス"
}
},
"APP": {
"DIALOG": {
"START": "続行",
"TITLE": "プロセスアプリケーションの選択",
"LIST": "プロセスアプリケーションのリスト",
"ERROR": "Process Services への接続中に問題が発生しました"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "ログイン",
"CANCEL": "キャンセル",
"CHOOSE": "選択"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Klikk på Lagre for å legge til en rapport med gjeldende innstillinger til rapportlisten.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Startdato",
"END-DATE": "Sluttdato",
"MESSAGES": {
"START-DATE-REQUIRED": "Startdato er påkrevd",
"START-LESS-THAN-END-DATE": "Startdato må være før sluttdato"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Ingen applikasjoner funnet",
"SUBTITLE": "Opprett en ny applikasjon som er lett å finne senere",
"TASK_APP_NAME": "Oppgaveapp"
},
"LIST": {
"MESSAGES": {
"TITLE": "Fant ingen oppgaver",
"SUBTITLE": "Opprett en ny oppgave som du lett kan finne igjen senere",
"NONE": "Ingen oppgavelister funnet"
}
},
"PROPERTIES": {
"TASK_NAME": "Oppgave",
"THUMBNAIL": "Miniatyrbilde",
"DURATION": "Varighet",
"PARENT_TASK_ID": "Overordnet oppgave-ID",
"NAME": "Navn",
"ASSIGNEE": "Tilordnet",
"ASSIGNEE_DEFAULT": "Ingen tilordnet",
"PRIORITY": "Prioritet",
"DUE_DATE": "Forfallsdato",
"DUE_DATE_DEFAULT": "Ingen fristdato",
"STATUS": "Status",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"PARENT_NAME": "Navn på overordnet",
"PARENT_NAME_DEFAULT": "Ingen overordnet",
"CREATED_BY": "Opprettet av",
"CREATED": "Opprettet",
"END_DATE": "Sluttdato",
"ID": "ID",
"DESCRIPTION": "Beskrivelse",
"DESCRIPTION_DEFAULT": "Ingen beskrivelse",
"FORM_NAME": "Skjemaets navn",
"FORM_NAME_DEFAULT": "Ikke noe skjema"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Vis",
"REMOVE_CONTENT": "Fjern",
"DOWNLOAD_CONTENT": "Last ned",
"DOWNLOAD_AUDIT": "Last ned revisjon"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktiviteter",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivitet",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Detaljer",
"ASSIGNEE": "Tilordnet",
"DUE": "Forfaller",
"FORM": "Skjema",
"PEOPLE": "Personer som denne oppgavene er delt med",
"COMMENTS": "Kommentarer",
"CHECKLIST": "Sjekkliste",
"INVOLVED_PEOPLE": "Personer involvert",
"ADD_PEOPLE": "Legg til personer og grupper",
"ADD_ASSIGNEE": "Legg til ny tilordnet"
},
"BUTTON": {
"COMPLETE": "Fullfør",
"CLAIM": "Krev",
"UNCLAIM": "Frigi",
"DRAG-ATTACHMENT": "Slipp filer for å laste opp",
"UPLOAD-ATTACHMENT": "Last opp vedlegg"
},
"MESSAGES": {
"NONE": "Ingen oppgavedetaljer funnet",
"CLAIM": "Klikk på Krev for å jobbe med denne oppgaven"
},
"FORM": {
"NONE": "Ikke noe skjema"
},
"DUE": {
"NONE": "Ingen forfallsdato"
},
"ASSIGNEE": {
"NONE": "Ingen tilordnet"
},
"PEOPLE": {
"NONE": "Ingen involvert"
},
"CHECKLIST": {
"NONE": "Ingen sjekkliste",
"DIALOG": {
"TITLE": "Ny avmerking",
"CANCEL-BUTTON": "Avbryt",
"ADD-BUTTON": "Legg til sjekkliste",
"PLACEHOLDER": "Navn"
}
},
"ERROR": {
"TITLE": "Kan ikke fullføre handlingen",
"DESCRIPTION": "Prøv igjen, eller kontroller om du har tilgang.",
"CLOSE": "Lukk"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Ingen oppgavefilter valgt"
}
},
"START_TASK": {
"DEFAULT_NAME": "Mine standardoppgaver",
"BUTTON": "Opprett oppgave",
"FORM": {
"TITLE": "Start oppgave",
"LABEL": {
"NONE": "Ingen",
"NAME": "Navn",
"DESCRIPTION": "Beskrivelse",
"ATTACHFORM": "Legg ved skjema",
"ASSIGNEE": "Tilordnet",
"FORM": "Skjema",
"DATE": "Velg dato"
},
"ACTION": {
"START": "Start",
"CANCEL": "Avbryt"
},
"ERROR": {
"REQUIRED": "Felt er obligatorisk",
"DATE": "Datoformat DD.MM.ÅÅÅÅ",
"MAXIMUM_LENGTH": "Lengde overskredet, maks {{characters}} tegn.",
"MESSAGE": "Angi en annen verdi"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Tilordnet",
"DIALOG_CLOSE": "Lukk",
"ADD_USER": "Legg til",
"ADD_ASSIGNEE": "Tilordne",
"SEARCH_USER": "Søk etter bruker",
"SEARCH": {
"NO_USERS": "Ingen funnet å involvere"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Denne listen er tom",
"DRAG-AND-DROP": {
"TITLE": "Dra og slipp",
"SUBTITLE": "for å laste opp filer"
}
},
"EMPTY-LIST": {
"HEADER": "Ingen tilgjengelige filer"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Ingen skjemaer er vedlagt",
"COMPLETE_TASK_MESSAGE": "Oppgaven {{taskName}} er fullført",
"COMPLETE_TASK_SUB_MESSAGE": "Ingen skjemaer å legge til"
},
"ATTACH_FORM": {
"SELECT_FORM": "Velg skjema å legge ved",
"REMOVE_FORM": "Fjern skjema",
"SELECT_OPTION": "Velg et alternativ"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Ingen prosesser funnet",
"SUBTITLE": "Opprett en ny prosess som er lett å finne senere",
"SUMMARY": "{{total}} prosesstilfeller funnet",
"ERROR": "Kan ikke laste inn prosesstilfeller. Prøv igjen, eller del følgende melding med IT-teamet: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Ingen prosesstilfellefilter valgt."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Prosess",
"NAME": "Navn",
"THUMBNAIL": "Miniatyrbilde",
"STATUS": "Status",
"END_DATE": "Sluttdato",
"END_DATE_DEFAULT": "Ingen fristdato",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"CREATED_BY": "Opprettet av",
"CREATED_BY_DEFAULT": "Ingen tilordnet",
"CREATED": "Opprettet",
"BUSINESS_KEY": "Forretningsnøkkel",
"BUSINESS_KEY_DEFAULT": "Ingen",
"DESCRIPTION": "Beskrivelse",
"DESCRIPTION_DEFAULT": "Ingen beskrivelse",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Vis",
"REMOVE_CONTENT": "Fjern",
"DOWNLOAD_CONTENT": "Last ned",
"DOWNLOAD_AUDIT": "Last ned revisjon",
"VIEW_TASK": "Vis oppgave"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Startet av",
"STARTED": "Startet",
"ENDED": "Avsluttet",
"COMMENTS": "Kommentarer",
"START_FORM": "Start skjema",
"TASKS_ACTIVE": "Aktive oppgaver",
"TASKS_COMPLETED": "Fullførte oppgaver",
"TASK_SUBTITLE": "Tilordnet til {{user}}, opprettet {{created}}"
},
"BUTTON": {
"CANCEL": "Avbryt prosess",
"CLOSE": "Lukk",
"SHOW_DIAGRAM": "Vis diagram",
"DRAG-ATTACHMENT": "Slipp filer for å laste opp",
"UPLOAD-ATTACHMENT": "Last opp vedlegg"
},
"MESSAGES": {
"NONE": "Ingen prosessdetaljer funnet"
},
"TASKS": {
"NO_ACTIVE": "Ingen oppgaver aktive i øyeblikket",
"NO_COMPLETED": "Ingen oppgaver ennå fullført",
"TASK_DETAILS": "Detaljer for oppgave",
"TASK_CLOSE": "Lukk"
},
"COMMENTS": {
"ADD": "Legg til kommentar",
"HEADER": "Kommentarer ({{ count }})",
"NONE": "Ingen kommentarer",
"BUTTON": {
"ADD": "Legg til kommentar"
},
"ADD_DIALOG": {
"TITLE": "Nytt kommentar",
"LABEL": {
"MESSAGE": "Melding"
},
"BUTTON": {
"ADD": "Legg til kommentar",
"CANCEL": "Avbryt"
}
}
},
"ADD_DIALOG": {
"TITLE": "Angi prosessvariabel",
"LABEL": {
"NAME": "Navn",
"VALUE": "Verdi",
"SCOPE": "Område"
}
},
"EDIT_DIALOG": {
"TITLE": "Rediger prosessvariabel'"
},
"ERROR_DIALOG": {
"TITLE": "Kan ikke fullføre handlingen",
"DESCRIPTION": "Du har kanskje ikke det nødvendige tilgangsnivået, kontakt IT-teamet."
}
},
"START_PROCESS": {
"BUTTON": "Start prosess",
"NO_PROCESS_DEFINITIONS": "Du kan ikke starte en prosess fordi det ikke finnes noen tilgjengelige prosessdefinisjoner",
"FORM": {
"TITLE": "Start prosess",
"LABEL": {
"TYPE": "Velg prosess",
"NAME": "Prosessnavn"
},
"TYPE_PLACEHOLDER": "Velg én...",
"ACTION": {
"START": "Start prosess",
"CANCEL": "Avbryt"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Kan ikke laste prosessdefinisjoner, kontroller om du har tilgang.",
"START": "Kan ikke start nytt prosesstilfelle, kontroller om du har tilgang.",
"MAXIMUM_LENGTH": "Lengde overskredet, maks {{characters}} tegn."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Denne listen er tom",
"DRAG-AND-DROP": {
"TITLE": "Dra og slipp",
"SUBTITLE": "for å laste opp filer"
}
},
"EMPTY-LIST": {
"HEADER": "Ingen tilgjengelige filer"
},
"COLUMNS": {
"NAME": "Navn",
"CREATED-ON": "Opprettet"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Opprett",
"NEW_TASK": "Ny oppgave",
"NEW_PROCESS": "Ny prosess"
}
},
"APP": {
"DIALOG": {
"START": "Fortsett",
"TITLE": "Velg et program",
"LIST": "Programliste",
"ERROR": "Kan ikke koble til Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Logg på",
"CANCEL": "Avbryt",
"CHOOSE": "Velg"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Klik op Opslaan om een rapport met de huidige instellingen toe te voegen aan uw lijst met rapporten.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Begindatum",
"END-DATE": "Einddatum",
"MESSAGES": {
"START-DATE-REQUIRED": "Begindatum is vereist",
"START-LESS-THAN-END-DATE": "De begindatum moet voor de einddatum liggen"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Geen toepassingen gevonden",
"SUBTITLE": "Maak een nieuwe toepassing die u later gemakkelijk wilt kunnen vinden",
"TASK_APP_NAME": "Task App"
},
"LIST": {
"MESSAGES": {
"TITLE": "Geen taken gevonden",
"SUBTITLE": "Maak een nieuwe taak die u later gemakkelijk wilt kunnen vinden",
"NONE": "Geen takenlijsten gevonden"
}
},
"PROPERTIES": {
"TASK_NAME": "Taak",
"THUMBNAIL": "Miniatuur",
"DURATION": "Duur",
"PARENT_TASK_ID": "Id bovenliggende taak",
"NAME": "Naam",
"ASSIGNEE": "Toegewezen persoon",
"ASSIGNEE_DEFAULT": "Geen toegewezen persoon",
"PRIORITY": "Prioriteit",
"DUE_DATE": "Vervaldatum",
"DUE_DATE_DEFAULT": "Geen vervaldatum",
"STATUS": "Status",
"CATEGORY": "Categorie",
"CATEGORY_DEFAULT": "Geen categorie",
"PARENT_NAME": "Naam bovenliggend element",
"PARENT_NAME_DEFAULT": "Geen bovenliggend element",
"CREATED_BY": "Gemaakt door",
"CREATED": "Gemaakt",
"END_DATE": "Einddatum",
"ID": "Id",
"DESCRIPTION": "Beschrijving",
"DESCRIPTION_DEFAULT": "Geen beschrijving",
"FORM_NAME": "Formuliernaam",
"FORM_NAME_DEFAULT": "Geen formulier"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Weergeven",
"REMOVE_CONTENT": "Verwijderen",
"DOWNLOAD_CONTENT": "Downloaden",
"DOWNLOAD_AUDIT": "Audit downloaden"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Activiteiten",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Activiteit",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Details",
"ASSIGNEE": "Toegewezen persoon",
"DUE": "Vervalt",
"FORM": "Formulier",
"PEOPLE": "Personen met wie deze taak is gedeeld",
"COMMENTS": "Opmerkingen",
"CHECKLIST": "Controlelijst",
"INVOLVED_PEOPLE": "Betrokken personen",
"ADD_PEOPLE": "Personen en groepen toevoegen",
"ADD_ASSIGNEE": "Nieuwe toegewezen persoon toevoegen"
},
"BUTTON": {
"COMPLETE": "Voltooid",
"CLAIM": "Claimen",
"UNCLAIM": "Vrijgeven",
"DRAG-ATTACHMENT": "Bestanden neerzetten om te uploaden",
"UPLOAD-ATTACHMENT": "Bijlage uploaden"
},
"MESSAGES": {
"NONE": "Geen taakdetails gevonden",
"CLAIM": "Klik op Claimen om aan deze taak te werken"
},
"FORM": {
"NONE": "Geen formulier"
},
"DUE": {
"NONE": "Geen vervaldatum"
},
"ASSIGNEE": {
"NONE": "Geen toegewezen persoon"
},
"PEOPLE": {
"NONE": "Niemand betrokken"
},
"CHECKLIST": {
"NONE": "Geen controlelijst",
"DIALOG": {
"TITLE": "Nieuw vakje geselecteerd",
"CANCEL-BUTTON": "Annuleren",
"ADD-BUTTON": "Controlelijst toevoegen",
"PLACEHOLDER": "Naam"
}
},
"ERROR": {
"TITLE": "Kan de actie niet voltooien",
"DESCRIPTION": "Probeer het opnieuw of controleer of u over toegang beschikt.",
"CLOSE": "Sluiten"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Geen taakfilter geselecteerd"
}
},
"START_TASK": {
"DEFAULT_NAME": "Mijn standaardtaak",
"BUTTON": "Taak maken",
"FORM": {
"TITLE": "Taak starten",
"LABEL": {
"NONE": "Geen",
"NAME": "Naam",
"DESCRIPTION": "Beschrijving",
"ATTACHFORM": "Formulier bijvoegen",
"ASSIGNEE": "Toegewezen persoon",
"FORM": "Formulier",
"DATE": "Datum kiezen"
},
"ACTION": {
"START": "Start",
"CANCEL": "Annuleren"
},
"ERROR": {
"REQUIRED": "Veld vereist",
"DATE": "Datumnotatie dd-mm-jjjj",
"MAXIMUM_LENGTH": "Lengte overschreden, max. {{characters}} tekens",
"MESSAGE": "Voer een andere waarde in"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Toegewezen persoon",
"DIALOG_CLOSE": "Sluiten",
"ADD_USER": "Toevoegen",
"ADD_ASSIGNEE": "Toewijzen",
"SEARCH_USER": "Gebruiker zoeken",
"SEARCH": {
"NO_USERS": "Niemand gevonden om te betrekken"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Deze lijst is leeg",
"DRAG-AND-DROP": {
"TITLE": "Slepen en neerzetten",
"SUBTITLE": "om bestanden te uploaden"
}
},
"EMPTY-LIST": {
"HEADER": "Er zijn geen bestanden beschikbaar"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Geen formulieren bijgevoegd",
"COMPLETE_TASK_MESSAGE": "Taak {{taskName}} voltooid",
"COMPLETE_TASK_SUB_MESSAGE": "Geen formulieren om toe te voegen"
},
"ATTACH_FORM": {
"SELECT_FORM": "Selecteer formulier om bij te voegen",
"REMOVE_FORM": "Formulier verwijderen",
"SELECT_OPTION": "Selecteer een optie"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Geen processen gevonden",
"SUBTITLE": "Maak een nieuw proces dat u later gemakkelijk wilt kunnen vinden",
"SUMMARY": "{{total}} procesinstances gevonden",
"ERROR": "Kan procesinstances niet laden. Probeer het opnieuw of geef het volgende bericht door aan het IT-team: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Geen procesinstancefilter geselecteerd."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Proces",
"NAME": "Naam",
"THUMBNAIL": "Miniatuur",
"STATUS": "Status",
"END_DATE": "Einddatum",
"END_DATE_DEFAULT": "Geen vervaldatum",
"CATEGORY": "Categorie",
"CATEGORY_DEFAULT": "Geen categorie",
"CREATED_BY": "Gemaakt door",
"CREATED_BY_DEFAULT": "Geen toegewezen persoon",
"CREATED": "Gemaakt",
"BUSINESS_KEY": "Business key",
"BUSINESS_KEY_DEFAULT": "Geen",
"DESCRIPTION": "Beschrijving",
"DESCRIPTION_DEFAULT": "Geen beschrijving",
"ID": "Id"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Weergeven",
"REMOVE_CONTENT": "Verwijderen",
"DOWNLOAD_CONTENT": "Downloaden",
"DOWNLOAD_AUDIT": "Audit downloaden",
"VIEW_TASK": "Taak weergeven"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Gestart door",
"STARTED": "Gestart",
"ENDED": "Beëindigd",
"COMMENTS": "Opmerkingen",
"START_FORM": "Beginformulier",
"TASKS_ACTIVE": "Actieve taken",
"TASKS_COMPLETED": "Voltooide taken",
"TASK_SUBTITLE": "Toegewezen aan {{user}}, gemaakt {{created}}"
},
"BUTTON": {
"CANCEL": "Proces annuleren",
"CLOSE": "Sluiten",
"SHOW_DIAGRAM": "Diagram weergeven",
"DRAG-ATTACHMENT": "Bestanden neerzetten om te uploaden",
"UPLOAD-ATTACHMENT": "Bijlage uploaden"
},
"MESSAGES": {
"NONE": "Geen procesdetails gevonden"
},
"TASKS": {
"NO_ACTIVE": "Geen momenteel actieve taken",
"NO_COMPLETED": "Nog geen taken voltooid",
"TASK_DETAILS": "Taakdetails",
"TASK_CLOSE": "Sluiten"
},
"COMMENTS": {
"ADD": "Opmerking toevoegen",
"HEADER": "Opmerkingen ({{ count }})",
"NONE": "Geen opmerkingen",
"BUTTON": {
"ADD": "Opmerking toevoegen"
},
"ADD_DIALOG": {
"TITLE": "Nieuwe opmerking",
"LABEL": {
"MESSAGE": "Bericht"
},
"BUTTON": {
"ADD": "Opmerking toevoegen",
"CANCEL": "Annuleren"
}
}
},
"ADD_DIALOG": {
"TITLE": "Procesvariabele instellen",
"LABEL": {
"NAME": "Naam",
"VALUE": "Waarde",
"SCOPE": "Bereik"
}
},
"EDIT_DIALOG": {
"TITLE": "Procesvariabele bewerken"
},
"ERROR_DIALOG": {
"TITLE": "Kan de actie niet voltooien",
"DESCRIPTION": "U beschikt mogelijk niet over het vereiste toegangsniveau, neem contact op met het IT-team."
}
},
"START_PROCESS": {
"BUTTON": "Proces starten",
"NO_PROCESS_DEFINITIONS": "U kunt geen proces starten omdat er geen procesdefinities beschikbaar zijn",
"FORM": {
"TITLE": "Proces starten",
"LABEL": {
"TYPE": "Proces selecteren",
"NAME": "Procesnaam"
},
"TYPE_PLACEHOLDER": "Maak een keuze...",
"ACTION": {
"START": "Proces starten",
"CANCEL": "Annuleren"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Kan procesdefinities niet laden, controleer of u over toegang beschikt.",
"START": "Kan geen nieuwe procesinstance starten, controleer of u over toegang beschikt.",
"MAXIMUM_LENGTH": "Lengte overschreden, max. {{characters}} tekens."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Deze lijst is leeg",
"DRAG-AND-DROP": {
"TITLE": "Slepen en neerzetten",
"SUBTITLE": "om bestanden te uploaden"
}
},
"EMPTY-LIST": {
"HEADER": "Er zijn geen bestanden beschikbaar"
},
"COLUMNS": {
"NAME": "Naam",
"CREATED-ON": "Gemaakt op"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Maken",
"NEW_TASK": "Nieuwe taak",
"NEW_PROCESS": "Nieuw proces"
}
},
"APP": {
"DIALOG": {
"START": "Doorgaan",
"TITLE": "App selecteren",
"LIST": "Lijst met apps",
"ERROR": "Er is een probleem opgetreden bij het verbinden met Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Aanmelden",
"CANCEL": "Annuleren",
"CHOOSE": "Kiezen"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Kliknij Zapisz, aby do listy raportów dodać raport z bieżącymi ustawieniami.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Data rozpoczęcia",
"END-DATE": "Data zakończenia",
"MESSAGES": {
"START-DATE-REQUIRED": "Data rozpoczęcia jest wymagana.",
"START-LESS-THAN-END-DATE": "Data rozpoczęcia musi być wcześniejsza od daty zakończenia."
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Nie znaleziono aplikacji.",
"SUBTITLE": "Utwórz nową aplikację, którą później będzie łatwo znaleźć.",
"TASK_APP_NAME": "Aplikacja zadań"
},
"LIST": {
"MESSAGES": {
"TITLE": "Nie znaleziono zadań.",
"SUBTITLE": "Utwórz nowe zadanie, które później będzie łatwo znaleźć.",
"NONE": "Nie znaleziono list zadań."
}
},
"PROPERTIES": {
"TASK_NAME": "Zadanie",
"THUMBNAIL": "Miniatura",
"DURATION": "Czas trwania",
"PARENT_TASK_ID": "Identyfikator zadania nadrzędnego",
"NAME": "Nazwa",
"ASSIGNEE": "Osoba przypisana",
"ASSIGNEE_DEFAULT": "Brak osoby przypisanej",
"PRIORITY": "Priorytet",
"DUE_DATE": "Data ukończenia",
"DUE_DATE_DEFAULT": "Brak daty",
"STATUS": "Status",
"CATEGORY": "Kategoria",
"CATEGORY_DEFAULT": "Brak kategorii",
"PARENT_NAME": "Nazwa obiektu nadrzędnego",
"PARENT_NAME_DEFAULT": "Brak obiektu nadrzędnego",
"CREATED_BY": "Utworzone przez",
"CREATED": "Utworzono",
"END_DATE": "Data zakończenia",
"ID": "Identyfikator",
"DESCRIPTION": "Opis",
"DESCRIPTION_DEFAULT": "Brak opisu",
"FORM_NAME": "Nazwa formularza",
"FORM_NAME_DEFAULT": "Brak formularza"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Widok",
"REMOVE_CONTENT": "Usuń",
"DOWNLOAD_CONTENT": "Pobierz",
"DOWNLOAD_AUDIT": "Pobierz inspekcję"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktywności",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Działanie",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Szczegóły",
"ASSIGNEE": "Osoba przypisana",
"DUE": "Termin",
"FORM": "Formularz",
"PEOPLE": "Osoby, którym udostępniono to zadanie.",
"COMMENTS": "Komentarze",
"CHECKLIST": "Lista kontrolna",
"INVOLVED_PEOPLE": "Osoby zaangażowane",
"ADD_PEOPLE": "Dodaj osoby i grupy",
"ADD_ASSIGNEE": "Dodaj nową osobę przypisaną"
},
"BUTTON": {
"COMPLETE": "Zakończ",
"CLAIM": "Przejmij",
"UNCLAIM": "Zwolnij",
"DRAG-ATTACHMENT": "Upuść i prześlij pliki",
"UPLOAD-ATTACHMENT": "Prześlij załącznik"
},
"MESSAGES": {
"NONE": "Nie znaleziono szczegółów zadania.",
"CLAIM": "Kliknij przycisk Przejmij, aby przystąpić do pracy nad tym zadaniem."
},
"FORM": {
"NONE": "Brak formularza"
},
"DUE": {
"NONE": "Bez daty ukończenia"
},
"ASSIGNEE": {
"NONE": "Brak osoby przypisanej"
},
"PEOPLE": {
"NONE": "Brak osób zaangażowanych"
},
"CHECKLIST": {
"NONE": "Brak listy kontrolnej",
"DIALOG": {
"TITLE": "Nowe sprawdzenie",
"CANCEL-BUTTON": "Anuluj",
"ADD-BUTTON": "Dodaj listę kontrolną",
"PLACEHOLDER": "Nazwa"
}
},
"ERROR": {
"TITLE": "Nie można wykonać czynności.",
"DESCRIPTION": "Spróbuj ponownie lub sprawdź, czy masz dostęp.",
"CLOSE": "Zamknij"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nie wybrano filtra zadań."
}
},
"START_TASK": {
"DEFAULT_NAME": "Moje domyślne zadanie",
"BUTTON": "Utwórz zadanie",
"FORM": {
"TITLE": "Rozpocznij zadanie",
"LABEL": {
"NONE": "Brak",
"NAME": "Nazwa",
"DESCRIPTION": "Opis",
"ATTACHFORM": "Załącz formularz",
"ASSIGNEE": "Osoba przypisana",
"FORM": "Formularz",
"DATE": "Wybierz datę"
},
"ACTION": {
"START": "Uruchom",
"CANCEL": "Anuluj"
},
"ERROR": {
"REQUIRED": "Pole wymagane",
"DATE": "Format daty DD/MM/RRRR",
"MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków",
"MESSAGE": "Wprowadź inną wartość."
}
}
},
"PEOPLE": {
"ASSIGNEE": "Osoba przypisana",
"DIALOG_CLOSE": "Zamknij",
"ADD_USER": "Dodaj",
"ADD_ASSIGNEE": "Przypisz",
"SEARCH_USER": "Szukaj użytkownika",
"SEARCH": {
"NO_USERS": "Nie znaleziono osób do zaangażowania."
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Ta lista jest pusta.",
"DRAG-AND-DROP": {
"TITLE": "Przeciągnij i upuść",
"SUBTITLE": "aby przesłać pliki"
}
},
"EMPTY-LIST": {
"HEADER": "Brak dostępnych plików."
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Nie załączono formularzy",
"COMPLETE_TASK_MESSAGE": "Zadanie {{taskName}} zostało zakończone.",
"COMPLETE_TASK_SUB_MESSAGE": "Brak formularzy do dodania."
},
"ATTACH_FORM": {
"SELECT_FORM": "Wybierz formularz do załączenia.",
"REMOVE_FORM": "Usuń formularz",
"SELECT_OPTION": "Wybierz opcję"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Nie znaleziono żadnego procesu.",
"SUBTITLE": "Utwórz nowy proces, który później będzie łatwo znaleźć.",
"SUMMARY": "Znaleziono następującą liczbę wystąpień procesu: {{total}}.",
"ERROR": "Nie można wczytać wystąpień procesu. Spróbuj ponownie lub udostępnij zespołowi IT następujący komunikat: {{errorMessage}}."
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nie wybrano filtra wystąpień procesu."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Proces",
"NAME": "Nazwa",
"THUMBNAIL": "Miniatura",
"STATUS": "Status",
"END_DATE": "Data zakończenia",
"END_DATE_DEFAULT": "Brak daty",
"CATEGORY": "Kategoria",
"CATEGORY_DEFAULT": "Brak kategorii",
"CREATED_BY": "Utworzone przez",
"CREATED_BY_DEFAULT": "Brak osoby przypisanej",
"CREATED": "Utworzono",
"BUSINESS_KEY": "Klucz biznesowy",
"BUSINESS_KEY_DEFAULT": "Brak",
"DESCRIPTION": "Opis",
"DESCRIPTION_DEFAULT": "Brak opisu",
"ID": "Identyfikator"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Widok",
"REMOVE_CONTENT": "Usuń",
"DOWNLOAD_CONTENT": "Pobierz",
"DOWNLOAD_AUDIT": "Pobierz inspekcję",
"VIEW_TASK": "Widok zadania"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Uruchomione przez",
"STARTED": "Uruchomione",
"ENDED": "Zakończone",
"COMMENTS": "Komentarze",
"START_FORM": "Uruchom formularz",
"TASKS_ACTIVE": "Aktywne zadania",
"TASKS_COMPLETED": "Ukończone zadania",
"TASK_SUBTITLE": "Przypisane do użytkownika {{user}}, utworzone {{created}}."
},
"BUTTON": {
"CANCEL": "Anuluj proces",
"CLOSE": "Zamknij",
"SHOW_DIAGRAM": "Pokaż schemat",
"DRAG-ATTACHMENT": "Upuść i prześlij pliki",
"UPLOAD-ATTACHMENT": "Prześlij załącznik"
},
"MESSAGES": {
"NONE": "Nie znaleziono szczegółów procesu."
},
"TASKS": {
"NO_ACTIVE": "Brak obecnie aktywnych zadań.",
"NO_COMPLETED": "Brak ukończonych zadań.",
"TASK_DETAILS": "Szczegóły zadania",
"TASK_CLOSE": "Zamknij"
},
"COMMENTS": {
"ADD": "Dodaj komentarz",
"HEADER": "Liczba komentarzy: ({{ count }})",
"NONE": "Brak komentarzy",
"BUTTON": {
"ADD": "Dodaj komentarz"
},
"ADD_DIALOG": {
"TITLE": "Nowy komentarz",
"LABEL": {
"MESSAGE": "Komunikat"
},
"BUTTON": {
"ADD": "Dodaj komentarz",
"CANCEL": "Anuluj"
}
}
},
"ADD_DIALOG": {
"TITLE": "Ustaw zmienną procesu",
"LABEL": {
"NAME": "Nazwa",
"VALUE": "Wartość",
"SCOPE": "Zakres"
}
},
"EDIT_DIALOG": {
"TITLE": "Edytuj zmienną procesu"
},
"ERROR_DIALOG": {
"TITLE": "Nie można wykonać czynności.",
"DESCRIPTION": "Prawdopodobnie nie dysponujesz żądanym poziomem dostępu. Skonsultuj się z zespołem IT."
}
},
"START_PROCESS": {
"BUTTON": "Rozpocznij proces",
"NO_PROCESS_DEFINITIONS": "Nie można rozpocząć procesu, ponieważ brak dostępnych definicji procesu.",
"FORM": {
"TITLE": "Rozpocznij proces",
"LABEL": {
"TYPE": "Wybierz proces",
"NAME": "Nazwa procesu"
},
"TYPE_PLACEHOLDER": "Wybierz jeden...",
"ACTION": {
"START": "Rozpocznij proces",
"CANCEL": "Anuluj"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Nie można wczytać definicji procesu. Sprawdź, czy masz dostęp.",
"START": "Nie można rozpocząć nowego wystąpienia procesu. Sprawdź, czy masz dostęp.",
"MAXIMUM_LENGTH": "Przekroczono długość, maksymalna długość wynosi {{characters}} znaków"
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Ta lista jest pusta.",
"DRAG-AND-DROP": {
"TITLE": "Przeciągnij i upuść",
"SUBTITLE": "aby przesłać pliki"
}
},
"EMPTY-LIST": {
"HEADER": "Brak dostępnych plików."
},
"COLUMNS": {
"NAME": "Nazwa",
"CREATED-ON": "Data utworzenia"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Utwórz",
"NEW_TASK": "Nowe zadanie",
"NEW_PROCESS": "Nowy proces"
}
},
"APP": {
"DIALOG": {
"START": "Kontynuuj",
"TITLE": "Wybierz aplikację procesu",
"LIST": "Lista aplikacji procesu",
"ERROR": "Podczas nawiązywania połączenia z usługami procesu wystąpił problem."
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Zaloguj",
"CANCEL": "Anuluj",
"CHOOSE": "Wybierz"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Clique em Salvar para adicionar um relatório com as configurações atuais à sua lista de relatórios.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Data de início",
"END-DATE": "Data de término",
"MESSAGES": {
"START-DATE-REQUIRED": "A data de início é obrigatória",
"START-LESS-THAN-END-DATE": "A data de início deve ser anterior à data de término"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Nenhum Aplicativo Encontrado",
"SUBTITLE": "Crie um aplicativo que você possa identificar com facilidade depois",
"TASK_APP_NAME": "Aplicativo de tarefas"
},
"LIST": {
"MESSAGES": {
"TITLE": "Nenhuma tarefa encontrada",
"SUBTITLE": "Crie uma tarefa que você consiga encontrar facilmente depois",
"NONE": "Nenhuma lista de tarefas encontrada"
}
},
"PROPERTIES": {
"TASK_NAME": "Tarefa",
"THUMBNAIL": "Miniatura",
"DURATION": "Duração",
"PARENT_TASK_ID": "ID da tarefa primária",
"NAME": "Nome",
"ASSIGNEE": "Destinatário",
"ASSIGNEE_DEFAULT": "Nenhum destinatário",
"PRIORITY": "Prioridade",
"DUE_DATE": "Data de vencimento",
"DUE_DATE_DEFAULT": "Nenhuma data",
"STATUS": "Status",
"CATEGORY": "Categoria",
"CATEGORY_DEFAULT": "Nenhuma categoria",
"PARENT_NAME": "Nome primário",
"PARENT_NAME_DEFAULT": "Nenhum primário",
"CREATED_BY": "Criado por",
"CREATED": "Criado",
"END_DATE": "Data de término",
"ID": "ID",
"DESCRIPTION": "Descrição",
"DESCRIPTION_DEFAULT": "Nenhuma descrição",
"FORM_NAME": "Nome de formulário",
"FORM_NAME_DEFAULT": "Nenhum formulário"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visualizar",
"REMOVE_CONTENT": "Remover",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Baixar Auditoria"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Atividades",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Atividade",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Detalhes",
"ASSIGNEE": "Destinatário",
"DUE": "Vencimento",
"FORM": "Formulário",
"PEOPLE": "Pessoas com quem esta tarefa está compartilhada",
"COMMENTS": "Comentários",
"CHECKLIST": "Lista de verificação",
"INVOLVED_PEOPLE": "Pessoas Envolvidas",
"ADD_PEOPLE": "Adicionar pessoas e grupos",
"ADD_ASSIGNEE": "Adicionar novo destinatário"
},
"BUTTON": {
"COMPLETE": "Completar",
"CLAIM": "Reivindicar",
"UNCLAIM": "Liberar",
"DRAG-ATTACHMENT": "Solte os arquivos para carregar",
"UPLOAD-ATTACHMENT": "Carregar Anexo"
},
"MESSAGES": {
"NONE": "Nenhum detalhe de tarefa encontrado",
"CLAIM": "Clique em Reivindicar para trabalhar nesta tarefa"
},
"FORM": {
"NONE": "Nenhum formulário"
},
"DUE": {
"NONE": "Sem data de vencimento"
},
"ASSIGNEE": {
"NONE": "Nenhum destinatário"
},
"PEOPLE": {
"NONE": "Ninguém envolvido"
},
"CHECKLIST": {
"NONE": "Nenhuma lista de verificação",
"DIALOG": {
"TITLE": "Nova verificação",
"CANCEL-BUTTON": "Cancelar",
"ADD-BUTTON": "Adicionar lista de verificação",
"PLACEHOLDER": "Nome"
}
},
"ERROR": {
"TITLE": "Não foi possível concluir a ação",
"DESCRIPTION": "Tente novamente ou verifique se você tem acesso.",
"CLOSE": "Fechar"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nenhum filtro de tarefa selecionado"
}
},
"START_TASK": {
"DEFAULT_NAME": "Minha tarefa padrão",
"BUTTON": "Criar tarefa",
"FORM": {
"TITLE": "Iniciar tarefa",
"LABEL": {
"NONE": "Nenhum",
"NAME": "Nome",
"DESCRIPTION": "Descrição",
"ATTACHFORM": "Anexar formulário",
"ASSIGNEE": "Destinatário",
"FORM": "Formulário",
"DATE": "Escolher Data"
},
"ACTION": {
"START": "Iniciar",
"CANCEL": "Cancelar"
},
"ERROR": {
"REQUIRED": "Campo obrigatório",
"DATE": "Formato de data DD/MM/AAAA",
"MAXIMUM_LENGTH": "Tamanho excedido, máximo de {{characters}} caracteres.",
"MESSAGE": "Insira um valor diferente"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Destinatário",
"DIALOG_CLOSE": "Fechar",
"ADD_USER": "Adicionar",
"ADD_ASSIGNEE": "Atribuir",
"SEARCH_USER": "Pesquisar usuário",
"SEARCH": {
"NO_USERS": "Ninguém encontrado para envolver"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Esta lista está vazia",
"DRAG-AND-DROP": {
"TITLE": "Arraste e solte",
"SUBTITLE": "para carregar arquivos"
}
},
"EMPTY-LIST": {
"HEADER": "Nenhum arquivo disponível"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Sem formulários anexados",
"COMPLETE_TASK_MESSAGE": "Tarefa {{taskName}} concluída",
"COMPLETE_TASK_SUB_MESSAGE": "Sem formulários a serem adicionados"
},
"ATTACH_FORM": {
"SELECT_FORM": "Selecionar formulário para anexar",
"REMOVE_FORM": "Remover formulário",
"SELECT_OPTION": "Selecionar uma opção"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Nenhum Processo Encontrado",
"SUBTITLE": "Crie um processo que você possa identificar com facilidade depois",
"SUMMARY": "{{total}} instâncias de processo encontradas",
"ERROR": "Não foi possível carregar as instâncias de processos. Tente novamente ou compartilhe a mensagem a seguir com sua Equipe de TI: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Nenhum filtro de instância de processo selecionado."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Processo",
"NAME": "Nome",
"THUMBNAIL": "Miniatura",
"STATUS": "Status",
"END_DATE": "Data de término",
"END_DATE_DEFAULT": "Nenhuma data",
"CATEGORY": "Categoria",
"CATEGORY_DEFAULT": "Nenhuma categoria",
"CREATED_BY": "Criado por",
"CREATED_BY_DEFAULT": "Nenhum destinatário",
"CREATED": "Criado",
"BUSINESS_KEY": "Chave de negócios",
"BUSINESS_KEY_DEFAULT": "Nenhum",
"DESCRIPTION": "Descrição",
"DESCRIPTION_DEFAULT": "Nenhuma descrição",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visualizar",
"REMOVE_CONTENT": "Remover",
"DOWNLOAD_CONTENT": "Download",
"DOWNLOAD_AUDIT": "Baixar auditoria",
"VIEW_TASK": "Exibir tarefa"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Iniciado por",
"STARTED": "Iniciado",
"ENDED": "Finalizado",
"COMMENTS": "Comentários",
"START_FORM": "Iniciar formulário",
"TASKS_ACTIVE": "Tarefas ativas",
"TASKS_COMPLETED": "Tarefas concluídas",
"TASK_SUBTITLE": "Atribuído a {{user}}, criado {{created}}"
},
"BUTTON": {
"CANCEL": "Cancelar processo",
"CLOSE": "Fechar",
"SHOW_DIAGRAM": "Mostrar diagrama",
"DRAG-ATTACHMENT": "Solte os arquivos para carregar",
"UPLOAD-ATTACHMENT": "Carregar Anexo"
},
"MESSAGES": {
"NONE": "Nenhum detalhe de processo encontrado"
},
"TASKS": {
"NO_ACTIVE": "Nenhuma tarefa ativa no momento",
"NO_COMPLETED": "Nenhuma tarefa concluída ainda",
"TASK_DETAILS": "Detalhes da tarefa",
"TASK_CLOSE": "Fechar"
},
"COMMENTS": {
"ADD": "Adicionar comentário",
"HEADER": "({{ count }}) comentários",
"NONE": "Sem comentários",
"BUTTON": {
"ADD": "Adicionar comentário"
},
"ADD_DIALOG": {
"TITLE": "Novo comentário",
"LABEL": {
"MESSAGE": "Mensagem"
},
"BUTTON": {
"ADD": "Adicionar comentário",
"CANCEL": "Cancelar"
}
}
},
"ADD_DIALOG": {
"TITLE": "Definir variável do processo",
"LABEL": {
"NAME": "Nome",
"VALUE": "Valor",
"SCOPE": "Escopo"
}
},
"EDIT_DIALOG": {
"TITLE": "Editar variável do processo"
},
"ERROR_DIALOG": {
"TITLE": "Não foi possível concluir a ação",
"DESCRIPTION": "Talvez você não tenha o nível de acesso exigido, verifique com a Equipe de TI."
}
},
"START_PROCESS": {
"BUTTON": "Iniciar processo",
"NO_PROCESS_DEFINITIONS": "Você não pode iniciar um processo porque não há definições de processo disponíveis",
"FORM": {
"TITLE": "Iniciar processo",
"LABEL": {
"TYPE": "Selecionar Processo",
"NAME": "Nome de processo"
},
"TYPE_PLACEHOLDER": "Escolha uma opção...",
"ACTION": {
"START": "Iniciar processo",
"CANCEL": "Cancelar"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Não foi possível carregar as definições do processo, verifique se você tem acesso.",
"START": "Não foi possível iniciar a instância de novo processo, verifique se você tem acesso.",
"MAXIMUM_LENGTH": "Tamanho excedido, máximo de {{characters}} caracteres."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Esta lista está vazia",
"DRAG-AND-DROP": {
"TITLE": "Arraste e solte",
"SUBTITLE": "para carregar arquivos"
}
},
"EMPTY-LIST": {
"HEADER": "Nenhum arquivo disponível"
},
"COLUMNS": {
"NAME": "Nome",
"CREATED-ON": "Criado em"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Criar",
"NEW_TASK": "Nova tarefa",
"NEW_PROCESS": "Novo processo"
}
},
"APP": {
"DIALOG": {
"START": "Continuar",
"TITLE": "Selecionar um aplicativo",
"LIST": "Lista de aplicações",
"ERROR": "Houve um problema ao conectar com o Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Login",
"CANCEL": "Cancelar",
"CHOOSE": "Escolher"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Нажмите Сохранить, чтобы добавить отчет с текущими параметрами в список отчетов.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Дата начала",
"END-DATE": "Дата окончания",
"MESSAGES": {
"START-DATE-REQUIRED": "Необходимо указать дату начала",
"START-LESS-THAN-END-DATE": "Дата начала должна быть раньше даты окончания"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Приложения не найдены",
"SUBTITLE": "Создайте новое приложение, которое вы сможете легко найти позже",
"TASK_APP_NAME": "Приложение для задач"
},
"LIST": {
"MESSAGES": {
"TITLE": "Задачи не найдены",
"SUBTITLE": "Создать новую задачу для быстрого поиска позже",
"NONE": "Списков задач не найдено"
}
},
"PROPERTIES": {
"TASK_NAME": "Задача",
"THUMBNAIL": "Эскиз",
"DURATION": "Продолжительность",
"PARENT_TASK_ID": "Идентификатор родительского задания",
"NAME": "Имя",
"ASSIGNEE": "Исполнитель",
"ASSIGNEE_DEFAULT": "Нет исполнителя",
"PRIORITY": "Приоритет",
"DUE_DATE": "Срок",
"DUE_DATE_DEFAULT": "Нет срока",
"STATUS": "Статус",
"CATEGORY": "Категория",
"CATEGORY_DEFAULT": "Нет категории",
"PARENT_NAME": "Имя родительского элемента",
"PARENT_NAME_DEFAULT": "Нет родительского элемента",
"CREATED_BY": "Создано пользователем",
"CREATED": "Создано",
"END_DATE": "Дата окончания",
"ID": "Идентификатор",
"DESCRIPTION": "Описание",
"DESCRIPTION_DEFAULT": "Нет описания",
"FORM_NAME": "Имя формы",
"FORM_NAME_DEFAULT": "Без формы"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Посмотреть",
"REMOVE_CONTENT": "Удалить",
"DOWNLOAD_CONTENT": "Скачать",
"DOWNLOAD_AUDIT": "Скачать аудит"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Действия",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Действие",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Сведения",
"ASSIGNEE": "Исполнитель",
"DUE": "Срок",
"FORM": "Форма",
"PEOPLE": "Люди, которым открыт доступ к этой задаче",
"COMMENTS": "Комментарии",
"CHECKLIST": "Контрольный список",
"INVOLVED_PEOPLE": "Участвующие люди",
"ADD_PEOPLE": "Добавить людей и группы",
"ADD_ASSIGNEE": "Добавить нового исполнителя"
},
"BUTTON": {
"COMPLETE": "Завершить",
"CLAIM": "Принять",
"UNCLAIM": "Освободить",
"DRAG-ATTACHMENT": "Перетащите файлы для загрузки",
"UPLOAD-ATTACHMENT": "Загрузить вложение"
},
"MESSAGES": {
"NONE": "Сведений о задаче не найдено",
"CLAIM": "Чтобы приступить к работе над этой задачей, нажмите \"Принять\""
},
"FORM": {
"NONE": "Без формы"
},
"DUE": {
"NONE": "Без срока"
},
"ASSIGNEE": {
"NONE": "Нет исполнителя"
},
"PEOPLE": {
"NONE": "Нет участников"
},
"CHECKLIST": {
"NONE": "Нет контрольных списков",
"DIALOG": {
"TITLE": "Новая проверка",
"CANCEL-BUTTON": "Отмена",
"ADD-BUTTON": "Добавить контрольный список",
"PLACEHOLDER": "Имя"
}
},
"ERROR": {
"TITLE": "Не удалось выполнить действие",
"DESCRIPTION": "Повторите попытку или убедитесь, что у вас есть доступ.",
"CLOSE": "Закрыть"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Фильтр задач не выбран"
}
},
"START_TASK": {
"DEFAULT_NAME": "Моя задача по умолчанию",
"BUTTON": "Создать задачу",
"FORM": {
"TITLE": "Начать задачу",
"LABEL": {
"NONE": "Нет",
"NAME": "Имя",
"DESCRIPTION": "Описание",
"ATTACHFORM": "Прикрепить форму",
"ASSIGNEE": "Исполнитель",
"FORM": "Форма",
"DATE": "Выбрать дату"
},
"ACTION": {
"START": "Начать",
"CANCEL": "Отмена"
},
"ERROR": {
"REQUIRED": "Обязательное поле",
"DATE": "Формат даты ДД.ММ.ГГГГ",
"MAXIMUM_LENGTH": "Превышение длины, макс. символов: {{characters}}",
"MESSAGE": "Введите другое значение"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Исполнитель",
"DIALOG_CLOSE": "Закрыть",
"ADD_USER": "Добавить",
"ADD_ASSIGNEE": "Назначить",
"SEARCH_USER": "Искать пользователя",
"SEARCH": {
"NO_USERS": "Участников не найдено"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Этот список пуст",
"DRAG-AND-DROP": {
"TITLE": "Перетащите",
"SUBTITLE": "для загрузки файлов"
}
},
"EMPTY-LIST": {
"HEADER": "Файлы отсутствуют"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Нет прикрепленных форм",
"COMPLETE_TASK_MESSAGE": "Задача {{taskName}} выполнена",
"COMPLETE_TASK_SUB_MESSAGE": "Нет форм для добавления"
},
"ATTACH_FORM": {
"SELECT_FORM": "Выбрать форму для прикрепления",
"REMOVE_FORM": "Удалить форму",
"SELECT_OPTION": "Выбрать параметр"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Процессы не найдены",
"SUBTITLE": "Создайте новый процесс, который вы сможете легко найти позже",
"SUMMARY": "Найдено экземпляров процесса: {{total}}",
"ERROR": "Не удалось загрузить экземпляры процессов. Повторите попытку или покажите IT-специалистам следующее сообщение: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Фильтр экземпляров процессов не найден."
}
},
"PROPERTIES": {
"PROCESS_NAME": "Процесс",
"NAME": "Имя",
"THUMBNAIL": "Эскиз",
"STATUS": "Статус",
"END_DATE": "Дата окончания",
"END_DATE_DEFAULT": "Нет срока",
"CATEGORY": "Категория",
"CATEGORY_DEFAULT": "Нет категории",
"CREATED_BY": "Создано пользователем",
"CREATED_BY_DEFAULT": "Нет исполнителя",
"CREATED": "Создано",
"BUSINESS_KEY": "Бизнес-ключ",
"BUSINESS_KEY_DEFAULT": "Нет",
"DESCRIPTION": "Описание",
"DESCRIPTION_DEFAULT": "Нет описания",
"ID": "Идентификатор"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Посмотреть",
"REMOVE_CONTENT": "Удалить",
"DOWNLOAD_CONTENT": "Скачать",
"DOWNLOAD_AUDIT": "Скачать аудит",
"VIEW_TASK": "Просмотреть задачу"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Запущено пользователем",
"STARTED": "Запущено",
"ENDED": "Завершено",
"COMMENTS": "Комментарии",
"START_FORM": "Запустить форму",
"TASKS_ACTIVE": "Активные задачи",
"TASKS_COMPLETED": "Завершенные задачи",
"TASK_SUBTITLE": "Назначено пользователю {{user}}, создано {{created}}"
},
"BUTTON": {
"CANCEL": "Отменить процесс",
"CLOSE": "Закрыть",
"SHOW_DIAGRAM": "Показать схему",
"DRAG-ATTACHMENT": "Перетащите файлы для загрузки",
"UPLOAD-ATTACHMENT": "Загрузить вложение"
},
"MESSAGES": {
"NONE": "Сведения о процессе не найдены"
},
"TASKS": {
"NO_ACTIVE": "Активные задачи в настоящее время отсутствуют",
"NO_COMPLETED": "Выполненные задачи пока отсутствуют",
"TASK_DETAILS": "Сведения о задаче",
"TASK_CLOSE": "Закрыть"
},
"COMMENTS": {
"ADD": "Добавить комментарий",
"HEADER": "Комментарии ({{ count }})",
"NONE": "Нет комментариев",
"BUTTON": {
"ADD": "Добавить комментарий"
},
"ADD_DIALOG": {
"TITLE": "Новый комментарий",
"LABEL": {
"MESSAGE": "Сообщение"
},
"BUTTON": {
"ADD": "Добавить комментарий",
"CANCEL": "Отмена"
}
}
},
"ADD_DIALOG": {
"TITLE": "Установить переменную процесса",
"LABEL": {
"NAME": "Имя",
"VALUE": "Значение",
"SCOPE": "Область применения"
}
},
"EDIT_DIALOG": {
"TITLE": "Редактировать переменную процесса"
},
"ERROR_DIALOG": {
"TITLE": "Не удалось выполнить действие",
"DESCRIPTION": "Возможно, у вас нет необходимого уровня доступа, обратитесь к IT-специалистам."
}
},
"START_PROCESS": {
"BUTTON": "Начать процесс",
"NO_PROCESS_DEFINITIONS": "Невозможно начать процесс, поскольку нет определений процесса",
"FORM": {
"TITLE": "Начать процесс",
"LABEL": {
"TYPE": "Выбрать процесс",
"NAME": "Имя процесса"
},
"TYPE_PLACEHOLDER": "Выбрать элемент...",
"ACTION": {
"START": "Начать процесс",
"CANCEL": "Отмена"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Не удалось загрузить определения процесса, проверьте, есть ли у вас доступ.",
"START": "Не удалось начать новый экземпляр процесса, проверьте, есть ли у вас доступ.",
"MAXIMUM_LENGTH": "Превышение длины, макс. символов: {{characters}}"
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Этот список пуст",
"DRAG-AND-DROP": {
"TITLE": "Перетащите",
"SUBTITLE": "для загрузки файлов"
}
},
"EMPTY-LIST": {
"HEADER": "Файлы отсутствуют"
},
"COLUMNS": {
"NAME": "Имя",
"CREATED-ON": "Дата создания"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Создать",
"NEW_TASK": "Новая задача",
"NEW_PROCESS": "Новый процесс"
}
},
"APP": {
"DIALOG": {
"START": "Продолжить",
"TITLE": "Выбрать приложение",
"LIST": "Список приложений",
"ERROR": "Возникла проблема при подключении к Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Войти",
"CANCEL": "Отмена",
"CHOOSE": "Выбрать"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "Klicka på Spara för att lägga till en rapport med aktuella inställningar till din rapportlista.",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "Startdatum",
"END-DATE": "Slutdatum",
"MESSAGES": {
"START-DATE-REQUIRED": "Startdatum krävs",
"START-LESS-THAN-END-DATE": "Startdatum måste ligga innan slutdatum"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "Inga program hittades",
"SUBTITLE": "Skapa ett nytt program som du enkelt hittar senare",
"TASK_APP_NAME": "Uppgiftsapp"
},
"LIST": {
"MESSAGES": {
"TITLE": "Inga uppgifter hittades",
"SUBTITLE": "Skapa en ny uppgift som du enkelt hittar senare",
"NONE": "Inga uppgiftslistor hittades"
}
},
"PROPERTIES": {
"TASK_NAME": "Uppgift",
"THUMBNAIL": "Miniatyrbild",
"DURATION": "Varaktighet",
"PARENT_TASK_ID": "Överordnad uppgift ID",
"NAME": "Namn",
"ASSIGNEE": "Tilldelad användare",
"ASSIGNEE_DEFAULT": "Ingen tilldelad användare",
"PRIORITY": "Prioritet",
"DUE_DATE": "Förfallodatum",
"DUE_DATE_DEFAULT": "Inget datum",
"STATUS": "Status",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"PARENT_NAME": "Överordnad namn",
"PARENT_NAME_DEFAULT": "Ingen överordnad",
"CREATED_BY": "Skapad av",
"CREATED": "Skapad",
"END_DATE": "Slutdatum",
"ID": "ID",
"DESCRIPTION": "Beskrivning",
"DESCRIPTION_DEFAULT": "Ingen beskrivning",
"FORM_NAME": "Formulärnamn",
"FORM_NAME_DEFAULT": "Inget formulär"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visa",
"REMOVE_CONTENT": "Ta bort",
"DOWNLOAD_CONTENT": "Ladda ner",
"DOWNLOAD_AUDIT": "Ladda ner granskning"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "Aktiviteter",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "Aktivitet",
"INFO_DRAWER_TAB_DETAILS_TITLE": "Detaljer",
"ASSIGNEE": "Tilldelad användare",
"DUE": "Förfaller",
"FORM": "Formulär",
"PEOPLE": "Personer den här uppgiften delas med",
"COMMENTS": "Kommentarer",
"CHECKLIST": "Checklista",
"INVOLVED_PEOPLE": "Personer involverade",
"ADD_PEOPLE": "Lägg till personer och grupper",
"ADD_ASSIGNEE": "Lägg till ny tilldelad användare"
},
"BUTTON": {
"COMPLETE": "Slutför",
"CLAIM": "Anta",
"UNCLAIM": "Avsäga",
"DRAG-ATTACHMENT": "Släpp filer att ladda upp",
"UPLOAD-ATTACHMENT": "Ladda upp bilaga"
},
"MESSAGES": {
"NONE": "Inga uppgiftsdetaljer hittades",
"CLAIM": "Klicka på Anta för att arbeta på den här uppgiften"
},
"FORM": {
"NONE": "Inget formulär"
},
"DUE": {
"NONE": "Inget förfallodatum"
},
"ASSIGNEE": {
"NONE": "Ingen tilldelad användare"
},
"PEOPLE": {
"NONE": "Ingen inbjuden"
},
"CHECKLIST": {
"NONE": "Ingen checklista",
"DIALOG": {
"TITLE": "Ny kontroll",
"CANCEL-BUTTON": "Avbryt",
"ADD-BUTTON": "Lägg till checklista",
"PLACEHOLDER": "Namn"
}
},
"ERROR": {
"TITLE": "Kunde inte slutföra åtgärden",
"DESCRIPTION": "Försök igen eller kontrolla att du har åtkomst.",
"CLOSE": "Stäng"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "Inget uppgiftsfilter valt"
}
},
"START_TASK": {
"DEFAULT_NAME": "Min standarduppgift",
"BUTTON": "Skapa uppgfit",
"FORM": {
"TITLE": "Starta uppgift",
"LABEL": {
"NONE": "Ingen",
"NAME": "Namn",
"DESCRIPTION": "Beskrivning",
"ATTACHFORM": "Bifoga formulär",
"ASSIGNEE": "Tilldelad användare",
"FORM": "Formulär",
"DATE": "Välj datum"
},
"ACTION": {
"START": "Starta",
"CANCEL": "Avbryt"
},
"ERROR": {
"REQUIRED": "Fält obligatoriskt",
"DATE": "Datumformat DD/MM/ÅÅÅÅ",
"MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max.",
"MESSAGE": "Ange ett annat värde"
}
}
},
"PEOPLE": {
"ASSIGNEE": "Tilldelad användare",
"DIALOG_CLOSE": "Stäng",
"ADD_USER": "Lägg till",
"ADD_ASSIGNEE": "Tilldela",
"SEARCH_USER": "Sök användare",
"SEARCH": {
"NO_USERS": "Hittade ingen att involvera"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "Den här listan är tom",
"DRAG-AND-DROP": {
"TITLE": "Dra och släpp",
"SUBTITLE": "för att ladda upp filer"
}
},
"EMPTY-LIST": {
"HEADER": "Inga filer är tillgängliga"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "Inga formulär bifogade",
"COMPLETE_TASK_MESSAGE": "Uppgift {{taskName}} slutförd",
"COMPLETE_TASK_SUB_MESSAGE": "Inga formulär ska läggas till"
},
"ATTACH_FORM": {
"SELECT_FORM": "Välj formulär att bifoga",
"REMOVE_FORM": "Ta bort formulär",
"SELECT_OPTION": "Välj ett alternativ"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "Inga processer hittades",
"SUBTITLE": "Skapa en ny proces som du enkelt hittar senare",
"SUMMARY": "{{total}} processinstanser hittades",
"ERROR": "Kunde inte läsa in processinstanser. Försök igen eller dela följande meddelande med din IT-avdelning: {{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "Inget processinstansfilter valt"
}
},
"PROPERTIES": {
"PROCESS_NAME": "Process",
"NAME": "Namn",
"THUMBNAIL": "Miniatyrbild",
"STATUS": "Status",
"END_DATE": "Slutdatum",
"END_DATE_DEFAULT": "Inget datum",
"CATEGORY": "Kategori",
"CATEGORY_DEFAULT": "Ingen kategori",
"CREATED_BY": "Skapad av",
"CREATED_BY_DEFAULT": "Ingen tilldelad användare",
"CREATED": "Skapad",
"BUSINESS_KEY": "Affärsnyckel",
"BUSINESS_KEY_DEFAULT": "Ingen",
"DESCRIPTION": "Beskrivning",
"DESCRIPTION_DEFAULT": "Ingen beskrivning",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "Visa",
"REMOVE_CONTENT": "Ta bort",
"DOWNLOAD_CONTENT": "Ladda ner",
"DOWNLOAD_AUDIT": "Ladda ner granskning",
"VIEW_TASK": "Visa uppgift"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "Startad av",
"STARTED": "Startade",
"ENDED": "Avslutade",
"COMMENTS": "Kommentarer",
"START_FORM": "Startformulär",
"TASKS_ACTIVE": "Aktiva uppgifter",
"TASKS_COMPLETED": "Slutförda uppgifter",
"TASK_SUBTITLE": "Tilldelad till {{user}}, skapad {{created}}"
},
"BUTTON": {
"CANCEL": "Avbryt processen",
"CLOSE": "Stäng",
"SHOW_DIAGRAM": "Visa diagram",
"DRAG-ATTACHMENT": "Släpp filer att ladda upp",
"UPLOAD-ATTACHMENT": "Ladda upp bilaga"
},
"MESSAGES": {
"NONE": "Inga processdetaljer hittades"
},
"TASKS": {
"NO_ACTIVE": "Inga aktiva uppgifter för närvarande",
"NO_COMPLETED": "Inga uppgifter slutförda än",
"TASK_DETAILS": "Uppgiftsdetaljer",
"TASK_CLOSE": "Stäng"
},
"COMMENTS": {
"ADD": "Lägg till en kommentar",
"HEADER": "Kommentarer ({{ count }})",
"NONE": "Inga kommentarer",
"BUTTON": {
"ADD": "Lägg till en kommentar"
},
"ADD_DIALOG": {
"TITLE": "Ny kommentar",
"LABEL": {
"MESSAGE": "Meddelande"
},
"BUTTON": {
"ADD": "Lägg till kommentar",
"CANCEL": "Avbryt"
}
}
},
"ADD_DIALOG": {
"TITLE": "Ställ in processvariabel",
"LABEL": {
"NAME": "Namn",
"VALUE": "Värde",
"SCOPE": "Definitionsområde"
}
},
"EDIT_DIALOG": {
"TITLE": "Redigera processvariabel"
},
"ERROR_DIALOG": {
"TITLE": "Kunde inte slutföra åtgärden",
"DESCRIPTION": "Du kanske inte har den åtkomstnivå som krävs, kolla med din IT-avdelning."
}
},
"START_PROCESS": {
"BUTTON": "Starta process",
"NO_PROCESS_DEFINITIONS": "Du kan inte starta en process eftersom inga processdefinitioner är tillgängliga",
"FORM": {
"TITLE": "Starta process",
"LABEL": {
"TYPE": "Välj process",
"NAME": "Processnamn"
},
"TYPE_PLACEHOLDER": "Välj en...",
"ACTION": {
"START": "Starta process",
"CANCEL": "Avbryt"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "Kunde inte läsa in processdefinitioner, kontrollera att du har åtkomst.",
"START": "Kunde inte starta ny processinstans, kontrollera att du har åtkomst.",
"MAXIMUM_LENGTH": "Längd överskriden, {{characters}} tecken max."
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "Den här listan är tom",
"DRAG-AND-DROP": {
"TITLE": "Dra och släpp",
"SUBTITLE": "för att ladda upp filer"
}
},
"EMPTY-LIST": {
"HEADER": "Inga filer är tillgängliga"
},
"COLUMNS": {
"NAME": "Namn",
"CREATED-ON": "Skapad den"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "Skapa",
"NEW_TASK": "Ny uppgift",
"NEW_PROCESS": "Ny process"
}
},
"APP": {
"DIALOG": {
"START": "Fortsätt",
"TITLE": "Välj ett processprogram",
"LIST": "Lista över processprogram",
"ERROR": "Det är problem med att ansluta till Process Services"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "Inloggning",
"CANCEL": "Avbryt",
"CHOOSE": "Välj"
}
}
}

View File

@@ -0,0 +1,333 @@
{
"DIALOG": {
"SAVE_MESSAGE": "单击保存以用当前设置将报告添加至报告列表。",
"EXPORT_MESSAGE": ""
},
"DATE-WIDGET": {
"START-DATE": "启动日期",
"END-DATE": "结束日期",
"MESSAGES": {
"START-DATE-REQUIRED": "需要启动日期",
"START-LESS-THAN-END-DATE": "启动日期必须在结束日期前"
}
},
"ADF_TASK_LIST": {
"APPS": {
"TITLE": "找不到应用程序",
"SUBTITLE": "创建您想要今后轻松查找的新应用程序",
"TASK_APP_NAME": "任务 App"
},
"LIST": {
"MESSAGES": {
"TITLE": "找不到任务",
"SUBTITLE": "创建您希望稍后轻松找到的新任务",
"NONE": "未找到任务列表"
}
},
"PROPERTIES": {
"TASK_NAME": "任务",
"THUMBNAIL": "缩略图",
"DURATION": "持续时间",
"PARENT_TASK_ID": "父任务 ID",
"NAME": "名称",
"ASSIGNEE": "被指派者",
"ASSIGNEE_DEFAULT": "没有被分派人",
"PRIORITY": "优先级",
"DUE_DATE": "截止日期",
"DUE_DATE_DEFAULT": "没有日期",
"STATUS": "状态",
"CATEGORY": "类别",
"CATEGORY_DEFAULT": "没有类别",
"PARENT_NAME": "父类别名称",
"PARENT_NAME_DEFAULT": "没有父类别",
"CREATED_BY": "创建者",
"CREATED": "已创建",
"END_DATE": "结束日期",
"ID": "ID",
"DESCRIPTION": "说明",
"DESCRIPTION_DEFAULT": "没有描述",
"FORM_NAME": "表单名称",
"FORM_NAME_DEFAULT": "无表单"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "查看",
"REMOVE_CONTENT": "删除",
"DOWNLOAD_CONTENT": "下载",
"DOWNLOAD_AUDIT": "下载审计"
},
"DETAILS": {
"LABELS": {
"INFO_DRAWER_TITLE": "活动",
"INFO_DRAWER_TAB_ACTIVITY_TITLE": "活动",
"INFO_DRAWER_TAB_DETAILS_TITLE": "详细信息",
"ASSIGNEE": "被指派者",
"DUE": "截止时间",
"FORM": "表单",
"PEOPLE": "与其共享该任务的人员",
"COMMENTS": "注释",
"CHECKLIST": "检查表",
"INVOLVED_PEOPLE": "涉及人员",
"ADD_PEOPLE": "添加人员和组",
"ADD_ASSIGNEE": "新增被分派人"
},
"BUTTON": {
"COMPLETE": "完成",
"CLAIM": "申领",
"UNCLAIM": "释放",
"DRAG-ATTACHMENT": "放置文件以上传",
"UPLOAD-ATTACHMENT": "上传附件"
},
"MESSAGES": {
"NONE": "未找到任务详情",
"CLAIM": "单击“申领”以处理此任务"
},
"FORM": {
"NONE": "无表单"
},
"DUE": {
"NONE": "无截止日期"
},
"ASSIGNEE": {
"NONE": "没有被分派人"
},
"PEOPLE": {
"NONE": "未包含任何人"
},
"CHECKLIST": {
"NONE": "没有检查表",
"DIALOG": {
"TITLE": "新建勾选项",
"CANCEL-BUTTON": "取消",
"ADD-BUTTON": "添加核对清单",
"PLACEHOLDER": "名称"
}
},
"ERROR": {
"TITLE": "无法完成该操作",
"DESCRIPTION": "重试或检查您是否有访问权限。",
"CLOSE": "关闭"
}
},
"FILTERS": {
"MESSAGES": {
"NONE": "未选择任务筛选器"
}
},
"START_TASK": {
"DEFAULT_NAME": "我的默认任务",
"BUTTON": "创建任务",
"FORM": {
"TITLE": "启动任务",
"LABEL": {
"NONE": "无",
"NAME": "名称",
"DESCRIPTION": "说明",
"ATTACHFORM": "附加表单",
"ASSIGNEE": "被指派者",
"FORM": "表单",
"DATE": "选择日期"
},
"ACTION": {
"START": "开始",
"CANCEL": "取消"
},
"ERROR": {
"REQUIRED": "必填字段",
"DATE": "日期格式 (YYYY/MM/DD)",
"MAXIMUM_LENGTH": "超出长度,最多 {{characters}} 字符",
"MESSAGE": "使用其他值"
}
}
},
"PEOPLE": {
"ASSIGNEE": "被指派者",
"DIALOG_CLOSE": "关闭",
"ADD_USER": "添加",
"ADD_ASSIGNEE": "指派",
"SEARCH_USER": "搜索用户",
"SEARCH": {
"NO_USERS": "未找到涉及的人员"
}
},
"ATTACHMENT": {
"EMPTY": {
"HEADER": "此列表为空",
"DRAG-AND-DROP": {
"TITLE": "拖放",
"SUBTITLE": "要上传文件"
}
},
"EMPTY-LIST": {
"HEADER": "没有可用的文件"
}
},
"STANDALONE_TASK": {
"NO_FORM_MESSAGE": "未附加表单",
"COMPLETE_TASK_MESSAGE": "已完成任务 {{taskName}}",
"COMPLETE_TASK_SUB_MESSAGE": "没有要添加的表单"
},
"ATTACH_FORM": {
"SELECT_FORM": "选择要附加的表单",
"REMOVE_FORM": "删除表单",
"SELECT_OPTION": "选择选项"
}
},
"ADF_PROCESS_LIST": {
"LIST": {
"TITLE": "找不到进程",
"SUBTITLE": "创建您想要今后轻松查找的新进程",
"SUMMARY": "找到 {{total}} 个进程实例",
"ERROR": "无法加载进程实例。请重试,或将以下信息告知 IT 团队:{{errorMessage}}"
},
"FILTERS": {
"MESSAGES": {
"NONE": "未选择进程实例过滤器。"
}
},
"PROPERTIES": {
"PROCESS_NAME": "流程",
"NAME": "名称",
"THUMBNAIL": "缩略图",
"STATUS": "状态",
"END_DATE": "结束日期",
"END_DATE_DEFAULT": "没有日期",
"CATEGORY": "类别",
"CATEGORY_DEFAULT": "没有类别",
"CREATED_BY": "创建者",
"CREATED_BY_DEFAULT": "没有被分派人",
"CREATED": "已创建",
"BUSINESS_KEY": "商业 Key",
"BUSINESS_KEY_DEFAULT": "无",
"DESCRIPTION": "说明",
"DESCRIPTION_DEFAULT": "没有描述",
"ID": "ID"
},
"MENU_ACTIONS": {
"VIEW_CONTENT": "查看",
"REMOVE_CONTENT": "删除",
"DOWNLOAD_CONTENT": "下载",
"DOWNLOAD_AUDIT": "下载审计",
"VIEW_TASK": "查看任务"
},
"DETAILS": {
"LABELS": {
"STARTED_BY": "启动者",
"STARTED": "已启动",
"ENDED": "已结束",
"COMMENTS": "注释",
"START_FORM": "启动表单",
"TASKS_ACTIVE": "活动的任务",
"TASKS_COMPLETED": "完成的任务",
"TASK_SUBTITLE": "分配给 {{user}},已创建 {{created}}"
},
"BUTTON": {
"CANCEL": "取消流程",
"CLOSE": "关闭",
"SHOW_DIAGRAM": "显示流程图",
"DRAG-ATTACHMENT": "放置文件以上传",
"UPLOAD-ATTACHMENT": "上传附件"
},
"MESSAGES": {
"NONE": "未找到流程详情"
},
"TASKS": {
"NO_ACTIVE": "没有当前处于活动状态的任务",
"NO_COMPLETED": "尚未完成任何任务",
"TASK_DETAILS": "任务详细信息",
"TASK_CLOSE": "关闭"
},
"COMMENTS": {
"ADD": "添加注释",
"HEADER": "评论 ({{ count }})",
"NONE": "无注释",
"BUTTON": {
"ADD": "添加注释"
},
"ADD_DIALOG": {
"TITLE": "新增评论",
"LABEL": {
"MESSAGE": "消息"
},
"BUTTON": {
"ADD": "添加注释",
"CANCEL": "取消"
}
}
},
"ADD_DIALOG": {
"TITLE": "设置流程变量",
"LABEL": {
"NAME": "名称",
"VALUE": "值",
"SCOPE": "范围"
}
},
"EDIT_DIALOG": {
"TITLE": "编辑流程变量"
},
"ERROR_DIALOG": {
"TITLE": "无法完成该操作",
"DESCRIPTION": "您可能没有要求的访问权限级别,请与 IT 团队确认。"
}
},
"START_PROCESS": {
"BUTTON": "启动流程",
"NO_PROCESS_DEFINITIONS": "无法启动流程,因为没有可用的流程定义",
"FORM": {
"TITLE": "启动流程",
"LABEL": {
"TYPE": "选择流程",
"NAME": "流程名称"
},
"TYPE_PLACEHOLDER": "选择一个...",
"ACTION": {
"START": "启动流程",
"CANCEL": "取消"
}
},
"ERROR": {
"LOAD_PROCESS_DEFS": "无法加载流程定义,请确定您是否有访问权限。",
"START": "无法启动新流程实例,请确定您是否有访问权限。",
"MAXIMUM_LENGTH": "超出长度,最多 {{characters}} 字符"
}
},
"PROCESS-ATTACHMENT": {
"EMPTY": {
"HEADER": "此列表为空",
"DRAG-AND-DROP": {
"TITLE": "拖放",
"SUBTITLE": "要上传文件"
}
},
"EMPTY-LIST": {
"HEADER": "没有可用的文件"
},
"COLUMNS": {
"NAME": "名称",
"CREATED-ON": "创建日期"
}
}
},
"ADF_SIDEBAR_ACTION_MENU": {
"BUTTON": {
"CREATE": "创建",
"NEW_TASK": "新任务",
"NEW_PROCESS": "新建流程"
}
},
"APP": {
"DIALOG": {
"START": "继续",
"TITLE": "选择一个流程App",
"LIST": "流程App列表",
"ERROR": "连接到 Process Services 时出现问题"
}
},
"ATTACH-FILE": {
"ACTIONS": {
"LOGIN": "登录",
"CANCEL": "取消",
"CHOOSE": "选择"
}
}
}

View File

@@ -0,0 +1,44 @@
/*!
* @license
* Copyright 2019 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 { NgModule } from '@angular/core';
import {
MAT_LABEL_GLOBAL_OPTIONS, MatAutocompleteModule, MatButtonModule, MatCardModule, MatCheckboxModule,
MatChipsModule, MatDatepickerModule, MatDialogModule, MatGridListModule, MatIconModule,
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
MatTooltipModule, MatMenuModule
} from '@angular/material';
export function modules() {
return [
MatAutocompleteModule, MatButtonModule, MatCardModule, MatDialogModule,
MatCheckboxModule, MatDatepickerModule, MatGridListModule, MatIconModule, MatInputModule,
MatListModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatTableModule,
MatTabsModule, MatProgressSpinnerModule, MatNativeDateModule, MatRippleModule, MatTooltipModule,
MatChipsModule, MatMenuModule
];
}
@NgModule({
providers: [
{provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: { float: 'never' }}
],
imports: modules(),
exports: modules()
})
export class MaterialModule {}

View File

@@ -0,0 +1,79 @@
/*!
* @license
* Copyright 2019 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 { AppDefinitionRepresentationModel } from '../task-list';
export let nonDeployedApps = [new AppDefinitionRepresentationModel({
id: '1',
name: '1',
icon: 'icon1'
}), new AppDefinitionRepresentationModel({
id: '1',
name: '2',
icon: 'icon2'
}), new AppDefinitionRepresentationModel({
id: '1',
name: '3',
icon: 'icon3'
})];
export let deployedApps = [new AppDefinitionRepresentationModel({
id: 1,
name: 'App1',
icon: 'icon1',
deploymentId: '1',
defaultAppId: 'fake-app-1',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 2,
name: 'App2',
icon: 'icon2',
deploymentId: '2',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 3,
name: 'App3',
icon: 'icon3',
deploymentId: '3',
modelId: null,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 4,
name: 'App4',
icon: 'icon4',
deploymentId: '4',
modelId: 65,
tenantId: null
}), new AppDefinitionRepresentationModel({
id: 5,
name: 'App5',
icon: 'icon5',
deploymentId: '5',
modelId: 66,
tenantId: 9
}), new AppDefinitionRepresentationModel({
id: 6,
name: 'App6',
icon: 'icon6',
deploymentId: '6',
tenantId: 9,
modelId: 66
})];
export let defaultApp = [new AppDefinitionRepresentationModel({
defaultAppId: 'tasks'
})];

View File

@@ -0,0 +1,18 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './public-api';

View File

@@ -0,0 +1,22 @@
/*!
* @license
* Copyright 2019 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.
*/
export let mockProcessInstanceComments = [
{ message: 'Test1', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} },
{ message: 'Test2', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} },
{ message: 'Test3', created: Date.now(), createdBy: {firstName: 'Admin', lastName: 'User'} }
];

View File

@@ -0,0 +1,150 @@
/*!
* @license
* Copyright 2019 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 { ObjectDataColumn } from '@alfresco/adf-core';
export let fakeProcessInstance = {
size: 2,
total: 2,
start: 0,
data: [
{
id: '1',
name: 'Process 773443333',
businessKey: null,
processDefinitionId: 'fakeprocess:5:7507',
tenantId: 'tenant_1',
started: '2015-11-09T12:36:14.184+0000',
ended: null,
startedBy: {
id: 3,
firstName: 'tenant2',
lastName: 'tenantLastName',
email: 'tenant2@tenant'
},
processDefinitionName: 'Fake Process Name',
processDefinitionDescription: null,
processDefinitionKey: 'fakeprocess',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 1,
processDefinitionDeploymentId: '2540',
graphicalNotationDefined: true,
startFormDefined: false,
suspended: false,
variables: []
},
{
id: '2',
name: 'Process 382927392',
businessKey: null,
processDefinitionId: 'fakeprocess:5:7507',
tenantId: 'tenant_1',
started: '2018-01-10T17:02:22.597+0000',
ended: null,
startedBy: {
id: 3,
firstName: 'tenant2',
lastName: 'tenantLastName',
email: 'tenant2@tenant'
},
processDefinitionName: 'Fake Process Name',
processDefinitionDescription: null,
processDefinitionKey: 'fakeprocess',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 1,
processDefinitionDeploymentId: '2540',
graphicalNotationDefined: true,
startFormDefined: false,
suspended: false,
variables: []
}
]
};
export let fakeProcessInstancesWithNoName = {
size: 2,
total: 2,
start: 0,
data: [
{
id: '1',
name: null,
processDefinitionId: 'fakeprocess:5:7507',
processDefinitionKey: 'fakeprocess',
processDefinitionName: 'Fake Process Name',
description: null,
category: null,
started: '2017-11-09T12:36:14.184+0000',
startedBy: {
id: 3,
firstName: 'tenant2',
lastName: 'tenantLastName',
email: 'tenant2@tenant'
}
},
{
id: 2,
name: '',
processDefinitionId: 'fakeprocess:5:7507',
processDefinitionKey: 'fakeprocess',
processDefinitionName: 'Fake Process Name',
description: null,
category: null,
started: '2017-11-09T12:37:25.184+0000',
startedBy: {
id: 3,
firstName: 'tenant2',
lastName: 'tenantLastName',
email: 'tenant2@tenant'
}
}
]
};
export let fakeProcessInstancesEmpty = {
size: 0,
total: 0,
start: 0,
data: []
};
export let fakeProcessCustomSchema = [
new ObjectDataColumn({
key: 'fakeName',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.FAKE',
sortable: true
}),
new ObjectDataColumn({
key: 'fakeProcessName',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.PROCESS_FAKE',
sortable: true
})
];
export let fakeProcessColumnSchema = {
default: [
{
key: 'name',
type: 'text',
title: 'ADF_PROCESS_LIST.PROPERTIES.NAME',
sortable: true
}
],
fakeProcessCustomSchema
};

View File

@@ -0,0 +1,175 @@
/*!
* @license
* Copyright 2019 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.
*/
/* spell-checker: disable */
import { ProcessInstance } from '../../process-list/models/process-instance.model';
export class ProcessList {
data: ProcessInstance[];
size: number;
start: number;
total: number;
constructor(data?: ProcessInstance[]) {
this.data = data || [];
}
}
export class SingleProcessList extends ProcessList {
constructor(name?: string) {
const instance = new ProcessInstance({
id: '123',
name: name
});
super([instance]);
}
}
export let exampleProcess = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
startedBy: {
id: 1001,
firstName: 'Bob',
lastName: 'Jones',
email: 'bob@app.activiti.com'
}
});
export let processEnded = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
startedBy: {
id: 1001,
firstName: 'Bob',
lastName: 'Jones',
email: 'bob@app.activiti.com'
},
ended: '2016-11-11T03:37:30.010+0000'
});
export let mockRunningProcess = new ProcessInstance({
id: '123',
name: 'Process 123',
started: '2016-11-10T03:37:30.010+0000',
startedBy: {
id: 1001,
firstName: 'Bob',
lastName: 'Jones',
email: 'bob@app.activiti.com'
},
ended: null
});
export let exampleProcessNoName = new ProcessInstance({
id: '123',
name: null,
started: '2016-11-10T03:37:30.010+0000',
startedBy: {
id: 1001,
firstName: 'Bob',
lastName: 'Jones',
email: 'bob@app.activiti.com'
},
processDefinitionName: 'My Process'
});
export let fakeProcessInstances = {
size: 2,
total: 2,
start: 0,
data: [
{
id: '340124',
name: 'James Franklin EMEA Onboarding',
businessKey: null,
processDefinitionId: 'HROnboarding:60:338704',
tenantId: 'tenant_1',
started: new Date('2017-10-09T12:19:44.560+0000'),
ended: null,
startedBy: {
id: 4004,
firstName: 'Integration',
lastName: 'Test',
email: 'srintegrationtest@test.com'
},
processDefinitionName: 'HROnboarding',
processDefinitionDescription: 'HR Onboarding Workflow',
processDefinitionKey: 'fakeProcessDefinitionKey1',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 60,
processDefinitionDeploymentId: '338695',
graphicalNotationDefined: true,
startFormDefined: false,
suspended: false,
variables: []
},
{
id: '340063',
name: 'Mary Franklin AMERICAS Onboarding',
businessKey: null,
processDefinitionId: 'HROnboarding:60:338704',
tenantId: 'tenant_1',
started: '2017-10-09T12:18:07.484+0000',
ended: null,
startedBy: {
id: 4004,
firstName: 'Integration',
lastName: 'Test',
email: 'srintegrationtest@test.com'
},
processDefinitionName: 'HROnboarding',
processDefinitionDescription: 'HR Onboarding Workflow',
processDefinitionKey: 'HROnboarding',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 60,
processDefinitionDeploymentId: '338695',
graphicalNotationDefined: true,
startFormDefined: false,
suspended: false,
variables: []
},
{
id: '337604',
name: 'John Jacobs AMERICAS Onboarding',
businessKey: null,
processDefinitionId: 'HROnboarding:49:303243',
tenantId: 'tenant_1',
started: '2017-09-25T10:02:23.522+0000',
ended: null,
startedBy: {
id: 4004,
firstName: 'Integration',
lastName: 'Test',
email: 'srintegrationtest@test.com'
},
processDefinitionName: 'HROnboarding',
processDefinitionDescription: 'HR Onboarding Workflow',
processDefinitionKey: 'fakeProcessDefinitionKey2',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 49,
processDefinitionDeploymentId: '303234',
graphicalNotationDefined: true,
startFormDefined: false,
suspended: false,
variables: []
}
]
};

View File

@@ -0,0 +1,82 @@
/*!
* @license
* Copyright 2019 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 { AppDefinitionRepresentationModel, TaskDetailsModel } from '../../task-list';
import { FilterProcessRepresentationModel } from '../../process-list/models/filter-process.model';
import { ProcessDefinitionRepresentation } from '../../process-list/models/process-definition.model';
export let fakeProcessFilters = {
size: 1, total: 1, start: 0,
data: [new FilterProcessRepresentationModel({
'name': 'Running',
'appId': '22',
'id': 333,
'recent': true,
'icon': 'glyphicon-random',
'filter': { 'sort': 'created-desc', 'name': '', 'state': 'running' }
})]
};
export let fakeEmptyFilters = {
size: 0, total: 0, start: 0,
data: []
};
export let mockError = {
message: null,
messageKey: 'GENERAL.ERROR.FORBIDDEN'
};
export let fakeApp1 = new AppDefinitionRepresentationModel({
deploymentId: 26,
name: 'HR processes',
icon: 'glyphicon-cloud',
description: null,
theme: 'theme-6',
modelId: 4,
id: 1
});
export let fakeApp2 = new AppDefinitionRepresentationModel({
deploymentId: 2501,
name: 'Sales onboarding',
icon: 'glyphicon-asterisk',
description: null,
theme: 'theme-1',
modelId: 1002,
id: 1000
});
export let fakeTasksList = {
data: [new TaskDetailsModel({
id: 1,
name: 'Task 1',
processInstanceId: 1000,
created: '2016-11-10T03:37:30.010+0000'
}), new TaskDetailsModel({
id: 2,
name: 'Task 2',
processInstanceId: 1000,
created: '2016-11-10T03:37:30.010+0000'
})]
};
export let fakeProcessDef = new ProcessDefinitionRepresentation({
id: '32323',
key: 'blah',
name: 'Process 1'
});

View File

@@ -0,0 +1,52 @@
/*!
* @license
* Copyright 2019 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 { ProcessDefinitionRepresentation } from '../../process-list/models/process-definition.model';
import { ProcessInstance } from '../../process-list/models/process-instance.model';
export let newProcess = new ProcessInstance({
id: '32323',
name: 'Process'
});
export let testProcessDef = new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
});
export let testProcessDefinitions = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
})];
export let testMultipleProcessDefs = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: false
}), new ProcessDefinitionRepresentation({
id: 'my:process2',
name: 'My Process 2',
hasStartForm: false
})];
export let testProcessDefWithForm = [new ProcessDefinitionRepresentation({
id: 'my:process1',
name: 'My Process 1',
hasStartForm: true
})];

View File

@@ -0,0 +1,28 @@
/*!
* @license
* Copyright 2019 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.
*/
export * from './process/process-instances-list.mock';
export * from './process/process.service.mock';
export * from './process/start-process.component.mock';
export * from './process/process.model.mock';
export * from './process/process-comments.mock';
export * from './task/start-task.mock';
export * from './task/task-details.mock';
export * from './task/task-details.component.mock';
export * from './task/task-list.mock';
export * from './task/tasklist-service.mock';

View File

@@ -0,0 +1,34 @@
/*!
* @license
* Copyright 2019 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.
*/
export let startTaskMock = {
'name': 'fakeName',
'description': 'fakeDescription',
'assignee': null,
'dueDate': '2017-11-03T15:25:42.749+0000',
'formKey': null,
'category': 'fakeAppId'
};
//
// export let noDataMock = {
// 'name': '',
// 'description': '',
// 'assignee': {},
// 'dueDate': '',
// 'formKey': '',
// 'category': ';'
// };

View File

@@ -0,0 +1,20 @@
/*!
* @license
* Copyright 2019 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.
*/
export let mockTaskDetailsComponent = {
noTaskDetailsTemplateComponent: null
};

View File

@@ -0,0 +1,427 @@
/*!
* @license
* Copyright 2019 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 { TaskDetailsModel } from '../../task-list/models/task-details.model';
export let standaloneTaskWithForm = new TaskDetailsModel({
'id': '100',
'name': 'Standalone Task With Form',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': null,
'processDefinitionDeploymentId': null,
'formKey': '222',
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedGroups': [],
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
});
export let standaloneTaskWithoutForm = new TaskDetailsModel({
'id': '200',
'name': 'Standalone Task Without Form',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': null,
'processDefinitionName': null,
'processDefinitionDescription': null,
'processDefinitionKey': null,
'processDefinitionCategory': null,
'processDefinitionVersion': null,
'processDefinitionDeploymentId': null,
'formKey': null,
'processInstanceStartUserId': null,
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedGroups': [],
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
});
export let taskDetailsMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionDescription': null,
'processDefinitionKey': 'TranslationProcess',
'processDefinitionCategory': 'http://www.activiti.org/processdef',
'processDefinitionVersion': 2,
'processDefinitionDeploymentId': '5',
'formKey': '4',
'processInstanceStartUserId': '1001',
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedGroups': [],
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
});
export let taskDetailsWithOutAssigneeMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': undefined,
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionDescription': null,
'processDefinitionKey': 'TranslationProcess',
'processDefinitionCategory': 'http://www.activiti.org/processdef',
'processDefinitionVersion': 2,
'processDefinitionDeploymentId': '5',
'formKey': '4',
'processInstanceStartUserId': '1001',
'initiatorCanCompleteTask': false,
'adhocTaskCanBeReassigned': false,
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'executionId': '86',
'involvedGroups': [],
'involvedPeople': [],
'memberOfCandidateUsers': false,
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false
});
export let claimableTaskDetailsMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': null,
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'involvedGroups': [{ 'id': 7007, 'name': 'group1', 'externalId': null, 'status': 'active', 'groups': null },
{ 'id': 8008, 'name': 'group2', 'externalId': null, 'status': 'active', 'groups': null }],
'involvedPeople': [],
'managerOfCandidateGroup': true,
'memberOfCandidateGroup': true,
'memberOfCandidateUsers': false
});
export let claimedTaskDetailsMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'involvedGroups': [{ 'id': 7007, 'name': 'group1', 'externalId': null, 'status': 'active', 'groups': null }],
'involvedPeople': [{ 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
{ 'id': 111, 'firstName': 'fake-first-name', 'lastName': 'fake-last-name', 'email': 'fake@app.activiti.com' }],
'managerOfCandidateGroup': true,
'memberOfCandidateGroup': true,
'memberOfCandidateUsers': true
});
export let claimedByGroupMemberMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': {
'id': 111,
'firstName': 'fake-first-name',
'lastName': 'fake-last-name',
'email': 'fake@app.activiti.com'
},
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'involvedGroups': [{ 'id': 7007, 'name': 'group1', 'externalId': null, 'status': 'active', 'groups': null }],
'involvedPeople': [{ 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
{ 'id': 111, 'firstName': 'fake-first-name', 'lastName': 'fake-last-name', 'email': 'fake@app.activiti.com' }],
'managerOfCandidateGroup': true,
'memberOfCandidateGroup': true,
'memberOfCandidateUsers': true
});
export let taskDetailsWithOutCandidateGroup = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': null,
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': null,
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'managerOfCandidateGroup': false,
'memberOfCandidateGroup': false,
'memberOfCandidateUsers': false,
'involvedGroups': [],
'involvedPeople': [{ 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
{ 'id': 111, 'firstName': 'fake-first-name', 'lastName': 'fake-last-name', 'email': 'fake@app.activiti.com' }]
});
export let completedTaskDetailsMock = new TaskDetailsModel({
'id': '91',
'name': 'Request translation',
'description': null,
'category': null,
'assignee': { 'id': 1001, 'firstName': 'Wilbur', 'lastName': 'Adams', 'email': 'wilbur@app.activiti.com' },
'created': '2016-11-03T15:25:42.749+0000',
'dueDate': null,
'endDate': '2016-11-03T15:25:42.749+0000',
'duration': null,
'priority': 50,
'parentTaskId': null,
'parentTaskName': null,
'processInstanceId': '86',
'processInstanceName': null,
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'involvedGroups': [],
'involvedPeople': [],
'managerOfCandidateGroup': true,
'memberOfCandidateGroup': true,
'memberOfCandidateUsers': false
});
export let taskFormMock = new TaskDetailsModel({
'id': 4,
'name': 'Translation request',
'processDefinitionId': 'TranslationProcess:2:8',
'processDefinitionName': 'Translation Process',
'processDefinitionKey': 'TranslationProcess',
'taskId': '91',
'taskName': 'Request translation',
'taskDefinitionKey': 'sid-DDECD9E4-0299-433F-9193-C3D905C3EEBE',
'tabs': [],
'fields': [{
'fieldType': 'ContainerRepresentation',
'id': '1478093984155',
'name': 'Label',
'type': 'container',
'value': null,
'required': false,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': null,
'options': null,
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'dateDisplayFormat': null,
'layout': null,
'sizeX': 2,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'numberOfColumns': 2,
'fields': {
'1': [{
'fieldType': 'AttachFileFieldRepresentation',
'id': 'originalcontent',
'name': 'Original content',
'type': 'upload',
'value': [],
'required': true,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': null,
'options': null,
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'params': {},
'dateDisplayFormat': null,
'layout': { 'row': -1, 'column': -1, 'colspan': 1 },
'sizeX': 1,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'metaDataColumnDefinitions': []
}],
'2': [{
'fieldType': 'RestFieldRepresentation',
'id': 'language',
'name': 'Language',
'type': 'dropdown',
'value': 'Choose one...',
'required': true,
'readOnly': false,
'overrideId': false,
'colspan': 1,
'placeholder': null,
'minLength': 0,
'maxLength': 0,
'minValue': null,
'maxValue': null,
'regexPattern': null,
'optionType': null,
'hasEmptyValue': true,
'options': [{ 'id': 'empty', 'name': 'Choose one...' }, { 'id': 'fr', 'name': 'French' }, {
'id': 'de',
'name': 'German'
}, { 'id': 'es', 'name': 'Spanish' }],
'restUrl': null,
'restResponsePath': null,
'restIdProperty': null,
'restLabelProperty': null,
'tab': null,
'className': null,
'params': { 'existingColspan': 1, 'maxColspan': 1 },
'dateDisplayFormat': null,
'layout': { 'row': -1, 'column': -1, 'colspan': 1 },
'sizeX': 1,
'sizeY': 1,
'row': -1,
'col': -1,
'visibilityCondition': null,
'endpoint': null,
'requestHeaders': null
}]
}
}],
'outcomes': [],
'javascriptEvents': [],
'className': '',
'style': '',
'customFieldTemplates': {},
'metadata': {},
'variables': [],
'gridsterForm': false,
'globalDateFormat': 'D-M-YYYY'
});
export let tasksMock = [new TaskDetailsModel(taskDetailsMock)];
export let noDataMock = [new TaskDetailsModel({
'id': 1005,
'message': 'example-message',
'created': '2017-10-06T11:54:53.443+0000',
'createdBy': { 'id': 4004, 'firstName': 'gadget', 'lastName': 'inspector', 'email': 'gadget@inspector.com' }
})];

View File

@@ -0,0 +1,113 @@
/*!
* @license
* Copyright 2019 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 { ObjectDataColumn } from '@alfresco/adf-core';
export let fakeGlobalTask = {
size: 2,
start: 0,
total: 2,
data: [
{
id: 14,
name: 'nameFake1',
description: 'descriptionFake1',
category: 'categoryFake1',
assignee: {
id: 2,
firstName: 'firstNameFake1',
lastName: 'lastNameFake1',
email: 'emailFake1'
},
created: '2017-03-01T12:25:17.189+0000',
dueDate: '2017-04-02T12:25:17.189+0000',
endDate: '2017-05-03T12:25:31.129+0000',
duration: 13940,
priority: 50,
parentTaskId: 1,
parentTaskName: 'parentTaskNameFake',
processInstanceId: 2511,
processInstanceName: 'processInstanceNameFake',
processDefinitionId: 'myprocess:1:4',
processDefinitionName: 'processDefinitionNameFake',
processDefinitionDescription: 'processDefinitionDescriptionFake',
processDefinitionKey: 'myprocess',
processDefinitionCategory: 'http://www.activiti.org/processdef',
processDefinitionVersion: 1,
processDefinitionDeploymentId: '1',
formKey: 1,
processInstanceStartUserId: null,
initiatorCanCompleteTask: false,
adhocTaskCanBeReassigned: false,
taskDefinitionKey: 'sid-B6813AF5-8ACD-4481-A4D5-8BAAD1CB1416',
executionId: 2511,
memberOfCandidateGroup: false,
memberOfCandidateUsers: false,
managerOfCandidateGroup: false
},
{
id: 2,
name: '',
description: 'descriptionFake2',
category: null,
assignee: {
id: 1,
firstName: 'fistNameFake2',
lastName: 'Administrator2',
email: 'admin'
},
created: '2017-03-01T12:25:17.189+0000',
dueDate: '2017-04-02T12:25:17.189+0000',
endDate: null
}
]
};
export let fakeCustomSchema = [
new ObjectDataColumn({
key: 'fakeName',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.FAKE',
sortable: true
}),
new ObjectDataColumn({
key: 'fakeTaskName',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.TASK_FAKE',
sortable: true
})
];
export let fakeColumnSchema = {
default: [
{
key: 'name',
type: 'text',
title: 'ADF_TASK_LIST.PROPERTIES.NAME',
sortable: true
}
],
fakeCustomSchema
};
export let fakeEmptyTask = {
size: 0,
start: 0,
total: 0,
data: []
};

View File

@@ -0,0 +1,270 @@
/*!
* @license
* Copyright 2019 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 {
AppDefinitionRepresentationModel,
FilterRepresentationModel
} from '../../task-list/models/filter.model';
export let fakeFilters = {
size: 2, total: 2, start: 0,
data: [
new AppDefinitionRepresentationModel(
{
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved' }
}
),
{
id: 2, name: 'FakeMyTasks', recent: false, icon: 'glyphicon-align-left',
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-assignee' }
}
]
};
export let fakeAppFilter = {
size: 1, total: 1, start: 0,
data: [
{
id: 1, name: 'FakeInvolvedTasks', recent: false, icon: 'glyphicon-align-left',
filter: { sort: 'created-desc', name: '', state: 'open', assignment: 'fake-involved' }
}
]
};
export let fakeApps = {
size: 2, total: 2, start: 0,
data: [
{
id: 1, defaultAppId: null, name: 'Sales-Fakes-App', description: 'desc-fake1', modelId: 22,
theme: 'theme-1-fake', icon: 'glyphicon-asterisk', 'deploymentId': '111', 'tenantId': null
},
{
id: 2, defaultAppId: null, name: 'health-care-Fake', description: 'desc-fake2', modelId: 33,
theme: 'theme-2-fake', icon: 'glyphicon-asterisk', 'deploymentId': '444', 'tenantId': null
}
]
};
export let fakeFilter = {
sort: 'created-desc', text: '', state: 'open', assignment: 'fake-assignee'
};
export let fakeUser1 = { id: 1, email: 'fake-email@dom.com', firstName: 'firstName', lastName: 'lastName' };
export let fakeUser2 = { id: 1001, email: 'some-one@somegroup.com', firstName: 'some', lastName: 'one' };
export let fakeTaskList = {
size: 1, total: 1, start: 0,
data: [
{
id: '1', name: 'FakeNameTask', description: null, category: null,
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
}
]
};
export let fakeTaskListDifferentProcessDefinitionKey = {
size: 2, total: 1, start: 0,
data: [
{
id: '1', name: 'FakeNameTask', description: null, category: null,
assignee: fakeUser1,
processDefinitionKey: '1',
created: '2016-07-15T11:19:17.440+0000'
},
{
id: '2', name: 'FakeNameTask2', description: null, category: null,
assignee: fakeUser1,
processDefinitionKey: '2',
created: '2016-07-15T11:19:17.440+0000'
}
]
};
export let secondFakeTaskList = {
size: 1, total: 1, start: 0,
data: [
{
id: '200', name: 'FakeNameTask', description: null, category: null,
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
}
]
};
export let mockErrorTaskList = {
error: 'wrong request'
};
export let fakeTaskDetails = { id: '999', name: 'fake-task-name', formKey: '99', assignee: fakeUser1 };
export let fakeTasksComment = {
size: 2, total: 2, start: 0,
data: [
{
id: 1, message: 'fake-message-1', created: '', createdBy: fakeUser1
},
{
id: 2, message: 'fake-message-2', created: '', createdBy: fakeUser1
}
]
};
export let fakeTasksChecklist = {
size: 1, total: 1, start: 0,
data: [
{
id: 1, name: 'FakeCheckTask1', description: null, category: null,
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
},
{
id: 2, name: 'FakeCheckTask2', description: null, category: null,
assignee: fakeUser1,
created: '2016-07-15T11:19:17.440+0000'
}
]
};
export let fakeRepresentationFilter1: FilterRepresentationModel = new FilterRepresentationModel({
appId: 1,
name: 'CONTAIN FILTER',
recent: true,
icon: 'glyphicon-align-left',
filter: {
processDefinitionId: null,
processDefinitionKey: null,
name: null,
state: 'open',
sort: 'created-desc',
assignment: 'involved',
dueAfter: null,
dueBefore: null
}
});
export let fakeRepresentationFilter2: FilterRepresentationModel = new FilterRepresentationModel({
appId: 2,
name: 'NO TASK FILTER',
recent: false,
icon: 'glyphicon-inbox',
filter: {
processDefinitionId: null,
processDefinitionKey: null,
name: null,
state: 'open',
sort: 'created-desc',
assignment: 'assignee',
dueAfter: null,
dueBefore: null
}
});
export let fakeAppPromise = new Promise(function (resolve) {
resolve(fakeAppFilter);
});
export let fakeFormList = {
size: 2,
total: 2,
start: 0,
data: [{
id: 1,
name: 'form with all widgets',
description: '',
createdBy: 2,
createdByFullName: 'Admin Admin',
lastUpdatedBy: 2,
lastUpdatedByFullName: 'Admin Admin',
lastUpdated: 1491400951205,
latestVersion: true,
version: 4,
comment: null,
stencilSet: null,
referenceId: null,
modelType: 2,
favorite: null,
permission: 'write',
tenantId: null
}, {
id: 2,
name: 'uppy',
description: '',
createdBy: 2,
createdByFullName: 'Admin Admin',
lastUpdatedBy: 2,
lastUpdatedByFullName: 'Admin Admin',
lastUpdated: 1490951054477,
latestVersion: true,
version: 2,
comment: null,
stencilSet: null,
referenceId: null,
modelType: 2,
favorite: null,
permission: 'write',
tenantId: null
}]
};
export let fakeTaskOpen1 = {
id: '1', name: 'FakeOpenTask1', description: null, category: null,
assignee: fakeUser1,
created: '2017-07-15T11:19:17.440+0000',
dueDate: null,
endDate: null
};
export let fakeTaskOpen2 = {
id: '1', name: 'FakeOpenTask2', description: null, category: null,
assignee: { id: 1, email: 'fake-open-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
created: '2017-07-15T11:19:17.440+0000',
dueDate: null,
endDate: null
};
export let fakeTaskCompleted1 = {
id: '1', name: 'FakeCompletedTaskName1', description: null, category: null,
assignee: { id: 1, email: 'fake-completed-email@dom.com', firstName: 'firstName', lastName: 'lastName' },
created: '2016-07-15T11:19:17.440+0000',
dueDate: null,
endDate: '2016-11-03T15:25:42.749+0000'
};
export let fakeTaskCompleted2 = {
id: '1', name: 'FakeCompletedTaskName2', description: null, category: null,
assignee: fakeUser1,
created: null,
dueDate: null,
endDate: '2016-11-03T15:25:42.749+0000'
};
export let fakeOpenTaskList = {
size: 2,
total: 2,
start: 0,
data: [fakeTaskOpen1, fakeTaskOpen2]
};
export let fakeCompletedTaskList = {
size: 2,
total: 2,
start: 0,
data: [fakeTaskCompleted1, fakeTaskCompleted2]
};

View File

@@ -0,0 +1,11 @@
<adf-datatable
#dataTable
class="adf-task-people-list"
[rows]="users"
[actions]="hasActions()"
[showHeader]="false"
(rowClick)="selectUser($event)"
(rowDblClick)="selectUser($event)"
(showRowActionsMenu)="onShowRowActionsMenu($event)"
(executeRowAction)="onExecuteRowAction($event)">
</adf-datatable>

View File

@@ -0,0 +1,9 @@
@mixin adf-task-people-list-theme($theme) {
.adf-task-people-list {
.adf-datatable-list {
width: 100%;
}
}
}

View File

@@ -0,0 +1,79 @@
/*!
* @license
* Copyright 2019 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 { UserProcessModel, setupTestBed } from '@alfresco/adf-core';
import { DataRowActionEvent, DataRowEvent, ObjectDataRow } from '@alfresco/adf-core';
import { UserEventModel } from '../../../task-list/models/user-event.model';
import { PeopleListComponent } from './people-list.component';
import { ProcessTestingModule } from '../../../testing/process.testing.module';
const fakeUser: UserProcessModel = new UserProcessModel({
id: 1,
firstName: 'fake-name',
lastName: 'fake-last',
email: 'fake@mail.com'
});
describe('PeopleListComponent', () => {
let peopleListComponent: PeopleListComponent;
let fixture: ComponentFixture<PeopleListComponent>;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(PeopleListComponent);
peopleListComponent = fixture.componentInstance;
fixture.detectChanges();
}));
it('should emit row click event', (done) => {
const row = new ObjectDataRow(fakeUser);
const rowEvent = new DataRowEvent(row, null);
peopleListComponent.clickRow.subscribe((selectedUser) => {
expect(selectedUser.id).toEqual(1);
expect(selectedUser.email).toEqual('fake@mail.com');
expect(peopleListComponent.user.id).toEqual(1);
expect(peopleListComponent.user.email).toEqual('fake@mail.com');
done();
});
peopleListComponent.selectUser(rowEvent);
});
it('should emit row action event', (done) => {
const row = new ObjectDataRow(fakeUser);
const removeObj = {
name: 'remove',
title: 'Remove'
};
const rowActionEvent = new DataRowActionEvent(row, removeObj);
peopleListComponent.clickAction.subscribe((selectedAction: UserEventModel) => {
expect(selectedAction.type).toEqual('remove');
expect(selectedAction.value.id).toEqual(1);
expect(selectedAction.value.email).toEqual('fake@mail.com');
done();
});
peopleListComponent.onExecuteRowAction(rowActionEvent);
});
});

View File

@@ -0,0 +1,87 @@
/*!
* @license
* Copyright 2019 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 { DataTableComponent } from '@alfresco/adf-core';
import { DataColumnListComponent, UserProcessModel } from '@alfresco/adf-core';
import { AfterContentInit, AfterViewInit, Component, ContentChild, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { UserEventModel } from '../../../task-list/models/user-event.model';
@Component({
selector: 'adf-people-list',
templateUrl: './people-list.component.html',
styleUrls: ['./people-list.component.scss']
})
export class PeopleListComponent implements AfterViewInit, AfterContentInit {
@ContentChild(DataColumnListComponent) columnList: DataColumnListComponent;
@ViewChild('dataTable')
peopleDataTable: DataTableComponent;
/** The array of user data used to populate the people list. */
@Input()
users: UserProcessModel[];
/** Toggles whether or not actions should be visible, i.e. the 'Three-Dots' menu. */
@Input()
actions: boolean = false;
/** Emitted when the user clicks a row in the people list. */
@Output()
clickRow: EventEmitter<UserProcessModel> = new EventEmitter<UserProcessModel>();
/** Emitted when the user clicks in the 'Three Dots' drop down menu for a row. */
@Output()
clickAction: EventEmitter<UserEventModel> = new EventEmitter<UserEventModel>();
user: UserProcessModel;
ngAfterContentInit() {
this.peopleDataTable.columnList = this.columnList;
}
ngAfterViewInit() {
}
selectUser(event: any) {
this.user = event.value.obj;
this.clickRow.emit(this.user);
}
hasActions(): boolean {
return this.actions;
}
onShowRowActionsMenu(event: any) {
const removeAction = {
title: 'Remove',
name: 'remove'
};
event.value.actions = [
removeAction
];
}
onExecuteRowAction(event: any) {
const args = event.value;
const action = args.action;
this.clickAction.emit(new UserEventModel({type: action.name, value: args.row.obj}));
}
}

View File

@@ -0,0 +1,33 @@
<mat-form-field class="adf-search-text-container">
<input
matInput
placeholder="{{ searchPlaceholder }}"
type="text"
id="userSearchText"
[value]=""
[formControl]="searchUser"
data-automation-id="adf-people-search-input">
</mat-form-field>
<ng-container *ngIf="users$ | async; let users">
<div class="adf-search-list-container" id="search-people-list" *ngIf="users.length > 0">
<adf-people-list [users]="users" (clickRow)="onRowClick($event)">
<data-columns>
<data-column key="firstName">
<ng-template let-entry="$implicit">
<div *ngIf="!entry.row.obj.pictureId" class="adf-people-pic">
{{getInitialUserName(entry.row.obj.firstName, entry.row.obj.lastName)}}</div>
<div>
<img [alt]="getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ')" *ngIf="entry.row.obj.pictureId" class="adf-people-img"
[src]="peopleProcessService.getUserImage(entry.row.obj)"/>
</div>
</ng-template>
</data-column>
<data-column key="email" class="adf-full-width">
<ng-template let-entry="$implicit">
<div class="adf-people-full-name">{{ getDisplayUser(entry.row.obj.firstName, entry.row.obj.lastName, ' ') }}</div>
</ng-template>
</data-column>
</data-columns>
</adf-people-list>
</div>
</ng-container>

View File

@@ -0,0 +1,47 @@
@mixin adf-task-list-people-search-field-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
.adf-people-search-field {
width: 100%;
.adf-search-text-container {
width: 100%;
input {
line-height: normal;
}
}
.adf-search-list-container {
max-height: 152px;
width: 100%;
overflow-y: auto;
}
adf-people-list ::ng-deep adf-datatable ::ng-deep thead {
display: none;
}
.adf-people-pic {
background: mat-color($primary);
width: 30px;
padding: 10px 5px;
border-radius: 90%;
color: #fff;
text-align: center;
font-weight: bolder;
font-size: 18px;
text-transform: uppercase;
vertical-align: text-bottom;
}
.adf-people-img {
border-radius: 90%;
width: 40px;
height: 40px;
vertical-align: middle;
}
}
}

View File

@@ -0,0 +1,66 @@
/*!
* @license
* Copyright 2019 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 { DebugElement } from '@angular/core';
import { setupTestBed } from '@alfresco/adf-core';
import { PeopleSearchFieldComponent } from './people-search-field.component';
import { By } from '@angular/platform-browser';
import { ProcessTestingModule } from '../../../testing/process.testing.module';
describe('PeopleSearchFieldComponent', () => {
let component: PeopleSearchFieldComponent;
let fixture: ComponentFixture<PeopleSearchFieldComponent>;
let debug: DebugElement;
setupTestBed({
imports: [ProcessTestingModule]
});
beforeEach(() => {
fixture = TestBed.createComponent(PeopleSearchFieldComponent);
component = fixture.componentInstance;
debug = fixture.debugElement;
fixture.detectChanges();
});
it('should have the proper placeholder by default', () => {
const searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
expect(searchField.placeholder).toBe('ADF_TASK_LIST.PEOPLE.SEARCH_USER');
});
it('should have the overridden placeholder if set as input parameter', () => {
component.placeholder = 'Arcadia Bay';
fixture.detectChanges();
const searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
expect(searchField.placeholder).toBe('Arcadia Bay');
});
it('should reset the user on reset method invocation', () => {
let searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
searchField.value = 'User to be searched';
fixture.detectChanges();
component.reset();
searchField = debug.query(By.css('[data-automation-id="adf-people-search-input"]')).nativeElement;
expect(searchField.value).toBe('');
});
});

Some files were not shown because too many files have changed in this diff Show More