return {
nameSpace: modelName.prefix(),
type: modelName.suffix(),
- prefix: this.id,
+ id: this.id,
action: action
};
},
var K = XT.Session,
schemas = XT.session.getSchemas(),
parse;
-
+
// A hack to undo damage done by Backbone inside
// save function. For use with options that have
// collections. See XT.DataSource for the other
}
}
}
+
return obj;
};
- return parse(this.recordType.prefix(), this.recordType.suffix(), resp);
+
+ this._lastParse = parse(this.recordType.prefix(), this.recordType.suffix(), resp);
+ return this._lastParse;
},
relationAdded: function (model, related, options) {
model.on(evt, replaceId);
},
+ /**
+ Revert a model back to its original state the last time it was fetched.
+ */
+ revert: function () {
+ var K = XM.Model;
+
+ this.clear({silent: true});
+ this.setStatus(K.BUSY_FETCHING);
+ this.set(this._lastParse, {silent: true});
+ this.setStatus(K.READY_CLEAN, {cascade: true});
+ },
+
/**
Revert the model to the previous status. Useful for reseting status
after a failed validation.
});
// #refactor XXX if this is a bona fide Backbone Relational relation,
// events will propagate automatically from child to parent.
- parent.changed[parentRelation.reverseRelation.key] = true;
- parent.trigger('change', parent, options);
+ if (parentRelation) {
+ parent.changed[parentRelation.reverseRelation.key] = true;
+ parent.trigger('change', parent, options);
+ }
}
this.release();
// Handle both `"key", value` and `{key: value}` -style arguments.
if (_.isObject(key) || _.isEmpty(key)) { value = options; }
- // Call the super version
- this.setStatus(K.BUSY_COMMITTING, options);
+ if (options.collection) {
+ options.collection.each(function (model) {
+ model.setStatus(K.BUSY_COMMITTING, options);
+ });
+ } else {
+ this.setStatus(K.BUSY_COMMITTING, options);
+ }
+
// allow the caller to pass in a different save function to call
result = options.prototypeSave ?
options.prototypeSave.call(this, key, value, options) :
using the carousel arranger and fitted to the size of the viewport.<br />
Its components can be extended via {@link XV.ExtensionsMixin}.<br />
Derived from <a href="http://enyojs.com/api/#enyo.FittableRows">enyo.FittableRows</a>.
+
+ Supported properties on the action array are:
+ * name
+ * label: Menu label. Defaults to name if not present.
+ * privilege: The privilege required by the user to enable the menu. Defaults enabled if not present.
+ * prerequisite: A function on the model that returns a boolean dictating whether to show the menu item or not.
+ * method: The function to call. Defaults to name if not present.
+ * isViewMethod: Boolean value dictates whether method is called on the view or the view's model. Default false.
+
@extends enyo.FittableRows
@extends XV.EditorMixin
@extends XV.ExtensionsMixin
kind: "FittableRows",
modelView: "EnyoView",
published: {
+ actions: null,
actionButtons: null,
title: "_none".loc(),
headerAttrs: null,
recordId: null,
saveText: "_save".loc(),
backText: "_back".loc(),
+ hideSaveAndNew: false,
hideApply: false,
hideRefresh: false,
dirtyWarn: true,
onLockChange: "",
onMenuChange: "",
onNotify: "",
- onSaveTextChange: ""
+ onSaveTextChange: "",
+ onTransactionList: "",
+ onWorkspace: ""
},
handlers: {
onValueChange: "controlValueChanged"
this.processExtensions();
this.titleChanged();
- this.setPrintAvailable(XT.session.config.printServer);
},
/**
@todo Document the destroy method.
kind: "XV.GridPanels",
published: {
menuItems: [],
- allowNew: true
+ allowNew: true,
},
events: {
onPrevious: "",
{kind: "FittableRows", name: "navigationPanel", classes: "left", components: [
{kind: "onyx.Toolbar", name: "menuToolbar", components: [
{kind: "onyx.Button", name: "backButton",
- content: "_back".loc(), onclick: "close"}
+ content: "_back".loc(), onclick: "close"},
+ {kind: "onyx.MenuDecorator", style: "margin: 0;", onSelect: "actionSelected",
+ components: [
+ {kind: "XV.IconButton", src: "/assets/menu-icon-gear.png",
+ content: "_actions".loc(), name: "actionButton",
+ classes: "xv-action-icon"},
+ {kind: "onyx.Menu", name: "actionMenu", maxHeight: 900}
+ ]}
]},
{name: "loginInfo", content: "", classes: "xv-navigator-header"},
{name: "menu", kind: "List", fit: true, touch: true,
]}
]}
],
- allowNewChanged: function (allowNew) {
+ actionSelected: function (inSender, inEvent) {
+ // Could have come from an action, or a an action button
+ var selected = inEvent.selected || inEvent.originator;
+
+ // If it's a view method then call call function on the workspace.
+ if (selected.isViewMethod) {
+ this.$.workspace[selected.method](inEvent);
+
+ // Otherwise call it on the workspace's model.
+ } else {
+ this.$.workspace.getValue()[selected.method]();
+ }
+ },
+ allowNewChanged: function () {
+ var allowNew = this.getAllowNew();
+
if (allowNew) {
this.$.saveAndNewButton.show();
} else {
callback: callback
});
},
+ buildMenus: function () {
+ var actionMenu = this.$.actionMenu,
+ workspace = this.$.workspace,
+ actions = workspace.getActions(),
+ actionButtons = workspace.getActionButtons(),
+ model = workspace.getValue(),
+ that = this,
+ count = 0;
+
+ // Handle menu actions
+ if (actions) {
+
+ // Reset the menu
+ actionMenu.destroyClientControls();
+
+ // Add whatever actions are applicable to the current context.
+ _.each(actions, function (action) {
+ var name = action.name,
+ prerequisite = action.prerequisite,
+ privilege = action.privilege,
+ isDisabled = privilege ? !XT.session.privileges.get(privilege) : false;
+
+ // Only create menu item if prerequisites are met.
+ if (!prerequisite || model[prerequisite]()) {
+ actionMenu.createComponent({
+ name: name,
+ kind: XV.MenuItem,
+ content: action.label || ("_" + name).loc(),
+ method: action.method || action.action || name,
+ disabled: isDisabled,
+ isViewMethod: action.isViewMethod
+ });
+ count++;
+ }
+
+ });
+
+ if (actions.length && !count) {
+ actionMenu.createComponent({
+ name: "noActions",
+ kind: XV.MenuItem,
+ content: "_noEligibleActions".loc(),
+ disabled: true
+ });
+ }
+
+ actionMenu.render();
+ this.$.actionButton.setShowing(actions.length);
+ }
+
+ // Handle button actions
+ if (actionButtons) {
+ _.each(actionButtons, function (action) {
+ var privs = XT.session.privileges,
+ noPriv = action.privilege ? !privs.get(action.privilege): false,
+ noCanDo = action.prerequisite ? !model[action.prerequisite]() : false;
+
+ that.$[action.name].setDisabled(noPriv || noCanDo);
+ });
+ }
+ },
create: function () {
this.inherited(arguments);
this.setLoginInfo();
if (workspace.value.getStatus() === XM.Model.READY_DIRTY &&
!workspace.getModelAmnesty()) {
- // Refresh because this model may be referenced elsewhere
+ // Revert because this model may be referenced elsewhere
_setBindings(this.$.workspace, "off");
- this.$.workspace.fetch({success: callback, obtainLock: false});
+ model.revert();
+ }
+
+ if (model && model.hasLockKey && model.hasLockKey()) {
+ model.releaseLock({
+ success: function () {
+ that.doPrevious();
+ },
+ error: function () {
+ XT.log("Error releasing lock");
+ that.doPrevious();
+ }
+ });
} else {
- callback();
+ that.doPrevious();
}
},
/**
// else see if the workspace has a specific implementation
this.$.workspace.handleHotKey(keyCode);
},
- handleWorkspaceEvent: function (inSender, inEvent) {
- if (inEvent.originator.isViewMethod) {
- this.$.workspace[inEvent.originator.associatedMethod]();
- } else {
- this.$.workspace.value[inEvent.originator.associatedMethod]();
- }
- },
/**
@todo Document the headerChanged method.
*/
save: function (options) {
var workspace = this.$.workspace,
print = workspace.printOnSaveSetting &&
- workspace.getPrintAvailable() &&
+ XT.session.config.printAvailable &&
XT.session.settings.get(workspace.printOnSaveSetting);
if (!this._saveState) { this._saveState = SAVE_APPLY; }
workspace.save(options);
id = options.id,
callback = options.callback,
// if the options do not specify allowNew, default it to true
- allowNew = options.allowNew === false ? false : true,
+ allowNew,
attributes = options.attributes;
if (workspace) {
fit: true,
callback: callback
};
- this.setAllowNew(allowNew);
+
workspace = this.createComponent(workspace);
+
+ // Handle save and new button
+ allowNew = _.isBoolean(options.allowNew) ?
+ options.allowNew : !workspace.getHideSaveAndNew();
+ this.setAllowNew(allowNew);
+
headerAttrs = workspace.getHeaderAttrs() || [];
if (headerAttrs.length) {
this.$.header.show();
}
// Show the print & report button if this workspace is set up to have it
- this.$.printButton.setShowing(workspace.allowPrint && workspace.printAvailable);
- this.$.reportButton.setShowing(workspace.allowPrint && workspace.printAvailable);
+ this.$.printButton.setShowing(workspace.allowPrint && XT.session.config.printAvailable);
+ this.$.reportButton.setShowing(workspace.allowPrint && XT.session.config.printAvailable);
// Set the button texts
this.$.saveButton.setContent(workspace.getSaveText());
this.$.refreshButton.hide();
}
- _.each(this.$.workspace.actionButtons, function (buttonDesc) {
- that.$.contentToolbar.createComponent({kind: "onyx.Button", content: buttonDesc.label,
- associatedMethod: buttonDesc.method, isViewMethod: buttonDesc.isViewMethod,
- ontap: "handleWorkspaceEvent"}, {owner: that});
+ // Handle any extra action buttons specified
+ _.each(this.$.workspace.actionButtons, function (action) {
+ that.$.contentToolbar.createComponent(
+ {kind: "onyx.Button",
+ name: action.name,
+ content: action.label || ("_" + action.name).loc(),
+ method: action.method || action.name,
+ isViewMethod: action.isViewMethod,
+ ontap: "actionSelected"},
+ {owner: that});
});
this.render();
} else {
this.spinnerHide();
}
+
+ this.buildMenus();
},
/**
@todo Document titleChanged method.