diff --git a/platform/commonUI/edit/bundle.json b/platform/commonUI/edit/bundle.json index a9c7ec5094..df6732ceaa 100644 --- a/platform/commonUI/edit/bundle.json +++ b/platform/commonUI/edit/bundle.json @@ -27,6 +27,15 @@ "category": "view-control", "glyph": "p" }, + { + "key": "properties", + "category": "contextual", + "implementation": "actions/PropertiesAction.js", + "glyph": "p", + "name": "Edit Properties...", + "description": "Edit properties of this object.", + "depends": [ "dialogService" ] + }, { "key": "remove", "category": "contextual", diff --git a/platform/commonUI/edit/src/actions/PropertiesAction.js b/platform/commonUI/edit/src/actions/PropertiesAction.js new file mode 100644 index 0000000000..18d2f57586 --- /dev/null +++ b/platform/commonUI/edit/src/actions/PropertiesAction.js @@ -0,0 +1,82 @@ +/*global define*/ + +/** + * Edit the properties of a domain object. Shows a dialog + * which should display a set of properties similar to that + * shown in the Create wizard. + */ +define( + ['./PropertiesDialog'], + function (PropertiesDialog) { + 'use strict'; + + /** + * Construct an action which will allow an object's metadata to be + * edited. + * + * @param {DialogService} dialogService a service which will show the dialog + * @param {DomainObject} object the object to be edited + * @param {ActionContext} context the context in which this action is performed + * @constructor + */ + function PropertiesAction(dialogService, context) { + var object = context.domainObject; + + // Persist modifications to this domain object + function doPersist() { + var persistence = object.getCapability('persistence'); + return persistence && persistence.persist(); + } + + // Update the domain object model based on user input + function updateModel(userInput, dialog) { + return object.useCapability('mutation', function (model) { + dialog.updateModel(model, userInput); + }); + } + + function showDialog(type) { + // Create a dialog object to generate the form structure, etc. + var dialog = new PropertiesDialog(type, object.getModel()); + + // Show the dialog + return dialogService.getUserInput( + dialog.getFormStructure(), + dialog.getInitialFormValue() + ).then(function (userInput) { + // Update the model, if user input was provided + return userInput && updateModel(userInput, dialog); + }).then(function (result) { + return result && doPersist(); + }); + } + + return { + /** + * Perform this action. + * @return {Promise} a promise which will be + * fulfilled when the action has completed. + */ + perform: function () { + var type = object.getCapability('type'); + return type && showDialog(type); + } + }; + } + + /** + * Filter this action for applicability against a given context. + * This will ensure that a domain object is present in the + * context. + */ + PropertiesAction.appliesTo = function (context) { + return (context || {}).domainObject && + (context || {}).domainObject.hasCapability("type") && + (context || {}).domainObject.hasCapability("persistence"); + }; + + return PropertiesAction; + } + +); + diff --git a/platform/commonUI/edit/src/actions/PropertiesDialog.js b/platform/commonUI/edit/src/actions/PropertiesDialog.js new file mode 100644 index 0000000000..6cca10527e --- /dev/null +++ b/platform/commonUI/edit/src/actions/PropertiesDialog.js @@ -0,0 +1,73 @@ +/*global define*/ + +/** + * Defines the PropertiesDialog, used by the PropertiesAction to + * populate the form shown in dialog based on the created type. + * + * @module common/actions/properties-dialog + */ +define( + function () { + 'use strict'; + + /** + * Construct a new Properties dialog. + * + * @param {TypeImpl} type the type of domain object for which properties + * will be specified + * @param {DomainObject} the object for which properties will be set + * @constructor + * @memberof module:common/actions/properties-dialog + */ + function PropertiesDialog(type, model) { + var properties = type.getProperties(); + + return { + /** + * Get sections provided by this dialog. + * @return {FormStructure} the structure of this form + */ + getFormStructure: function () { + return { + name: "Edit " + model.name, + sections: [{ + name: "Properties", + rows: properties.map(function (property, index) { + // Property definition is same as form row definition + var row = Object.create(property.getDefinition()); + row.key = index; + return row; + }) + }] + }; + }, + /** + * Get the initial state of the form shown by this dialog + * (based on the object model) + * @returns {object} initial state of the form + */ + getInitialFormValue: function () { + // Start with initial values for properties + // Note that index needs to correlate to row.key + // from getFormStructure + return properties.map(function (property) { + return property.getValue(model); + }); + }, + /** + * Update a domain object model based on the value of a form. + */ + updateModel: function (model, formValue) { + // Update all properties + properties.forEach(function (property, index) { + property.setValue(model, formValue[index]); + }); + } + }; + + + } + + return PropertiesDialog; + } +); \ No newline at end of file