strolch-wc-inspector/strolch-wc-inspector.html

712 lines
27 KiB
HTML

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-ajax/iron-ajax.html">
<link rel="import" href="../iron-pages/iron-pages.html">
<link rel="import" href="../paper-styles/color.html">
<link rel="import" href="../paper-material/paper-material.html">
<link rel="import" href="../paper-dialog/paper-dialog.html">
<link rel="import" href="../paper-button/paper-button.html">
<link rel="import" href="../paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../paper-item/paper-item.html">
<link rel="import" href="../paper-listbox/paper-listbox.html">
<link rel="import" href="../paper-tabs/paper-tabs.html">
<link rel="import" href="../strolch-wc-styles/strolch-wc-styles.html">
<link rel="import" href="strolch-wc-inspector-behavior.html">
<link rel="import" href="strolch-wc-inspector-objects.html">
<dom-module id="strolch-wc-inspector">
<template>
<style is="custom-style" include="strolch-wc-styles">
:host {
display: block;
margin: 0;
padding: 0;
height: 100%;
}
.toolbar {
background-color: var(--paper-blue-600);
color: rgba(255, 255, 255, 0.8);
height: 42px;
padding-left: 20px;
}
paper-tabs {
margin: 0;
padding: 0;
height: 100%;
--paper-tabs-selection-bar-color: var(--paper-amber-600);
background-color: var(--paper-blue-600);
color: #fff;
}
paper-dropdown-menu {
margin-left: 1em;
}
.uploadTypeDropDown {
margin: 0;
}
paper-dropdown-menu.custom {
--paper-dropdown-menu-label: {
background-color: var(--paper-blue-600);
color: #ffffff;
};
--paper-dropdown-menu-input: {
background-color: var(--paper-blue-600);
color: #ffffff;
};
--paper-input-container: {
color: #ffffff;
};
--paper-input-container-input: {
color: #ffffff;
};
--paper-input-container-label: {
color: #ffffff;
font-size: smaller;
};
--paper-input-container-focus: {
color: #ffffff;
};
--paper-input-container-underline: {
display: none;
};
}
paper-listbox {
--paper-listbox-background-color: var(--paper-blue-600);
--paper-listbox-color: #ffffff;
}
paper-material {
background-color: #ffffff;
}
.uploadDlg {
width: 600px;
}
textarea {
padding: 10px;
width: calc(100% - 20px);
height: 100%;
min-height: 300px;
}
.textarea {
width: auto;
overflow: auto;
min-height: auto;
line-height: 20px;
border: none;
}
</style>
<div class="g-row">
<div class="g-3">
<div class="toolbar">
<paper-dropdown-menu no-label-float label="select realm" class="custom">
<paper-listbox attr-for-selected="value" class="dropdown-content" selected="{{selectedRealm}}">
<template is="dom-repeat" items="{{realms}}">
<paper-item value="[[item.name]]">[[item.name]] ([[item.size]])</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</div>
</div>
<div class="g-9">
<div class="g-row toolbar">
<div class="g-10">
<template is="dom-if" if="[[selectedRealm]]">
<paper-tabs selected="{{selectedObjectType}}" attr-for-selected="name">
<paper-tab name="Resource">[[resourcesSummary]]</paper-tab>
<paper-tab name="Order">[[ordersSummary]]</paper-tab>
<paper-tab name="Activity">[[activitiesSummary]]</paper-tab>
</paper-tabs>
</template>
</div>
<div class="g-2">
<paper-icon-button icon="refresh" title="Refresh" on-tap="reloadRealms"></paper-icon-button>
<paper-icon-button icon="cloud-download"
title="Download entire Realm"
on-tap="onExportRealm"></paper-icon-button>
<paper-icon-button icon="cloud-upload"
title="Upload data to realm"
on-tap="onUploadTapped"></paper-icon-button>
</div>
</div>
</div>
</div>
<div class="g-row">
<div class="g-12">
<iron-pages selected="{{selectedObjectType}}" attr-for-selected="name">
<section name="Resource">
<strolch-wc-inspector-objects id="resourcesInspector"
base-path="[[basePath]]"
realm="[[selectedRealm]]"
object-type="Resource"
object-summaries="[[resources]]"></strolch-wc-inspector-objects>
</section>
<section name="Order">
<strolch-wc-inspector-objects id="ordersInspector"
base-path="[[basePath]]"
realm="[[selectedRealm]]"
object-type="Order"
object-summaries="[[orders]]"></strolch-wc-inspector-objects>
</section>
<section name="Activity">
<strolch-wc-inspector-objects id="activitiesInspector"
base-path="[[basePath]]"
realm="[[selectedRealm]]"
object-type="Activity"
object-summaries="[[activities]]"></strolch-wc-inspector-objects>
</section>
</iron-pages>
</div>
</div>
<paper-dialog id="dlg" modal>
<h2>[[dlgTitle]]</h2>
<textarea class="textarea" readonly rows="7" cols="50">{{dlgText}}</textarea>
<div class="buttons">
<paper-button dialog-confirm autofocus>Close</paper-button>
</div>
</paper-dialog>
<paper-dialog id="uploadDlg" class="uploadDlg" modal>
<h3>Import elements</h3>
<paper-dropdown-menu class="uploadTypeDropDown" label-always-float label="Upload Type">
<paper-listbox class="dropdown-content" attr-for-selected="value" selected="{{uploadType}}">
<paper-item value="text">Text</paper-item>
<paper-item value="file">File</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<iron-pages attr-for-selected="name" selected="[[uploadType]]" class="g-m-0">
<div name="text">
<textarea value="{{modelAsText::input}}"></textarea>
<h4>Add:</h4>
<div>
<paper-checkbox checked="{{addResources}}">Resources</paper-checkbox>
<paper-checkbox checked="{{addOrders}}">Orders</paper-checkbox>
<paper-checkbox checked="{{addActivities}}">Activities</paper-checkbox>
</div>
<h4>Update:</h4>
<div>
<paper-checkbox checked="{{updateResources}}">Resources</paper-checkbox>
<paper-checkbox checked="{{updateOrders}}">Orders</paper-checkbox>
<paper-checkbox checked="{{updateActivities}}">Activities</paper-checkbox>
<paper-checkbox checked="{{failOnUpdate}}">FailOnUpdate</paper-checkbox>
</div>
<div class="buttons">
<paper-button class="g-pull-right" on-tap="onCancelUploadTap" raised>
<iron-icon icon="close"></iron-icon>
Cancel
</paper-button>
<paper-button class="g-pull-right" on-tap="onUploadTextTap" raised>
<iron-icon icon="add"></iron-icon>
Add
</paper-button>
</div>
</div>
<div name="file">
<paper-input label="Encoding" value="{{uploadEncoding}}" class="g-mt-1"></paper-input>
<vaadin-upload class="g-mt-2"
id="uploadFile"
accept=".xml"
method="POST"
max-files="1"
max-file-size="100000000"
on-upload-error="onUploadFileError"
on-upload-before="onUploadFileBefore"
on-upload-success="onUploadFileSuccess"
on-upload-request="onUploadFileRequest"></vaadin-upload>
<h4>Add:</h4>
<div>
<paper-checkbox checked="{{addResources}}">Resources</paper-checkbox>
<paper-checkbox checked="{{addOrders}}">Orders</paper-checkbox>
<paper-checkbox checked="{{addActivities}}">Activities</paper-checkbox>
</div>
<h4>Update:</h4>
<div>
<paper-checkbox checked="{{updateResources}}">Resources</paper-checkbox>
<paper-checkbox checked="{{updateOrders}}">Orders</paper-checkbox>
<paper-checkbox checked="{{updateActivities}}">Activities</paper-checkbox>
<paper-checkbox checked="{{failOnUpdate}}">FailOnUpdate</paper-checkbox>
</div>
<div class="buttons">
<paper-button class="g-pull-right" on-tap="onCancelUploadTap" raised>
<iron-icon icon="close"></iron-icon>
Close
</paper-button>
</div>
</div>
</iron-pages>
</paper-dialog>
<iron-ajax id="ajax"
content-type="application/json"
handle-as="json"
on-response="_handleAjaxResponse"
on-error="onAjaxError"></iron-ajax>
<iron-ajax id="ajaxXml"
content-type="application/xml"
handle-as="text"
method="GET"
on-response="_handleAjaxResponse"
on-error="onAjaxError"></iron-ajax>
</template>
<script>
Polymer({
is: "strolch-wc-inspector",
behaviors: [
StrolchInspectorBehavior
],
properties: {
realms: {
type: Array,
value: null
},
selectedRealm: {
type: Object,
value: null,
observer: "selectedRealmChanged"
},
resourcesSummary: {
type: String,
value: "Resources"
},
ordersSummary: {
type: String,
value: "Orders"
},
activitiesSummary: {
type: String,
value: "Activities"
},
selectedObjectType: {
type: String,
value: null,
observer: "selectedObjectTypeChanged"
},
resources: {
type: Object,
value: null
},
orders: {
type: Object,
value: null
},
activities: {
type: Object,
value: null
},
uploadType: {
type: String,
value: "text"
},
uploadEncoding: {
type: String,
value: "utf-8"
},
modelAsText: {
type: String,
value: ""
},
propagateShowDialog: {
type: Boolean,
value: false
},
failOnUpdate: {
type: Boolean,
value: false
},
addResources: {
type: Boolean,
value: true
},
addOrders: {
type: Boolean,
value: true
},
addActivities: {
type: Boolean,
value: true
},
updateResources: {
type: Boolean,
value: true
},
updateOrders: {
type: Boolean,
value: true
},
updateActivities: {
type: Boolean,
value: true
}
},
listeners: {
"strolch-show-dialog": "onShowDialog"
},
onShowDialog: function (event) {
if (!this.propagateShowDialog) {
event.cancelBubble = true;
event.stopPropagation();
this.showError(event.detail.title, event.detail.text);
}
},
showError: function (title, text) {
this.dlgTitle = title;
this.dlgText = text;
console.log('ERROR: ' + this.dlgTitle + ': ' + this.dlgText);
this.$.dlg.open();
},
selectedRealmChanged: function (newValue, oldValue) {
if (newValue != null) {
console.log('Selected realm changed from ' + oldValue + " to " + newValue);
Strolch.setQueryParamValue('realm', newValue);
this.reloadSelectedRealm();
}
},
selectedObjectTypeChanged: function (newValue, oldValue) {
if (newValue != null) {
console.log('Selected object type changed from ' + oldValue + " to " + newValue);
Strolch.setQueryParamValue('objectType', newValue);
if (oldValue != null && newValue != oldValue) {
Strolch.setQueryParamValue('type', null);
}
this.reloadSelectedObjectType();
}
},
ready: function () {
//
},
reload: function () {
this.selectedRealm = null;
this.selectedObjectType = null;
this.resources = null;
this.orders = null;
this.activities = null;
this.reloadRealms();
},
reloadRealms: function () {
var realmToSelect = Strolch.getQueryParamValue('realm');
this._handleAjaxResponse = function (data) {
this.selectedRealm = null;
this.selectedObjectType = null;
this.resources = null;
this.orders = null;
this.activities = null;
this.realms = data.detail.response.realms;
if (Strolch.isNotEmptyString(realmToSelect)) {
for (var i = 0; i < this.realms.length; i++) {
if (this.realms[i].name === realmToSelect) {
this.selectedRealm = realmToSelect;
break;
}
}
}
if (this.selectedRealm == null && this.realms.length > 0) {
this.selectedRealm = this.realms[0].name;
}
};
this.$.ajax.url = this.basePath + 'rest/strolch/inspector';
this.$.ajax.method = 'GET';
this.$.ajax.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
this.$.ajax.generateRequest();
},
onExportRealm: function () {
this._handleAjaxResponse = function (data) {
var response = data.detail.response;
var fileName = this.selectedRealm + '_' + Strolch.toDateTimeNoDelim(new Date()) + '.xml';
Strolch.handleAjaxFileDownload(response, fileName, 'application/xml');
};
this.$.ajaxXml.url = this.basePath + 'rest/strolch/inspector/' + this.selectedRealm + '/xml';
this.$.ajaxXml.headers = {'Accept': 'application/xml'};
this.$.ajaxXml.method = 'GET';
this.$.ajaxXml.generateRequest();
},
onUploadTapped: function (event) {
this.modelAsText = "<StrolchModel>\n\n\n</StrolchModel>";
this.$.uploadFile.files = [];
this.$.uploadDlg.open();
},
onCancelUploadTap: function (event) {
this.modelAsText = "<StrolchModel>\n\n\n</StrolchModel>";
this.$.uploadDlg.close();
},
onUploadTextTap: function (event) {
if (!this.modelAsText || this.modelAsText.length === 0) {
this.showError('Model empty', 'Model can not be empty!');
return;
}
this.dlgTitle = 'Import failed';
this._handleAjaxResponse = function (data) {
this.modelAsText = "<StrolchModel>\n\n\n</StrolchModel>";
this.$.uploadDlg.close();
this.dlgTitle = 'Import done';
this.dlgText = data.detail.response.msg;
this.$.dlg.open();
this.reloadRealms();
};
this.$.ajax.url = this.basePath + 'rest/strolch/inspector/' + this.selectedRealm + '/import';
this.$.ajax.headers = {
'Accept': 'application/xml',
'Content-Type': 'application/xml'
};
this.$.ajax.params = this._getImportParams();
this.$.ajax.method = 'POST';
this.$.ajax.body = this.modelAsText;
this.$.ajax.generateRequest();
},
_getImportParams: function () {
return {
failOnUpdate: this.failOnUpdate,
addResources: this.addResources,
addOrders: this.addOrders,
addActivities: this.addActivities,
updateResources: this.updateResources,
updateOrders: this.updateOrders,
updateActivities: this.updateActivities,
};
},
onUploadFileBefore: function (evt) {
var pieces = [];
var params = this._getImportParams();
Object.keys(params).forEach(function (key) {
pieces.push(
this._wwwFormUrlEncodePiece(key) + '=' +
this._wwwFormUrlEncodePiece(params[key]));
}, this);
evt.detail.file.uploadTarget = this.basePath + 'rest/strolch/inspector/' + this.selectedRealm + '/import?' + pieces.join('&');
},
_wwwFormUrlEncodePiece: function (str) {
return str === null ? '' : encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n')).replace(/%20/g, '+');
},
onUploadFileSuccess: function (evt) {
this.$.uploadDlg.close();
this.dlgTitle = 'Import done';
this.dlgText = evt.detail.xhr.response;
if (this.dlgText.charAt(0) === '{')
this.dlgText = JSON.parse(this.dlgText).msg;
this.$.dlg.open();
this.reloadRealms();
},
onUploadFileRequest: function (evt) {
evt.preventDefault();
evt.detail.xhr.setRequestHeader("Content-Type", "application/xml" + "; charset=" + this.uploadEncoding);
evt.detail.xhr.send(evt.detail.file);
},
onUploadFileError: function (evt) {
console.log(evt);
var error = evt.detail.xhr.response;
if (error.charAt(0) === '{')
error = JSON.parse(error).msg;
this.showError('Upload failed', error);
},
reloadSelectedRealm: function () {
if (Strolch.isEmptyString(this.selectedRealm)) {
console.log('No realm selected!');
return;
}
var objectTypeToSelect = Strolch.getQueryParamValue('objectType');
this.selectedObjectType = null;
this.resources = null;
this.orders = null;
this.activities = null;
this._handleAjaxResponse = function (data) {
var elementMaps = data.detail.response.elementMaps;
for (var i = 0; i < elementMaps.length; i++) {
var element = elementMaps[i];
switch (element.objectType) {
case 'Resource':
this.resourcesSummary = 'Resources (' + element.nrOfElements + ')';
break;
case 'Order':
this.ordersSummary = 'Orders (' + element.nrOfElements + ')';
break;
case 'Activity':
this.activitiesSummary = 'Activities (' + element.nrOfElements + ')';
break;
default:
console.log('Unhandled object type: ' + element.objectType);
}
}
if (Strolch.isNotEmptyString(objectTypeToSelect)) {
this.selectedObjectType = objectTypeToSelect;
}
};
this.$.ajax.url = this.basePath + 'rest/strolch/inspector/' + this.selectedRealm;
this.$.ajax.method = 'GET';
this.$.ajax.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
this.$.ajax.generateRequest();
},
reloadSelectedObjectType: function () {
if (Strolch.isEmptyString(this.selectedRealm)) {
console.log('No realm selected!');
return;
}
if (Strolch.isEmptyString(this.selectedObjectType)) {
console.log('No objectType selected!');
return;
}
if (this.selectedObjectType === 'Resource' && this.resources != null) {
this.$$('#resourcesInspector').show();
return;
}
if (this.selectedObjectType === 'Order' && this.orders != null) {
this.$$('#ordersInspector').show();
return;
}
if (this.selectedObjectType === 'Activity' && this.activities != null) {
this.$$('#activitiesInspector').show();
return;
}
var typeToSelect = Strolch.getQueryParamValue('type');
function hasType(type, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].type === type)
return true;
}
return false;
}
this._handleAjaxResponse = function (data) {
switch (data.detail.response.objectType) {
case 'Resource':
this.resources = data.detail.response;
this.$$('#resourcesInspector').selectType(hasType(typeToSelect, this.resources.types) ? typeToSelect : null);
break;
case 'Order':
this.orders = data.detail.response;
this.$$('#ordersInspector').selectType(hasType(typeToSelect, this.orders.types) ? typeToSelect : null);
break;
case 'Activity':
this.activities = data.detail.response;
this.$$('#activitiesInspector').selectType(hasType(typeToSelect, this.activities.types) ? typeToSelect : null);
break;
default:
console.log('Unhandled object type: ' + data.detail.response.objectType);
}
};
this.$.ajax.url = this.basePath + 'rest/strolch/inspector/' + this.selectedRealm + '/' + this._typeSubPath(this.selectedObjectType);
this.$.ajax.method = 'GET';
this.$.ajax.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
this.$.ajax.generateRequest();
},
_typeSubPath: function (selectedType) {
if (selectedType === 'Resource') {
return 'resources';
} else if (selectedType === 'Order') {
return 'orders';
} else if (selectedType === 'Activity') {
return 'activities';
} else {
throw 'Unhandled selected type ' + selectedType;
}
},
_handleAjaxResponse: function (evt) {
console.log('NOT YET DEFINED!');
}
});
</script>
</dom-module>