diff --git a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html index 04531d9db4..766434a190 100644 --- a/demo-shell-ng2/app/components/activiti/activiti-demo.component.html +++ b/demo-shell-ng2/app/components/activiti/activiti-demo.component.html @@ -11,16 +11,16 @@
-
+
Task Filters
-
+
Task List
-
+
Task Details
diff --git a/demo-shell-ng2/app/components/patients/createpatient.component.css b/demo-shell-ng2/app/components/patients/createpatient.component.css new file mode 100644 index 0000000000..81e07b0891 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/createpatient.component.css @@ -0,0 +1,49 @@ +.upload-border { + position: relative; + height: 200px; + width: 200px; + padding: 5px 5px +} + +.drag-area { + width: 200px; + height: 100px; + border: 1px solid #888888; +} + +.image-cell{ + width: 100px; + height: 100px; + border-radius: 50px; + text-align: center; + position: absolute; + top: 0; + margin-left: -50px; + border: 3px #1c597f solid; + z-index: 99; + margin-top: 45px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.container-title-details{ + background-color: #1c597f; + color: #ffffff; +} + +.title-details { + margin: auto; + text-align: center; +} + +.user-image-wrap{ + background-color: #1c597f; + text-align: center; + height: 60px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.upload-photo-button{ + text-align: center; + height: 50px; + margin-top: 35px; +} diff --git a/demo-shell-ng2/app/components/patients/createpatient.component.html b/demo-shell-ng2/app/components/patients/createpatient.component.html new file mode 100644 index 0000000000..ef8febbf9f --- /dev/null +++ b/demo-shell-ng2/app/components/patients/createpatient.component.html @@ -0,0 +1,20 @@ +
+

Create Patient

+
+
+ +
+
+ + +
+ diff --git a/demo-shell-ng2/app/components/patients/createpatient.component.ts b/demo-shell-ng2/app/components/patients/createpatient.component.ts new file mode 100644 index 0000000000..91105cb242 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/createpatient.component.ts @@ -0,0 +1,101 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core'; +import { FormService, ActivitiForm } from 'ng2-activiti-form'; +import { Router } from '@angular/router'; +import { NotificationService } from '../../services/notification.service'; +import { ALFRESCO_ULPOAD_COMPONENTS } from 'ng2-alfresco-upload'; + +declare let __moduleName: string; +declare let AlfrescoApi: any; + +@Component({ + moduleId: __moduleName, + selector: 'createpatient-component', + templateUrl: './createpatient.component.html', + styleUrls: ['./createpatient.component.css'], + providers: [FormService], + directives: [ALFRESCO_ULPOAD_COMPONENTS, ActivitiForm] +}) +export class CreatePatientComponent { + + currentPath: string = '/Sites/swsdp/documentLibrary'; + + metadata: any = {}; + + photoNode: string = ""; + + imgSrc: string = "app/img/anonymous.gif"; + + constructor(private authService: AlfrescoAuthenticationService, private router: Router, + private notificationService: NotificationService, + private alfrescoSettingsService: AlfrescoSettingsService) { + } + + public fileUploaded(data) { + if (data && data.value) { + this.photoNode = data.value.entry.id; + this.imgSrc = this.alfrescoSettingsService.ecmHost + '/alfresco/api/-default-/public/alfresco/versions/1/nodes/' + data.value.entry.id + '/content?attachment=false'; + console.log(this.photoNode); + } + } + + saveMetadata(data: any) { + let name = ''; + if (!this.photoNode) { + name = this.generateUuid(); + } else { + name = this.photoNode; + } + + let body = { + name: name, + nodeType: 'hc:patientFolder', + properties: {}, + relativePath: this.currentPath + }; + + for (var key in data) { + if (data[key]) { + body.properties['hc:' + key] = data[key]; + } + } + let opts = {}; + + let self = this; + this.authService.getAlfrescoApi().nodes.addNode('-root-', body, opts).then( + (data) => { + console.log('The folder created', data); + self.router.navigate(['/patients']); + this.notificationService.sendNotification('User Created'); + }, + (err) => { + window.alert('See console output for error details'); + console.log(err); + } + ); + } + + private generateUuid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } +} diff --git a/demo-shell-ng2/app/components/patients/patient.model.ts b/demo-shell-ng2/app/components/patients/patient.model.ts new file mode 100644 index 0000000000..5832c4db27 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patient.model.ts @@ -0,0 +1,23 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class PatientModel { + folderName: string; + firstName: string; + lastName: string; + doctor: string; +} diff --git a/demo-shell-ng2/app/components/patients/patientdetails.component.css b/demo-shell-ng2/app/components/patients/patientdetails.component.css new file mode 100644 index 0000000000..45c649042c --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patientdetails.component.css @@ -0,0 +1,30 @@ +.image-cell{ + width: 100px; + height: 100px; + border-radius: 50px; + text-align: center; + position: absolute; + top: 0; + margin-left: -50px; + border: 3px #1c597f solid; + z-index: 99; + margin-top: 45px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.container-title-details{ + background-color: #1c597f; + color: #ffffff; +} + +.title-details { + margin: auto; + text-align: center; +} + +.user-image-wrap{ + background-color: #1c597f; + text-align: center; + height: 60px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} diff --git a/demo-shell-ng2/app/components/patients/patientdetails.component.html b/demo-shell-ng2/app/components/patients/patientdetails.component.html new file mode 100644 index 0000000000..082592d564 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patientdetails.component.html @@ -0,0 +1,14 @@ +
+

Patient Details

+
+
+ +
+ + diff --git a/demo-shell-ng2/app/components/patients/patientdetails.component.ts b/demo-shell-ng2/app/components/patients/patientdetails.component.ts new file mode 100644 index 0000000000..740fc645ca --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patientdetails.component.ts @@ -0,0 +1,82 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core'; +import { FormService, ActivitiForm } from 'ng2-activiti-form'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Subscription } from 'rxjs/Rx'; + +declare let __moduleName: string; +declare let AlfrescoApi: any; + +@Component({ + moduleId: __moduleName, + selector: 'patient-details', + templateUrl: './patientdetails.component.html', + styleUrls: ['./patientdetails.component.css'], + providers: [FormService], + directives: [ActivitiForm] +}) +export class PatientDetailsComponent implements OnInit, OnDestroy { + + private sub: Subscription; + + currentPath: string = '/Sites/swsdp/documentLibrary'; + + metadata: any = {}; + + nodeId: string; + + photoNodeId: string; + + ticket: string = localStorage.getItem('ticket-ECM'); + + constructor(private route: ActivatedRoute, + private router: Router, + private authService: AlfrescoAuthenticationService, + public alfrescoSettingsService: AlfrescoSettingsService) { + } + + ngOnInit() { + this.sub = this.route.params.subscribe(params => { + this.retriveNodeMetadataFromEcm(params['id']); + }); + } + + ngOnDestroy() { + if (this.sub) { + this.sub.unsubscribe(); + } + } + + private retriveNodeMetadataFromEcm(nodeId: string): void{ + var self = this; + this.nodeId = nodeId; + this.authService.getAlfrescoApi().nodes.getNodeInfo(this.nodeId).then(function (data) { + console.log(data.properties); + self.photoNodeId = data.name; + for (var key in data.properties) { + console.log(key + ' => ' + data[key]); + self.metadata [key.replace('hc:','')] = data.properties[key]; + } + + }, function (error) { + console.log('This node does not exist'); + }); + } +} diff --git a/demo-shell-ng2/app/components/patients/patients.component.css b/demo-shell-ng2/app/components/patients/patients.component.css new file mode 100644 index 0000000000..73ef4cae95 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patients.component.css @@ -0,0 +1,72 @@ +.container { + /*margin: 10px;*/ +} + +@media only screen and (max-width: 640px) { + .container { + margin: 0; + } +} + +.patients-debug-container { + padding: 10px; +} + +.patients-debug-container .debug-toggle-text { + padding-left: 15px; + cursor: pointer; +} + +.patients-debug-container .debug-toggle-text:hover { + font-weight: bold; +} + +alfresco-document-list >>> .image-cell { + width: 50px; + height: 50px; + cursor: default; + border: 2px solid #aaaaaa; + border-radius: 30px; +} + +alfresco-document-list >>> .mdl-data-table { + border: 0px; +} + +.image-cell{ + background-color: #ffffff; + width: 100px; + height: 100px; + border-radius: 50px; + text-align: center; + position: absolute; + top: 17px; + margin-left: -50px; + border: 3px #1c597f solid; + z-index: 99; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.container-title-details{ + background-color: #1c597f; + color: #ffffff; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.title-details { + margin: auto; + text-align: center; +} + +.user-image-wrap{ + background-color: #1c597f; + text-align: center; + height: 64px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +@media only screen and (max-width: 840px) { + #tags { + width: 100%; + } +} diff --git a/demo-shell-ng2/app/components/patients/patients.component.html b/demo-shell-ng2/app/components/patients/patients.component.html new file mode 100644 index 0000000000..d556a1ddee --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patients.component.html @@ -0,0 +1,218 @@ +
+
+
+

Tags

+
+
    +
  • + + + + +
  • +
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+
    +
  • + + {{prop.name}} + {{prop.value}} + +
  • +
+
+
+ + + + + +

Set Tags

+
+
+
+ + +
+
+
+
+ + +
+
+ + + + + + + +
+
+ + diff --git a/demo-shell-ng2/app/components/patients/patients.component.ts b/demo-shell-ng2/app/components/patients/patients.component.ts new file mode 100644 index 0000000000..dc29fbcb76 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/patients.component.ts @@ -0,0 +1,402 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, OnInit, ViewChild, ChildNode } from '@angular/core'; +import { Router } from '@angular/router'; +import { + PaginationComponent, + DataColumn, + DataRow, + ObjectDataColumn +} from 'ng2-alfresco-datatable'; +import { + DOCUMENT_LIST_DIRECTIVES, + DOCUMENT_LIST_PROVIDERS, + DocumentList, + ShareDataRow, + RowFilter, + MinimalNodeEntity, + ImageResolver +} from 'ng2-alfresco-documentlist'; +import { + MDL, + AlfrescoContentService, + CONTEXT_MENU_DIRECTIVES, + AlfrescoPipeTranslate, + AlfrescoSettingsService +} from 'ng2-alfresco-core'; +import { ALFRESCO_ULPOAD_COMPONENTS } from 'ng2-alfresco-upload'; +import { VIEWERCOMPONENT } from 'ng2-alfresco-viewer'; +import { FormService } from 'ng2-activiti-form'; +import { PatientModel } from './patient.model'; +import { TagModel, TagCache, TagFilter } from './tag.model'; +import { TagService } from './tag.service'; + +declare let __moduleName: string; + +@Component({ + moduleId: __moduleName, + selector: 'patients-component', + templateUrl: './patients.component.html', + styleUrls: ['./patients.component.css'], + directives: [ + DOCUMENT_LIST_DIRECTIVES, + MDL, + ALFRESCO_ULPOAD_COMPONENTS, + VIEWERCOMPONENT, + CONTEXT_MENU_DIRECTIVES, + PaginationComponent + ], + providers: [DOCUMENT_LIST_PROVIDERS, FormService, TagService], + pipes: [AlfrescoPipeTranslate] +}) +export class PatientsComponent implements OnInit { + + private DEFAULT_PATH: string = '/Sites/swsdp/documentLibrary'; + + currentPath: string = this.DEFAULT_PATH; + + urlFile: string; + fileName: string; + mimeType: string; + fileShowed: boolean = false; + + acceptedFilesType: string = '.jpg,.pdf,.js'; + + @ViewChild(DocumentList) + documentList: DocumentList; + + newPatient: PatientModel; + debugMode: boolean = false; + + tags: TagCache = {}; + tagFilters: TagFilter[] = []; + selectedNode: MinimalNodeEntity; + selectedNodeProperties: NodePropertyModel[] = []; + selectedNodePropertiesName: string; + tagFilter: RowFilter; + folderImageResolver: ImageResolver; + ticket: string = localStorage.getItem('ticket-ECM'); + ecmHost: string; + detailsAvatarImage: string; + isVisitFolder: boolean = false; + private patientLayout: DataColumn[] = []; + private fileLayout: DataColumn[] = []; + emptyimgSrc: string = "app/img/anonymous.gif"; + + constructor(private contentService: AlfrescoContentService, + private router: Router, + private tagService: TagService, + private alfrescoSettingsService: AlfrescoSettingsService) { + this.newPatient = new PatientModel(); + this.ecmHost = alfrescoSettingsService.ecmHost; + this.tagFilter = (row: ShareDataRow) => { + let selectedTags = this.tagFilters + .filter(f => f.isSelected) + .map(f => f.id); + + if (selectedTags.length > 0) { + let properties = row.node.entry.properties; + if (properties) { + let tags = properties['cm:taggable']; + if (tags && tags instanceof Array && tags.length > 0) { + + let result = false; + + for (let i = 0; i < selectedTags.length; i++) { + if (tags.indexOf(selectedTags[i]) > -1) { + result = true; + break; + } + } + + return result; + } + } + return false; + } + + return true; + }; + + this.folderImageResolver = (row: DataRow, col: DataColumn) => { + let isFolder = row.getValue('isFolder'); + if (isFolder) { + let value = row.getValue(col.key); + return this.alfrescoSettingsService.ecmHost + `/alfresco/api/-default-/public/alfresco/versions/1/nodes/` + + value + '/content?attachment=false&alf_ticket=' + this.ticket; + } + return null; + }; + + this.patientLayout = this.getPatientLayout(); + this.fileLayout = this.getFileLayout(); + } + + isAdmin() { + if (localStorage.getItem(`username`) === 'admin') { + return true; + } else { + return false; + } + } + + resetFilters() { + if (this.tagFilters && this.tagFilters.length > 0) { + this.tagFilters.map(f => f.isSelected = false); + this.documentList.reload(); + } + } + + patientDetails(event: any) { + this.router.navigate(['/patientdetails', event.value.entry.id]); + } + + showFile(event) { + if (event.value.entry.isFile) { + this.fileName = event.value.entry.name; + this.mimeType = event.value.entry.content.mimeType; + this.urlFile = this.contentService.getContentUrl(event.value); + this.fileShowed = true; + } else { + this.fileShowed = false; + } + } + + onFolderChanged(event?: any) { + if (event) { + this.selectedNode = null; + this.selectedNodeProperties = null; + + + this.currentPath = event.path; + this.loadTags(); + if (this.currentPath === this.DEFAULT_PATH) { + this.folderImageResolver = (row: DataRow, col: DataColumn) => { + let isFolder = row.getValue('isFolder'); + if (isFolder) { + let value = row.getValue(col.key); + return this.alfrescoSettingsService.ecmHost + `/alfresco/api/-default-/public/alfresco/versions/1/nodes/` + + value + '/content?attachment=false&alf_ticket=' + this.ticket; + } + return null; + }; + this.documentList.data.setColumns(this.patientLayout); + this.isVisitFolder = false; + } else { + this.documentList.data.setColumns(this.fileLayout); + this.folderImageResolver = (row: DataRow, col: DataColumn) => { + return 'app/img/checklist.svg'; + }; + this.isVisitFolder = true; + } + } + } + + ngOnInit() { + // this.loadTags(); + } + + onNodeClicked(event?: any) { + console.log(event); + if (event && event.value) { + this.selectedNodeProperties = null; + this.selectedNode = event.value; + this.selectedNodePropertiesName = event.value.entry.name; + if(this.isVisitFolder){ + this.detailsAvatarImage = 'app/img/checklist.svg'; + }else{ + this.detailsAvatarImage = this.ecmHost + '/alfresco/api/-default-/public/alfresco/versions/1/nodes/' + this.selectedNodePropertiesName + '/content?attachment=false&alf_ticket=' + this.ticket; + } + if (this.selectedNode) { + this.selectedNodeProperties = this.getNodeProperties(this.selectedNode); + console.log(this.selectedNodeProperties); + } + } + } + + onFilterChanged(event) { + setTimeout(() => { + this.documentList.reload(); + }, 500); + } + + addTag(event){ + let self = this; + let nodeId = event.value.entry.id; + let dialog = document.querySelector('dialog'); + if (! dialog.showModal) { + dialogPolyfill.registerDialog(dialog); + } + dialog.showModal(); + dialog.querySelector('.close').addEventListener('click', function() { + dialog.close(); + }); + dialog.querySelector('.save').addEventListener('click', function() { + self.setNodeTags(nodeId, dialog.querySelector('#node-tags').value); + dialog.close(); + }); + } + + setNodeTags(nodeId: string, value: string) { + if (nodeId && value) { + let tags = value.split(',').map(val => { + return { + tag: val.trim() + } + }); + + this.tagService.addTags(nodeId, tags).then( + data => { + console.log(data); + // TODO: share seems to have issues with returning newly created tags + // it sometimes takes several seconds for changes to global tags to propagate + // and become visible + /* + this.getTags().then( + res => { + console.log('after tags updated'); + console.log(res); + this.tags = res || []; + this.documentList.reload(); + }, + this.handleError + ); + */ + }, + this.handleError + ); + } + } + + + scheduleAppointment(event?: any) { + this.router.navigate(['/startvisit', event.value.entry.id]); + } + + private getNodeProperties(node: MinimalNodeEntity): NodePropertyModel[] { + let result = []; + + if (node && node.entry && node.entry.properties) { + let props = node.entry.properties; + Object.keys(props).forEach(key => { + result.push(new NodePropertyModel(key, props[key])); + }); + } + + return result; + } + + private loadTags() { + this.tagService.getTags().then( + (tags: TagModel[]) => { + this.tagFilters = tags.map((tag) => new TagFilter(tag.id, tag.tag)); + tags.forEach(tag => this.tags[tag.id] = tag); + }, + this.handleError + ); + } + + private handleError(err) { + console.log(err); + } + + private getPatientLayout(): DataColumn[] { + return [ + new ObjectDataColumn({ + key: 'name', + type: 'image' + }), + new ObjectDataColumn({ + title: 'First Name', + key: 'properties.hc:firstName', + sortable: true, + cssClass: 'desktop-only' + }), + new ObjectDataColumn({ + title: 'Last Name', + key: 'properties.hc:lastName', + sortable: true, + cssClass: 'desktop-only' + }), + new ObjectDataColumn({ + title: 'Doctor', + key: 'properties.hc:doctor', + sortable: true, + cssClass: 'desktop-only' + }), + new ObjectDataColumn({ + title: 'Created On', + key: 'createdAt', + type: 'date', + format: 'shortDate', + sortable: true, + cssClass: 'desktop-only' + }) + ]; + } + + private getFileLayout(): DataColumn[] { + return [ + new ObjectDataColumn({ + key: '$thumbnail', + type: 'image' + }), + new ObjectDataColumn({ + title: 'Display Name', + key: 'name', + sortable: true, + cssClass: 'full-width ellipsis-cell' + }), + new ObjectDataColumn({ + title: 'Created By', + key: 'createdByUser.displayName', + sortable: true, + cssClass: 'desktop-only' + }), + new ObjectDataColumn({ + title: 'Created On', + key: 'createdAt', + type: 'date', + format: 'shortDate', + sortable: true, + cssClass: 'desktop-only' + }) + ]; + } +} + +class NodePropertyModel { + + prefix: string; + name: string; + value: string; + fullName: string; + + constructor(name: string, value: string) { + this.fullName = name; + this.name = name; + if (name) { + let idx = name.indexOf(':'); + if (idx > -1) { + this.prefix = name.substring(0, idx); + this.name = name.substring(idx + 1); + } + } + this.value = value; + } +} diff --git a/demo-shell-ng2/app/components/patients/tag.model.ts b/demo-shell-ng2/app/components/patients/tag.model.ts new file mode 100644 index 0000000000..22bffb5181 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/tag.model.ts @@ -0,0 +1,39 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class TagModel { + id: string; + tag: string; + + constructor(id: string, tag: string) { + this.id = id; + this.tag = tag; + } +} + +export interface TagCache { + [key: string]: TagModel; +} + +export class TagFilter extends TagModel { + count: number = 0; + isSelected: boolean = false; + + constructor(id: string, tag: string) { + super(id, tag); + } +} diff --git a/demo-shell-ng2/app/components/patients/tag.service.ts b/demo-shell-ng2/app/components/patients/tag.service.ts new file mode 100644 index 0000000000..21b50da699 --- /dev/null +++ b/demo-shell-ng2/app/components/patients/tag.service.ts @@ -0,0 +1,49 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { TagModel } from './tag.model'; + +@Injectable() +export class TagService { + + constructor(private authService: AlfrescoAuthenticationService) {} + + getTags(): Promise { + return new Promise((resolve, reject) => { + this.authService.getAlfrescoApi().core.tagsApi.getTags({}).then( + data => { + let entries = data.list.entries || []; + let tags = entries.map(obj => obj.entry); + resolve(tags); + }, + err => reject(err) + ); + }); + } + + addTags(nodeId: string, tags: { tag: string }[]): Promise { + return new Promise((resolve, reject) => { + this.authService.getAlfrescoApi().core.tagsApi.addTag(nodeId, tags).then( + data => resolve(data), + err => reject(err) + ); + }); + } + +} diff --git a/demo-shell-ng2/app/components/visit/process.data.ts b/demo-shell-ng2/app/components/visit/process.data.ts new file mode 100644 index 0000000000..d5049424fb --- /dev/null +++ b/demo-shell-ng2/app/components/visit/process.data.ts @@ -0,0 +1,12 @@ +export interface Process { + category: string; + deploymentId: string; + description: string; + hasStartForm: boolean; + id: string; + key: string; + name: string; + tenantId: string; + version: number; + metaDataValues: any[]; +} diff --git a/demo-shell-ng2/app/components/visit/process.service.ts b/demo-shell-ng2/app/components/visit/process.service.ts new file mode 100644 index 0000000000..6d807f825a --- /dev/null +++ b/demo-shell-ng2/app/components/visit/process.service.ts @@ -0,0 +1,121 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Response, Http, Headers, RequestOptions } from '@angular/http'; +import { Observable } from 'rxjs/Observable'; +import { AlfrescoAuthenticationService, AlfrescoSettingsService } from 'ng2-alfresco-core'; + +import { Process } from './process.data'; + + +@Injectable() +export class ProcessService { + + constructor(private http: Http, + private authService: AlfrescoAuthenticationService, + private alfrescoSettingsService: AlfrescoSettingsService) { + } + + getDeployedApplications(name: string): Observable { + let url = `${this.alfrescoSettingsService.bpmHost}/activiti-app/api/enterprise/runtime-app-definitions`; + let options = this.getRequestOptions(); + return this.http + .get(url, options) + .map((response: Response) => response.json().data.find(p => p.name === name)) + .do(data => console.log('Application: ' + JSON.stringify(data))) + .catch(this.handleError); + } + + + getProcessDefinitions(): Observable { + let url = `${this.alfrescoSettingsService.bpmHost}/activiti-app/api/enterprise/process-definitions`; + let options = this.getRequestOptions(); + return this.http + .get(url, options) + .map((response: Response) => response.json()) + .do(data => console.log('All: ' + JSON.stringify(data))) + .catch(this.handleError); + } + + getProcessDefinitionByApplication(application: any): Observable { + return this.getProcessDefinitions() + .map((processes: Process[]) => processes.data.find(p => p.deploymentId === application.deploymentId)); + } + + getStartFormForProcess(processDefinitionId: string): Observable { + let url = `${this.alfrescoSettingsService.bpmHost}/activiti-app/api/enterprise/process-definitions/${processDefinitionId}/start-form`; + let options = this.getRequestOptions(); + return this.http + .get(url, options) + .map((response: Response) => response.json()) + .catch(this.handleError); + } + + startProcessByID(processDefinitionId: string, processName: string): void { + let url = `${this.alfrescoSettingsService.bpmHost}/activiti-app/api/enterprise/process-instances`; + let options = this.getRequestOptions(); + let body = JSON.stringify({processDefinitionId: processDefinitionId, name: processName}); + console.log(body); + return this.http + .post(url, body, options) + .map(this.toJson) + .catch(this.handleError); + } + + getTaskIdFromProcessID(processDefinitionId: string, appDefinitionId: string, processInstanceId: string): Observable { + let url = `${this.alfrescoSettingsService.bpmHost}/activiti-app/api/enterprise/tasks/query`; + let options = this.getRequestOptions(); + let body = JSON.stringify({ + processDefinitionId: processDefinitionId, + appDefinitionId: appDefinitionId, + processInstanceId: processInstanceId + }); + console.log(body); + return this.http + .post(url, body, options) + .map(this.toJson) + .catch(this.handleError); + } + + + private getHeaders(): Headers { + return new Headers({ + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': this.authService.getTicket('BPM') + }); + } + + private getRequestOptions(): RequestOptions { + let headers = this.getHeaders(); + return new RequestOptions({headers: headers}); + } + + private toJson(res: Response) { + let body = res.json(); + return body || {}; + } + + private handleError(error: any) { + console.log("ERROR"); + let errMsg = (error.message) ? error.message : + error.status ? `${error.status} - ${error.statusText}` : 'Server error'; + console.error(errMsg); + return Observable.throw(errMsg); + } +} diff --git a/demo-shell-ng2/app/components/visit/start-visit.component.css b/demo-shell-ng2/app/components/visit/start-visit.component.css new file mode 100644 index 0000000000..69a8081965 --- /dev/null +++ b/demo-shell-ng2/app/components/visit/start-visit.component.css @@ -0,0 +1,39 @@ +.image-cell{ + width: 100px; + height: 100px; + border-radius: 50px; + text-align: center; + position: absolute; + top: 0; + margin-left: -50px; + border: 3px #1c597f solid; + z-index: 99; + margin-top: 45px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.container-title-details{ + background-color: #1c597f; + color: #ffffff; +} + +.title-details { + margin: auto; + text-align: center; +} + +.user-image-wrap{ + background-color: #1c597f; + text-align: center; + height: 60px; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); +} + +.upload-photo-button{ + text-align: center; + height: 50px; + margin-top: 35px; +} +.wrap-form{ + margin-top: 35px; +} diff --git a/demo-shell-ng2/app/components/visit/start-visit.component.html b/demo-shell-ng2/app/components/visit/start-visit.component.html new file mode 100644 index 0000000000..35776643a7 --- /dev/null +++ b/demo-shell-ng2/app/components/visit/start-visit.component.html @@ -0,0 +1,10 @@ +
+

Schedule Appointment

+
+
+ +
+
+ +
diff --git a/demo-shell-ng2/app/components/visit/start-visit.component.ts b/demo-shell-ng2/app/components/visit/start-visit.component.ts new file mode 100644 index 0000000000..bcdbc92aa3 --- /dev/null +++ b/demo-shell-ng2/app/components/visit/start-visit.component.ts @@ -0,0 +1,134 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component } from '@angular/core'; +import { AlfrescoAuthenticationService } from 'ng2-alfresco-core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Subscription } from 'rxjs/Rx'; +import { ProcessService } from './process.service'; +import { Process } from './process.data'; + +import { FormService, ActivitiForm } from 'ng2-activiti-form'; +import { NotificationService } from '../../services/notification.service'; + +declare let __moduleName: string; +declare let AlfrescoApi: any; + +@Component({ + moduleId: __moduleName, + selector: 'start-visit-component', + templateUrl: './start-visit.component.html', + styleUrls: ['./start-visit.component.css'], + providers: [ProcessService, FormService], + directives: [ActivitiForm] +}) + +export class StartVisitComponent { + + private sub: Subscription; + + currentPath: string = '/Sites/swsdp/documentLibrary'; + + metadata: any = {}; + + nodeId: string; + + nodeName: string; + + errorMessage: string; + + processName: string = "TEST"; + + process: Process; + + taskId: string; + + constructor(private route: ActivatedRoute, + private router: Router, + private processService: ProcessService, + private authService: AlfrescoAuthenticationService, + private notificationService: NotificationService) { + } + + ngOnInit() { + this.sub = this.route.params.subscribe(params => { + this.retriveNodeMetadataFromEcm(params['id']); + }); + + + let self = this; + this.processService.getDeployedApplications("Visit").subscribe( + application => { + console.log("I'm the application hello", application); + this.processService.getProcessDefinitionByApplication(application).subscribe( + process => { + console.log("this is the process", process); + self.processService.startProcessByID(process.id, process.name).subscribe( + startedProcess => { + console.log(startedProcess); + this.processService.getTaskIdFromProcessID(process.id, application.id, startedProcess.id).subscribe( + response => { + console.log(response.data[0].id); + self.taskId = response.data[0].id; + }, + error => { + console.log(error) + } + ); + }, + error => { + console.log(error); + } + ); + }, + error => this.errorMessage = error + ); + console.log(application); + }, + error => this.errorMessage = error + ); + } + + public saveData(){ + this.router.navigate(['/patients']); + this.notificationService.sendNotification('New Visit Created'); + } + + private retriveNodeMetadataFromEcm(nodeId: string): void { + var self = this; + this.nodeId = nodeId; + this.authService.getAlfrescoApi().nodes.getNodeInfo(this.nodeId).then(function (data) { + console.log(data.properties); + self.nodeName = data.name; + for (var key in data.properties) { + console.log(key + ' => ' + data[key]); + self.metadata [key.replace('hc:', '')] = data.properties[key]; + } + self.metadata.nodeId = self.nodeName; + + }, function (error) { + console.log('This node does not exist'); + }); + } + + private generateUuid() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } +} diff --git a/demo-shell-ng2/app/img/admin.jpeg b/demo-shell-ng2/app/img/admin.jpeg new file mode 100644 index 0000000000..0efd7dbd02 Binary files /dev/null and b/demo-shell-ng2/app/img/admin.jpeg differ diff --git a/demo-shell-ng2/app/img/anonymous.gif b/demo-shell-ng2/app/img/anonymous.gif new file mode 100644 index 0000000000..e1b58fa57d Binary files /dev/null and b/demo-shell-ng2/app/img/anonymous.gif differ diff --git a/demo-shell-ng2/app/img/background.jpg b/demo-shell-ng2/app/img/background.jpg new file mode 100644 index 0000000000..792f58a231 Binary files /dev/null and b/demo-shell-ng2/app/img/background.jpg differ diff --git a/demo-shell-ng2/app/img/checklist.svg b/demo-shell-ng2/app/img/checklist.svg new file mode 100644 index 0000000000..603b46fef5 --- /dev/null +++ b/demo-shell-ng2/app/img/checklist.svg @@ -0,0 +1,782 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo-shell-ng2/app/img/completed.svg b/demo-shell-ng2/app/img/completed.svg new file mode 100644 index 0000000000..84f75fa8a2 --- /dev/null +++ b/demo-shell-ng2/app/img/completed.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/demo-shell-ng2/app/img/createvisit.jpg b/demo-shell-ng2/app/img/createvisit.jpg new file mode 100644 index 0000000000..7505e347e4 Binary files /dev/null and b/demo-shell-ng2/app/img/createvisit.jpg differ diff --git a/demo-shell-ng2/app/img/users.png b/demo-shell-ng2/app/img/users.png new file mode 100644 index 0000000000..b1cca051a4 Binary files /dev/null and b/demo-shell-ng2/app/img/users.png differ diff --git a/demo-shell-ng2/app/img/visit.jpg b/demo-shell-ng2/app/img/visit.jpg new file mode 100644 index 0000000000..b07d287404 Binary files /dev/null and b/demo-shell-ng2/app/img/visit.jpg differ diff --git a/demo-shell-ng2/app/img/visitor.jpg b/demo-shell-ng2/app/img/visitor.jpg new file mode 100644 index 0000000000..813426332c Binary files /dev/null and b/demo-shell-ng2/app/img/visitor.jpg differ diff --git a/demo-shell-ng2/app/services/notification.service.ts b/demo-shell-ng2/app/services/notification.service.ts new file mode 100644 index 0000000000..d93a12144b --- /dev/null +++ b/demo-shell-ng2/app/services/notification.service.ts @@ -0,0 +1,31 @@ +/*! + * @license + * Copyright 2016 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Injectable } from '@angular/core'; +import { Subject } from 'rxjs/Subject'; + +@Injectable() +export class NotificationService { + + notificationsdSource = new Subject(); + + notifications = this.notificationsdSource.asObservable(); + + sendNotification(message: string) { + this.notificationsdSource.next(message); + } +} diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.css b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.css index 34500e7278..6eb9bd0de9 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.css +++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.css @@ -19,3 +19,7 @@ .activiti-form-debug-container .debug-toggle-text:hover { font-weight: bold; } + +.activiti-form-hide-button { + display: none; +} diff --git a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html index afa87b40af..b269a29029 100644 --- a/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html +++ b/ng2-components/ng2-activiti-form/src/components/activiti-form.component.html @@ -1,11 +1,10 @@
-

Please select a Task

+

Please select a Visit

-
-
+

{{form.taskName}}

@@ -21,11 +20,12 @@
-
+
-