diff --git a/app/components/file-upload.js b/app/components/file-upload.js new file mode 100644 index 0000000..461df9b --- /dev/null +++ b/app/components/file-upload.js @@ -0,0 +1,19 @@ +/** + * File: file-upload.js + * Author: Markus Grigull + * Date: 05.12.2016 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + +import Ember from 'ember'; +import EmberUploader from 'ember-uploader'; + +export default EmberUploader.FileField.extend({ + files: null, + + filesDidChange: function(files) { + this.set('files', files); + } +}); diff --git a/app/components/widget-image.js b/app/components/widget-image.js new file mode 100644 index 0000000..22a3dc1 --- /dev/null +++ b/app/components/widget-image.js @@ -0,0 +1,106 @@ +/** + * File: widget-image.js + * Author: Markus Grigull + * Date: 05.12.2016 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + +import WidgetAbstract from './widget-abstract'; +import Ember from 'ember'; +import ENV from '../config/environment'; +import EmberUploader from 'ember-uploader'; + +const { + inject: { service }, + RSVP +} = Ember; + +export default WidgetAbstract.extend({ + classNames: [ 'widgetImage' ], + + session: service('session'), + sessionUser: Ember.inject.service('session-user'), + store: service(), + + url: 'http://' + ENV.APP.API_HOST, + namespace: 'api/v1', + + doubleClick() { + if (this.get('editing') === true) { + // prepare modal + this.set('name', this.get('widget.name')); + + // show modal + this.set('isShowingModal', true); + } + }, + + actions: { + submitModal() { + // verify properties + let properties = this.getProperties('name'); + properties.widgetData = { path: this.get('image.path') }; + + this.get('widget').setProperties(properties); + + let self = this; + + this.get('widget').save().then(function() { + self.set('isShowingModal', false); + }); + }, + + cancelModal() { + this.set('isShowingModal', false); + }, + + selectImage(image) { + // get image by path + var self = this; + + this.get('widget.visualization').then((visualization) => { + visualization.get('project').then((project) => { + project.get('owner').then((user) => { + user.get('files').then((files) => { + files.forEach(function(file) { + if (file.get('name') === image) { + // set image + self.set('image', file); + } + }); + }); + }); + }); + }); + }, + + upload() { + // check if any files to upload + let files = this.get('uploadFiles'); + + if (!Ember.isEmpty(files)) { + var uploadURL = this.get('url') + '/' + this.get('namespace') + '/upload'; + + const uploader = EmberUploader.Uploader.create({ + multiple: true, + url: uploadURL, + ajaxSettings: { + headers: { + 'x-access-token': this.get('session.data.authenticated.token') + } + } + }); + + var self = this; + + uploader.upload(files).then(event => { + // reload user + var user = self.get('sessionUser.user'); + self.get('store').findRecord('user', user.get('id')); + }); + } + } + } +}); diff --git a/app/controllers/visualization/edit.js b/app/controllers/visualization/edit.js index 5d7556d..ad31ff4 100644 --- a/app/controllers/visualization/edit.js +++ b/app/controllers/visualization/edit.js @@ -50,7 +50,7 @@ export default Ember.Controller.extend(FetchLiveDataMixin, { properties.type = 'widget-table'; properties.name = "Table"; properties.width = 500; - proeprties.height = 200; + properties.height = 200; properties.widgetData = { simulator: defaultSimulatorid }; } else if (name === 'value') { properties.type = 'widget-value'; @@ -64,6 +64,12 @@ export default Ember.Controller.extend(FetchLiveDataMixin, { properties.width = 500; properties.height = 400; properties.widgetData = { signals: [0], simulator: defaultSimulatorid, type: 'multiple' }; + } else if (name === 'image') { + properties.type = 'widget-image'; + properties.name = 'Image'; + properties.width = 300; + properties.height = 300; + properties.widgetData = { path: null }; } else { // DEBUG console.log('Add unknown widget ' + name); diff --git a/app/models/file.js b/app/models/file.js new file mode 100644 index 0000000..fc7e63a --- /dev/null +++ b/app/models/file.js @@ -0,0 +1,18 @@ +/** + * File: file.js + * Author: Markus Grigull + * Date: 25.01.2017 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + +import DS from 'ember-data'; + +export default DS.Model.extend({ + name: DS.attr('string'), + path: DS.attr('string'), + type: DS.attr('string'), + user: DS.belongsTo('user', { async: true }), + date: DS.attr('date') +}); diff --git a/app/models/user.js b/app/models/user.js index cded992..b2bf6d4 100644 --- a/app/models/user.js +++ b/app/models/user.js @@ -17,5 +17,6 @@ export default Model.extend({ adminLevel: attr('number'), projects: hasMany('project', { async: true }), simulations: hasMany('simulation', { async: true }), - mail: attr('string') + mail: attr('string'), + files: hasMany('file', { async: true }) }); diff --git a/app/templates/components/file-upload.hbs b/app/templates/components/file-upload.hbs new file mode 100644 index 0000000..889d9ee --- /dev/null +++ b/app/templates/components/file-upload.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/app/templates/components/widget-image.hbs b/app/templates/components/widget-image.hbs new file mode 100644 index 0000000..b9b4f0c --- /dev/null +++ b/app/templates/components/widget-image.hbs @@ -0,0 +1,51 @@ +{{#if widget.widgetData.path}} + +{{/if}} + +{{#if isShowingModal}} + {{#modal-dialog attachment="middle center" translucentOverlay=true}} +

Image

+ +
+ + + + + + + + + + + + + + + + +
+ + + {{input id='name' placeholder='Enter widget name' value=name}} +
+ + + +
+ + {{file-upload files=uploadFiles}} +
+ + +
+
+ + {{#if errorMessage}} +

Error: {{errorMessage}}

+ {{/if}} + {{/modal-dialog}} +{{/if}} diff --git a/app/templates/visualization/edit.hbs b/app/templates/visualization/edit.hbs index 4d9d36d..c15d593 100644 --- a/app/templates/visualization/edit.hbs +++ b/app/templates/visualization/edit.hbs @@ -18,6 +18,10 @@ Plot {{/draggable-item}} + {{#draggable-item content='image'}} + Image + {{/draggable-item}} +

Hint: Double click widgets to edit or delete them.

diff --git a/package.json b/package.json index 7cdb0e3..30d5a65 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "ember-simple-auth": "^1.1.0", "ember-tether": "0.3.1", "ember-truth-helpers": "1.2.0", + "ember-uploader": "1.2.3", "loader.js": "^4.0.1" }, "dependencies": {} diff --git a/tests/integration/components/file-upload-test.js b/tests/integration/components/file-upload-test.js new file mode 100644 index 0000000..3c7b795 --- /dev/null +++ b/tests/integration/components/file-upload-test.js @@ -0,0 +1,24 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('file-upload', 'Integration | Component | file upload', { + integration: true +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{file-upload}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#file-upload}} + template block text + {{/file-upload}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/tests/integration/components/widget-image-test.js b/tests/integration/components/widget-image-test.js new file mode 100644 index 0000000..8eace27 --- /dev/null +++ b/tests/integration/components/widget-image-test.js @@ -0,0 +1,24 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('widget-image', 'Integration | Component | widget image', { + integration: true +}); + +test('it renders', function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{widget-image}}`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs` + {{#widget-image}} + template block text + {{/widget-image}} + `); + + assert.equal(this.$().text().trim(), 'template block text'); +}); diff --git a/tests/unit/models/file-test.js b/tests/unit/models/file-test.js new file mode 100644 index 0000000..225d072 --- /dev/null +++ b/tests/unit/models/file-test.js @@ -0,0 +1,12 @@ +import { moduleForModel, test } from 'ember-qunit'; + +moduleForModel('file', 'Unit | Model | file', { + // Specify the other units that are required for this test. + needs: [] +}); + +test('it exists', function(assert) { + let model = this.subject(); + // let store = this.store(); + assert.ok(!!model); +});