strolch-wc-inspector/strolch-wc-inspector-object...

683 lines
30 KiB
HTML

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
<link rel="import" href="../paper-header-panel/paper-header-panel.html">
<link rel="import" href="../paper-radio-group/paper-radio-group.html">
<link rel="import" href="../paper-checkbox/paper-checkbox.html">
<link rel="import" href="../paper-dialog/paper-dialog.html">
<link rel="import" href="../paper-button/paper-button.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-styles/default-theme.html">
<link rel="import" href="../paper-styles/shadow.html">
<link rel="import" href="../paper-styles/typography.html">
<link rel="import" href="../strolch-wc-styles/strolch-wc-styles.html">
<link rel="import" href="strolch-wc-inspector-behavior.html">
<dom-module id="strolch-wc-inspector-object">
<template>
<style is="custom-style" include="strolch-wc-styles">
:host {
display: block;
}
.title-div {
padding-left: 30px;
}
.title {
font-size: 16px;
font-weight: 400;
line-height: 40px;
margin: 0;
}
.sub {
font-size: small;
}
paper-material {
background: #ffffff;
}
paper-tabs {
border-top: solid #7F7F7F 1px;
--paper-tabs-selection-bar-color: var(--paper-amber-600);
background-color: #ffffff;
color: #000000;
}
textarea {
padding: 10px;
width: calc(100% - 20px);
max-width: calc(100% - 20px);
height: 100%;
min-height: 300px;
}
.cell {
margin-top: 0.5em;
overflow: auto;
}
.data-list {
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
section {
margin-bottom: 10px;
margin-left: 30px;
margin-right: 10px;
}
</style>
<paper-material elevation="2">
<div class="object-div">
<div class="g-row title-div" on-tap="_toggleExpanded">
<div class="g-12">
<h1 class="title">
<template is="dom-if" if="[[isRootElement]]">
<paper-checkbox checked="{{object._checked}}" on-tap="onCheckTapped"></paper-checkbox>
</template>
<span style="text-transform: uppercase">[[object.objectType]]</span>
<span class="sub g-ml-4">Id:</span> [[object.id]] <span class="sub g-ml-4">Name:</span>
[[object.name]] <span class="sub g-ml-4">Type:</span>
[[object.type]]
<paper-icon-button class="g-pull-right"
id="expandedIcon"
icon="expand-more"></paper-icon-button>
</h1>
</div>
</div>
<template is="dom-if" if="[[expanded]]">
<div class="g-row">
<div class="g-12">
<!-- Tabs -->
<paper-tabs selected="{{selectedDetailType}}"
attr-for-selected="name"
fallback-selection="none">
<paper-tab name="details">Details</paper-tab>
<paper-tab name="parameters">Parameters</paper-tab>
<paper-tab name="policies">Policies</paper-tab>
<template is="dom-if" if="[[_isResource(object.objectType)]]">
<paper-tab name="timedstates">Timed States</paper-tab>
</template>
<template is="dom-if" if="[[_isActivity(object.objectType)]]">
<paper-tab name="elements">Elements</paper-tab>
</template>
<template is="dom-if" if="[[isRootElement]]">
<paper-tab name="model">Model</paper-tab>
</template>
</paper-tabs>
<!-- Tab sections -->
<iron-pages selected="{{selectedDetailType}}" attr-for-selected="name">
<!-- details -->
<section name="details">
<template is="dom-if" if="[[!object]]">
<p class="g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<div class="g-row">
<div class="g-6">
<dl class="g-dl">
<dt>Id</dt>
<dd>[[object.id]]</dd>
<dt>Name</dt>
<dd>[[object.name]]</dd>
<dt>Type</dt>
<dd>[[object.type]]</dd>
<dt>Locator</dt>
<dd>[[object.locator]]</dd>
</dl>
<template is="dom-if"
if="[[_isActivity(object.objectType)]]"
restamp="true">
<dl class="g-dl">
<dt>State</dt>
<dd>[[object.state]]</dd>
<dt>TimeOrdering</dt>
<dd>[[object.timeOrdering]]</dd>
<dt>Start</dt>
<dd>[[_formatDate(object.start)]]</dd>
<dt>End</dt>
<dd>[[_formatDate(object.end)]]</dd>
</dl>
</template>
<template is="dom-if"
if="[[_isOrder(object.objectType)]]"
restamp="true">
<dl class="g-dl">
<dt>State</dt>
<dd>[[object.state]]</dd>
<dt>Date</dt>
<dd>[[_formatDate(object.date)]]</dd>
</dl>
</template>
<template is="dom-if"
if="[[_isAction(object.objectType)]]"
restamp="true">
<dl class="g-dl">
<dt>State</dt>
<dd>[[object.state]]</dd>
<dt>Start</dt>
<dd>[[_formatDate(object.start)]]</dd>
<dt>End</dt>
<dd>[[_formatDate(object.end)]]</dd>
<dt>Resource Type</dt>
<dd>[[object.resourceType]]</dd>
<dt>Resource Id</dt>
<dd>[[object.resourceId]]</dd>
</dl>
</template>
</div>
<div class="g-6">
<template is="dom-if" if="[[object.version]]" restamp="true">
<dl class="g-dl">
<dt>Created</dt>
<dd>[[_formatDate(object.version.created)]]</dd>
<dt>Updated</dt>
<dd>[[_formatDate(object.version.updated)]]</dd>
<dt>CreatedBy</dt>
<dd>[[object.version.createdBy]]</dd>
<dt>UpdatedBy</dt>
<dd>[[object.version.updatedBy]]</dd>
<dt>Deleted</dt>
<dd>[[object.version.deleted]]</dd>
<dt>Version</dt>
<dd>[[object.version.version]]</dd>
</dl>
</template>
</div>
</div>
</template>
</section>
<!-- parameters -->
<section name="parameters">
<template is="dom-if" if="[[!object]]">
<p class="g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<template is="dom-if" if="[[_isEmpty(object.parameterBags)]]">
<p class="g-center">No parameters defined on [[object.objectType]]
[[object.id]]</p>
</template>
<template is="dom-if" if="[[_isNotEmpty(object.parameterBags)]]">
<div class="g-row g-pt-2">
<div class="g-2"><b>ParameterBag</b></div>
<div class="g-2"><b>Parameter Id</b></div>
<div class="g-2"><b>Name</b></div>
<div class="g-2"><b>Interpretation</b></div>
<div class="g-1"><b>UOM</b></div>
<div class="g-1"><b>Type</b></div>
<div class="g-2"><b>Value</b></div>
</div>
<template is="dom-repeat"
items="{{_asArray(object.parameterBags)}}"
as="bag">
<template is="dom-repeat"
items="{{_asArray(bag.value.parameters)}}"
as="param">
<div class="g-row">
<div class="g-2 cell">[[bag.value.id]]</div>
<div class="g-2 cell">[[param.value.id]]</div>
<div class="g-2 cell">[[param.value.name]]</div>
<div class="g-2 cell">[[param.value.interpretation]]</div>
<div class="g-1 cell">[[param.value.uom]]</div>
<div class="g-1 cell">[[param.value.type]]</div>
<div class="g-2 cell">[[param.value.value]]</div>
</div>
</template>
</template>
</template>
</template>
</section>
<!-- policies -->
<section name="policies">
<template is="dom-if" if="[[!object]]">
<p class="g-m-4 g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<template is="dom-if" if="[[_isEmpty(object.policies)]]">
<p class="g-pt-4 g-center">No policies defined on [[objectName]]
[[object.id]]</p>
</template>
<template is="dom-if" if="[[_isNotEmpty(object.policies)]]">
<div class="g-row g-pt-2 data-list">
<div class="g-6"><b>Type</b></div>
<div class="g-6"><b>Value</b></div>
</div>
<template is="dom-repeat" items="{{_asArray(object.policies)}}" as="policy">
<div class="g-row data-list">
<div class="g-6 cell">[[policy.key]]</div>
<div class="g-6 g-pl-2 cell">[[policy.value]]</div>
</div>
</template>
</template>
</template>
</section>
<!-- timedstates -->
<template is="dom-if" if="[[_isResource(object.objectType)]]">
<section name="timedstates">
<template is="dom-if" if="[[!object]]">
<p class="g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<template is="dom-if" if="[[_isEmpty(object.timedStates)]]">
<p class="g-pt-4 g-center">No timed states defined on [[objectName]]
[[object.id]]</p>
</template>
<template is="dom-if" if="[[_isNotEmpty(object.timedStates)]]">
<template is="dom-repeat"
items="[[_asArray(object.timedStates)]]"
as="timedState">
<div class="g-row g-pt-2">
<div class="g-4"><b>Id</b> [[timedState.value.id]]</div>
<div class="g-4"><b>Name</b> [[timedState.value.name]]</div>
<div class="g-4"><b>Type</b> [[timedState.value.type]]</div>
</div>
<div class="g-row g-pt-4 data-list">
<div class="g-6"><b>Time</b></div>
<div class="g-6"><b>Value</b></div>
</div>
<template is="dom-repeat"
items="[[timedState.value.values]]"
as="timedStateValue">
<div class="g-row data-list">
<div class="g-6 cell">[[timedStateValue.time]]</div>
<div class="g-6 g-pl-2 cell">[[timedStateValue.value]]</div>
</div>
</template>
</template>
</template>
</template>
</section>
</template>
<!-- activity children -->
<template is="dom-if" if="[[_isActivity(object.objectType)]]">
<section name="elements">
<template is="dom-if" if="[[!object]]">
<p class="g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<template is="dom-repeat" items="[[object.elements]]" as="childElement">
<strolch-wc-inspector-object base-path="[[basePath]]"
realm="[[realm]]"
object="[[childElement]]"
class="g-m-2"></strolch-wc-inspector-object>
</template>
</template>
</section>
</template>
<!-- model -->
<template is="dom-if" if="[[isRootElement]]">
<section name="model">
<template is="dom-if" if="[[!object]]">
<p class="g-center">Loading...</p>
</template>
<template is="dom-if" if="[[object]]">
<textarea value="{{model::input}}"></textarea>
<div class="g-mt-3">
<paper-radio-group selected="{{modelType}}" style="font-size: small">
<paper-radio-button name="xml">XML</paper-radio-button>
<paper-radio-button name="json">JSON</paper-radio-button>
<paper-radio-button name="json-flat">JSON Flat</paper-radio-button>
</paper-radio-group>
<paper-button raised class="g-pull-right" on-tap="_saveModel">Save
</paper-button>
<paper-button class="g-pull-right" on-tap="_removeModel">Remove
</paper-button>
</div>
</template>
</section>
</template>
</iron-pages>
</div>
</div>
</template>
</div>
</paper-material>
<iron-ajax id="ajax"
content-type="application/json"
on-response="_handleAjaxResponse"
on-error="onAjaxError"></iron-ajax>
</template>
<script>
Polymer({
is: 'strolch-wc-inspector-object',
behaviors: [
StrolchInspectorBehavior
],
properties: {
realm: {
type: String,
value: function () {
return null;
}
},
isRootElement: {
type: Boolean,
value: function () {
return false;
}
},
object: {
type: Object,
value: function () {
return null;
},
observer: "_objectChanged"
},
modelType: {
type: String,
value: function () {
return 'xml';
},
observer: "_modelTypeChanged"
},
model: {
type: String,
value: null
},
expanded: {
type: Boolean,
value: false
},
selectedDetailType: {
type: String,
value: '',
observer: '_selectedDetailTypeChanged'
}
},
onCheckTapped: function (evt) {
evt.cancelBubble = true;
this.fire('strolch-element-selected', {object: this.object});
},
_objectChanged: function (newValue, oldValue) {
if (newValue != null && oldValue == null || (newValue != null && oldValue != null && newValue.id != oldValue.id)) {
this.expanded = false;
this.selectedDetailType = '';
}
},
_modelTypeChanged: function (newValue, oldValue) {
if (this.expanded && this.isRootElement && newValue != oldValue) {
this.reloadModel();
}
},
_selectedDetailTypeChanged: function (newValue, oldValue) {
if (newValue == null || newValue.length == 0 || newValue == 'none')
return;
if (this.expanded) {
if (newValue == 'model')
this.reloadModel();
else
this.reloadObject();
}
},
_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;
}
},
_isResource: function (objectType) {
return objectType == 'Resource';
},
_isOrder: function (objectType) {
return objectType == 'Order';
},
_isActivity: function (objectType) {
return objectType == 'Activity';
},
_isAction: function (objectType) {
return objectType == 'Action';
},
_isEmpty: function (obj) {
if (obj == null) return true;
if (obj instanceof Array) {
return obj.length == 0;
} else if (obj instanceof Object) {
return Object.keys(obj).length == 0;
}
return true;
},
_isNotEmpty: function (obj) {
return !this._isEmpty(obj);
},
_asArray: function (obj) {
if (!obj) return [];
return Object.keys(obj).map(function (key) {
return {
key: key,
value: obj[key]
};
});
},
_formatDate: function (date) {
return Strolch.toDateTime(date);
},
_toggleExpanded: function (evt) {
this.expanded = !this.expanded;
this.$.expandedIcon.icon = this.expanded ? 'expand-less' : 'expand-more';
if (this.expanded) {
if (this.selectedDetailType == 'model')
this.reloadModel();
else
this.reloadObject();
}
},
_getObjectUrl: function () {
var objectType = this.object.objectType;
var id = this.object.id;
var type = this.object.type;
return this.basePath + 'rest/strolch/inspector/' + this.realm + '/' + this._typeSubPath(objectType) + '/' + type + '/' + id;
},
_getAcceptHeader: function () {
if (this.modelType == 'xml') {
return 'application/xml'
} else if (this.modelType == 'json') {
return 'application/json'
} else if (this.modelType == 'json-flat') {
return 'application/json';
} else {
return 'application/xml';
}
},
reloadObject: function () {
if (!this.isRootElement) {
return;
}
this.dlgTitle = 'Reload object failed';
this._handleAjaxResponse = function (data) {
this.object = data.detail.response;
};
this.$.ajax.url = this._getObjectUrl();
this.$.ajax.headers = {'Accept': 'application/json'};
this.$.ajax.handleAs = 'json';
this.$.ajax.method = 'GET';
this.$.ajax.generateRequest();
},
reloadModel: function () {
if (this._isAction(this.object.objectType)) {
return;
}
var accept = this._getAcceptHeader();
var url = this._getObjectUrl();
if (this.modelType == 'json-flat') {
url += '?flat=true';
}
this.model = null;
this.dlgTitle = 'Reload model failed';
this._handleAjaxResponse = function (data) {
this.model = data.detail.response;
};
this.$.ajax.url = url;
this.$.ajax.headers = {'Accept': accept};
this.$.ajax.handleAs = 'text';
this.$.ajax.method = 'GET';
this.$.ajax.generateRequest();
},
_saveModel: function (evt) {
var accept = this._getAcceptHeader();
var url = this._getObjectUrl();
if (this.modelType == 'json-flat') {
url += '?flat=true';
}
this.dlgTitle = 'Save model failed';
this._handleAjaxResponse = function (data) {
this.model = null;
this.model = data.detail.response;
this.reloadObject();
};
this.$.ajax.url = url;
this.$.ajax.headers = {
'Accept': accept,
'Content-Type': accept
};
this.$.ajax.handleAs = 'text';
this.$.ajax.method = 'PUT';
this.$.ajax.body = this.model;
this.$.ajax.generateRequest();
},
_removeModel: function (evt) {
var accept = this._getAcceptHeader();
var url = this._getObjectUrl();
var object = this.object;
this.dlgTitle = 'Remove model failed';
this._handleAjaxResponse = function (data) {
this.fire("strolch-wc-obj-remove", {object: object});
};
this.$.ajax.url = url;
this.$.ajax.headers = {
'Accept': accept,
'Content-Type': accept
};
this.$.ajax.handleAs = 'text';
this.$.ajax.method = 'DELETE';
this.$.ajax.generateRequest();
},
ready: function () {
},
reload: function () {
},
_handleAjaxResponse: function (evt) {
console.log('NOT YET DEFINED!');
}
});
</script>
</dom-module>