UNPKG

spincycle

Version:

A reactive message router and object manager that lets clients subscribe to object property changes on the server

434 lines (385 loc) 19.2 kB
<link rel="import" href="../../bower_components/polymer/polymer.html"> <link rel="import" href="../../bower_components/paper-listbox/paper-listbox.html"> <link rel="import" href="../../bower_components/paper-item/paper-item.html"> <link rel="import" href="../../bower_components/iron-icons/maps-icons.html"> <link rel="import" href="../../bower_components/iron-icons/iron-icons.html"> <link rel="import" href="../../bower_components/paper-input/paper-input.html"> <link rel="import" href="../../bower_components/paper-input/paper-textarea.html"> <link rel="import" href="../../bower_components/paper-dialog/paper-dialog.html"> <link rel="import" href="../../bower_components/ace-widget/ace-widget.html"> <link rel="import" href="../../bower_components/carbon-i18n-behavior/carbon-i18n-behavior.html"> <script src="../i18n/spin-model.en.i18.js"></script> <script src="../i18n/spin-model.se.i18.js"></script> <link rel="import" href="spin-directreference.html"> <link rel="import" href="my-objarray.html"> <dom-module id="spin-model"> <template> <style> paper-button.fancy { background: #0062A2; color: white; width: 250px; margin-bottom: 10px; text-transform:none; box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2); } </style> <template is="dom-if" if="{{doshow}}"> <h4>{{model.name}}</h4> <paper-button raised class="fancy" on-tap="saveModel">Save</paper-button> <paper-listbox> <!-- <paper-button on-tap="saveModel">Save</paper-button> --> <my-objarray object="{{model}}" array="{{array}}"></my-objarray> <template id="modeltemplate" is="dom-repeat" items="{{array}}"> <div style="display:flex; flex-direction:row"> <paper-item > <!-- {{item.key}}__ --> <template is="dom-if" if="{{isType(item,'array')}}"> <spin-list propname="{{item.key}}" delete="true" incallbacks="[[outCallbacks]]" client="{{client}}" user="{{user}}" model="{{getTypeFor(item)}}" spinids="{{item.value}}" itemselected="{{selectedlistitem}}" show="true"></spin-list> <paper-button raised on-tap="addModel">[[i18n.add]] {{getTypeFor(item)}}</paper-button> <paper-dialog style="padding:20px;overflow:auto" id="addmodeldialog_{{getModelId()}}_{{getTypeFor(item)}}"> <h2>[[i18n.add]] {{item.type}}</h2> <spin-allmodels client="{{client}}" user="{{user}}" incallbacks="{{dialogCallbacks}}" listitemselected="{{dialoglistitemselected}}" model="{{getTypeFor(item)}}"></spin-allmodels> <div class="buttons"> <paper-button dialog-dismiss>[[i18n.cancel]]</paper-button> <paper-button dialog-confirm>[[i18n.accept]]</paper-button> </div> </paper-dialog> </template> <template is="dom-if" if="{{isType(item,'ref')}}"> <spin-directreference client="{{client}}" user="{{user}}" incallbacks="{{dialogCallbacks}}" propname="{{item.key}}" modelid="{{item.value}}" modeltype="{{getTypeFor(item)}}" ></spin-directreference> </template> <template is="dom-if" if="{{isType(item,'scalar')}}"> <paper-textarea id="{{item.key}}" label="[[getLabelFor(item.key)]]" disabled="{{item.disabled}}" type="text" value="{{item.value::input}}" on-keyup="onInputChange" autoSave="true" stopKeyboardEventPropagation="true" style="width:600px"> </paper-textarea> </template> <template is="dom-if" if="{{isType(item,'timestamp')}}"> <paper-textarea label="[[getLabelFor(item.key)]]" disabled="{{item.disabled}}" type="text" value="{{getDateFor(item.value)}}" on-keyup="onInputChange" autoSave="true" stopKeyboardEventPropagation="true" style="width:600px"> </paper-textarea> </template> <template is="dom-if" if="{{isType(item,'code')}}"> <div style="display:flex;flex-direction: row; justify-content: space-between;width:600px"> <strong style="padding-right:20px;">[[getLabelFor(item.key)]]</strong> <ace-widget on-editor-content="onEditorContent" style="width:500px;height:300px;">{{item.value}}</ace-widget> </div> </template> </paper-item> </div> </template> </paper-listbox> </template> </template> <script> Polymer({ is: 'spin-model', properties: { client:{type:'Object'}, model: {type: 'Object', notify:true, value: function() {return new Object()}, observer: 'onModelChanged' }, modelproperties: {type: 'Array', observer: 'onModelProperties'}, incallbacks: {type: 'Object'}, selectedlistitem:{type:'Object', notify:true, observer:'onListItemSelect'}, dialoglistitemselected:{type:'Object', observer:'onDialogSelect'}, readonlyproperties: {type: 'Array', value: ['id']} }, locale: { type: String, value: 'en' }, behaviors: [ Polymer.CarbonI18nBehavior ], showing: function() { console.log('this.doshow = '+this.doshow) return this.doshow }, onEditorContent:function(i) { console.log('onEditorContent called for '+i) console.dir(i) var key = i.model.item.key var value = i.detail.value console.log('setting mode property '+key+' to '+value) this.set('model.'+key, value) }, getLabelFor:function(key) { return this.i18n[key] || key }, getDateFor:function(v) { return new Date(v).toString() }, beforeRegister: function() { this.observers = [ '_onModel(model.*)', '_onArray(array.*)' ] }, _onModel: function(change) { //console.log("test._onItems", change.path); //console.dir(change) }, _onArray: function(change) { //console.log("test._onArray", change.path); //console.dir(change) }, onModelProperties:function(props) { //console.log('spin-model ------ onModelProperties') //console.dir(props) }, onListItemSelect: function(item) { console.log('spin-model onListitemSelected') //console.dir(item) //this.onDialogSelect(item) }, onInputChange:function(e) { console.log('onInputChange called') console.dir(e) var key = e.model.item.key var value = e.path[0].value console.log('key = '+key+', value = '+value) this.set('model.'+key, value) }, getTypeFor:function(item) { //console.log('getTypeFor '+item.key+' called') var rv = '' this.modelproperties.forEach(function(prop) { if(prop.name == item.key) { rv = prop.type } }) //console.log('getTypeFor '+item.key+' return '+rv+' modelprops =') //console.dir(this.modelproperties) return rv }, getModelId:function() { var rv = '' for(var k in this.model) { if(k == 'id') { rv = this.model[k] } } return rv }, isType: function(item, what) { //console.log('isType called for '+item+' and '+what+' modelproperties = '+this.modelproperties) //console.dir(item) var rv = false if(this.modelproperties) { this.modelproperties.forEach( function ( prop ) { if (prop.name == item.key) { //console.log('found '+prop.name) //console.dir(prop) if(what == 'timestamp' && prop.name.indexOf('At') > -1) { rv = true } if(what=='code' && prop.code == true && !prop.array && !prop.type) { rv = true } if (what == 'scalar' && !prop.array && !prop.type && prop.name.indexOf('At') == -1 && !prop.code) { rv = true } if (what == 'array' && prop.array == true && !prop.code) { rv = true } if (what == 'ref' && prop.type && !(prop.array == true) && !prop.code) { rv = true } } } ) //console.log('isType called for '+item.key+' and '+what+' returning '+rv) } return rv }, textAreaAutoSave:function(e) { console.log('textAreaAutoSave called') console.dir(e) }, ready: function() { this.doshow = false this.subscriptions = [] this.dialogCallbacks = { onSelect: this.onDialogSelect.bind(this), onSelectReference: this.onSelectReference.bind(this) } this.outCallbacks = { onDelete: this.onDeleteListElement.bind(this) } }, addModel: function(e) { var item = e.model.item this.modeldialogitem = item console.log('spin-model addModel called. opening dialog for item') console.dir(item) var id = "addmodeldialog_"+this.model.id+"_"+this.getTypeFor(item) console.log('dialog id -> '+id) var dialog = this.$$('#'+id) dialog.open() }, onDeleteListElement: function(item, propname) { console.log('spin-model got delete list item callback for property '+propname) console.dir(item) if(confirm('Really remove list item '+item.name+' from '+propname+' list?')) { var list = this.model[propname] console.log( 'current list is ' ) console.dir( list ) var idx = -1 list.forEach( function ( id, i ) { if (id == item.id) { idx = i } } ) if (idx > -1) { list.splice( idx, 1 ) this.changeValueInArrayFor(propname, []) this.changeValueInArrayFor(propname, list) console.log( 'list after is' ) console.dir( this.model[propname] ) this.onItemChange( {model: {item: this.model}} ) } } this.onModelChanged(this.model) }, onSelectReference: function(propname, item) { console.log('=======*** spin-model onSelectReference called') console.dir(item) this.model[propname] = item.id this.onItemChange({model:{item:this.model}}) }, onDialogSelect: function(item) { console.log('======= spin-model onDialogSelect called') console.dir(item) var prop = this.modeldialogitem console.log('saved prop is') console.dir(prop) //this.model[prop.name].push(item) console.log('======= pushing '+item.type+' '+item.id+' onto array property '+prop.key) var i = this.getIndexInArrayFor(prop.key) console.log('index for '+prop.key+' is '+i) var arr = this.array[i].value console.log('existing array for '+prop.key+' is '+arr) arr.push(item.id) this.changeValueInArrayFor(prop.key, []) this.changeValueInArrayFor(prop.key, arr) //this.notifyPath('array.'+i+'.value') var type = this.getTypeFor(prop) console.log('======= spin-model added new object to array property '+type) console.dir(this.model[prop.key]) var id = "addmodeldialog_"+this.model.id+"_"+type var dialog = this.$$('#'+id) dialog.close() }, changeValueInArrayFor:function(propname, value) { var idx = this.getIndexInArrayFor(propname) if(idx > -1) { this.set('array.'+idx+'.value', value) } }, getIndexInArrayFor:function(propname) { var idx = -1 this.array.forEach(function(el, i) { if(el.key == propname) { idx = i } }) return idx }, saveModel: function() { this.onItemChange({model:{item: {}}}) }, onItemChange: function(e) { console.log('-------------------- spin-model onItemChange called.') console.dir(this.model) this.client.emitMessage({target: '_update'+this.model.type, obj: this.model, type: this.model.type}).then(function(ures) { console.log('spin-model update result: '+ures) }.bind(this)) }, onModelChanged: function(newmodel) { //console.log('spin-model onModelChanged called') //console.dir(newmodel) //console.log('---------------------------spin-model: i18n is') //console.dir(this.i18n) if(newmodel && newmodel.id) { this.doshow = true } if(newmodel && !this.modelproperties && this.client) { this.client.emitMessage({target: 'getModelFor', modelname: newmodel.type}).then(function(mprops) { console.log('======================= spin-mode.onModelChanged getModelFor returns ') console.dir(mprops) this.set('modelproperties', mprops) this.set('model', this.model) this.notifyPath('model', this.model) }.bind(this)) } }, onSelect: function(e) { console.log('onSelect called at spin-model') var item = e.model.p if(this.incallbacks && this.incallbacks.onSelect) { this.incallbacks.onSelect(item) } this.set('selectedlistitem', item) }, onDelete:function(e) { console.log('onDelete called at spin-model') var item = e.model.p if(this.incallbacks && this.incallbacks.onDelete) { this.incallbacks.onDelete(item) } }, }); </script> </dom-module>