857 lines
20 KiB
JavaScript
857 lines
20 KiB
JavaScript
/*
|
|
* Axelor Business Solutions
|
|
*
|
|
* Copyright (C) 2005-2019 Axelor (<http://axelor.com>).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
(function() {
|
|
|
|
"use strict";
|
|
|
|
var ui = angular.module('axelor.ui');
|
|
|
|
ui.controller('SearchViewCtrl', SearchViewCtrl);
|
|
|
|
SearchViewCtrl.$inject = ['$scope', '$element', '$http', 'DataSource', 'ViewService', 'MenuService'];
|
|
function SearchViewCtrl($scope, $element, $http, DataSource, ViewService, MenuService) {
|
|
|
|
var view = $scope._views.search || {};
|
|
|
|
$scope._dataSource = DataSource.create('multi-search');
|
|
|
|
$scope.$applyAsync(function(){
|
|
if (view.deferred)
|
|
view.deferred.resolve($scope);
|
|
});
|
|
|
|
function fixFields(fields) {
|
|
_.each(fields, function(field){
|
|
if (field.type == 'reference') {
|
|
field.type = 'MANY_TO_ONE';
|
|
field.canNew = false;
|
|
field.canEdit = false;
|
|
}
|
|
|
|
if (field.type)
|
|
field.type = field.type.toUpperCase();
|
|
else
|
|
field.type = 'STRING';
|
|
});
|
|
return fields;
|
|
}
|
|
|
|
$scope.show = function(viewPromise) {
|
|
if (!viewPromise) {
|
|
viewPromise = $scope.loadView('search', view.name);
|
|
viewPromise.success(function(fields, schema){
|
|
$scope.initView(schema);
|
|
});
|
|
}
|
|
|
|
$scope.onShow(viewPromise);
|
|
};
|
|
|
|
$scope.onShow = function() {
|
|
|
|
};
|
|
|
|
$scope.initView = function(schema) {
|
|
|
|
var params = $scope._viewParams;
|
|
|
|
$scope._searchFields = fixFields(schema.searchFields);
|
|
$scope._resultFields = fixFields(schema.resultFields);
|
|
|
|
$scope._searchView = schema;
|
|
$scope._showSingle = params.params && params.params.showSingle;
|
|
$scope._forceEdit = params.params && params.params.forceEdit;
|
|
$scope._hideActions = params.params && params.params.hideActions;
|
|
|
|
$scope.updateRoute();
|
|
|
|
if (params.options && params.options.mode == "search") {
|
|
$scope.setRouteOptions(params.options);
|
|
}
|
|
|
|
};
|
|
|
|
$scope.getRouteOptions = function() {
|
|
var args = [],
|
|
query = $scope._routeSearch;
|
|
|
|
return {
|
|
mode: 'search',
|
|
args: args,
|
|
query: query
|
|
};
|
|
};
|
|
|
|
$scope._routeSearch = null;
|
|
var onNewCalled = false;
|
|
$scope.setRouteOptions = function(options) {
|
|
var opts = options || {},
|
|
fields = $scope._searchFields || [],
|
|
search = opts.search,
|
|
record = {};
|
|
|
|
var changed = !angular.equals($scope._routeSearch, search);
|
|
|
|
$scope._routeSearch = search;
|
|
|
|
if (!onNewCalled && _.isEmpty(search)) {
|
|
onNewCalled = true;
|
|
scopes.form.$broadcast('on:new');
|
|
}
|
|
if (!search || _.isEmpty(search) || !changed) {
|
|
return $scope.updateRoute();
|
|
}
|
|
|
|
_.each(fields, function(field) {
|
|
var value = search[field.name];
|
|
if (value === undefined) {
|
|
return;
|
|
}
|
|
if (field.target) {
|
|
if (value) {
|
|
record[field.name] = {id: +value};
|
|
}
|
|
} else {
|
|
record[field.name] = value;
|
|
}
|
|
});
|
|
|
|
if (search.objects) {
|
|
scopes.toolbar.editRecord({
|
|
objectSelect: search.objects
|
|
});
|
|
}
|
|
|
|
scopes.form.editSearch(record, fields);
|
|
|
|
function _doSearch() {
|
|
var promise = $scope.doSearch();
|
|
if (promise && promise.then && $scope._showSingle) {
|
|
promise.then(function () {
|
|
var items = scopes.grid.getItems();
|
|
if (items && items.length === 1) {
|
|
scopes.grid.selection = [0];
|
|
scopes.grid.onEdit();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
var promise = scopes.toolbar._viewPromise;
|
|
if (promise && promise.then) {
|
|
promise.then(function() {
|
|
$scope.$timeout(_doSearch);
|
|
});
|
|
} else {
|
|
_doSearch();
|
|
}
|
|
|
|
};
|
|
|
|
var scopes = {};
|
|
$scope._register = function(key, scope) {
|
|
scopes[key] = scope;
|
|
};
|
|
|
|
$scope.doSearch = function() {
|
|
var params = _.extend({}, scopes.form.record),
|
|
empty = _.chain(params).values().compact().isEmpty().value();
|
|
if (empty)
|
|
return $scope.doClear();
|
|
|
|
var selected = (scopes.toolbar.record || {}).objectSelect;
|
|
|
|
_.extend(params,{
|
|
__name: view.name,
|
|
__selected: _.isEmpty(selected) ? null : selected.split(/,\s*/)
|
|
});
|
|
|
|
var promise = $http.post('ws/search', {
|
|
limit: view.limit || 80,
|
|
data: params
|
|
});
|
|
|
|
return promise.then(function(response){
|
|
var res = response.data,
|
|
records = res.data || [];
|
|
|
|
// slickgrid expects unique `id` so generate them and store original one
|
|
_.each(records, function(rec, i){
|
|
rec._id = rec.id;
|
|
rec.id = i + 1;
|
|
});
|
|
|
|
scopes.grid.setItems(records);
|
|
|
|
if (scopes.form.$events.onLoad) {
|
|
scopes.form.record._count = records.length;
|
|
scopes.form.record._countByModels = _.countBy(records, function(rec) {
|
|
return rec._model;
|
|
});
|
|
scopes.form.$events.onLoad();
|
|
}
|
|
|
|
if (_.isEmpty(records)) {
|
|
axelor.notify.info(_t("No records found."));
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
$scope.doClear = function(all) {
|
|
scopes.form.edit(null);
|
|
scopes.form.$broadcast('on:new');
|
|
scopes.grid.setItems([]);
|
|
if (all) {
|
|
scopes.toolbar.edit(null);
|
|
scopes.toolbar.doReset();
|
|
}
|
|
};
|
|
|
|
$scope.doAction = function() {
|
|
|
|
var action = scopes.toolbar.getMenuAction();
|
|
if (!action) {
|
|
return;
|
|
}
|
|
|
|
var grid = scopes.grid,
|
|
index = _.first(grid.selection),
|
|
record = grid.getItem(index);
|
|
|
|
action = action.action;
|
|
record = _.extend({
|
|
_action: action
|
|
}, record);
|
|
|
|
record.id = record._id;
|
|
|
|
MenuService.action(action).success(function(result){
|
|
|
|
if (!result.data) {
|
|
return;
|
|
}
|
|
|
|
var view = result.data[0].view;
|
|
var tab = view;
|
|
|
|
tab.action = _.uniqueId('$act');
|
|
tab.viewType = 'form';
|
|
|
|
tab.context = _.extend({}, tab.context, {
|
|
_ref : record
|
|
});
|
|
|
|
$scope.openTab(tab);
|
|
});
|
|
};
|
|
}
|
|
|
|
ui.controller('SearchFormCtrl', SearchFormCtrl);
|
|
|
|
SearchFormCtrl.$inject = ['$scope', '$element', 'ViewService'];
|
|
function SearchFormCtrl($scope, $element, ViewService) {
|
|
|
|
ui.FormViewCtrl.call(this, $scope, $element);
|
|
$scope._register('form', $scope);
|
|
$scope.setEditable();
|
|
|
|
// prevent requesting defaults
|
|
$scope.defaultValues = {};
|
|
|
|
$scope.$watch('_searchView', function searchSchemaWatch(schema) {
|
|
if (!schema) return;
|
|
var form = {
|
|
title: 'Search',
|
|
type: 'form',
|
|
cols: 1,
|
|
items: [{
|
|
type: 'panel',
|
|
title: schema.title,
|
|
items: schema.searchFields
|
|
}]
|
|
};
|
|
|
|
var meta = { fields: schema.searchFields };
|
|
ViewService.process(meta, schema.searchForm);
|
|
|
|
function process(item) {
|
|
if (item.items || item.pages) {
|
|
return _.each(item.items || item.pages, process);
|
|
}
|
|
switch (item.widget) {
|
|
case 'ManyToOne':
|
|
case 'OneToOne':
|
|
case 'SuggestBox':
|
|
item.canNew = false;
|
|
item.canEdit = false;
|
|
break;
|
|
case 'OneToMany':
|
|
case 'ManyToMany':
|
|
case 'MasterDetail':
|
|
item.hidden = true;
|
|
}
|
|
}
|
|
|
|
if (schema.searchForm && schema.searchForm.items) {
|
|
_.each(schema.searchForm.items, process);
|
|
}
|
|
|
|
$scope.fields = meta.fields;
|
|
$scope.schema = schema.searchForm || form;
|
|
$scope.schema.loaded = true;
|
|
});
|
|
|
|
var model = null;
|
|
var getContext = $scope.getContext;
|
|
|
|
$scope.getContext = function() {
|
|
var view = $scope._searchView || {};
|
|
if (model === null && view.selects) {
|
|
model = (_.first(view.selects) || {}).model;
|
|
}
|
|
|
|
var ctx = getContext.apply(this, arguments) || {};
|
|
ctx._model = model;
|
|
return ctx;
|
|
};
|
|
|
|
$scope.editSearch = function (record, fields) {
|
|
$scope.editRecord(record);
|
|
setTimeout(function () {
|
|
_.each(fields, function (field) {
|
|
if (!field.target || !$scope.record) return;
|
|
var item = $element.find('[x-field=' + field.name + ']');
|
|
var itemScope = item.data('$scope');
|
|
var value = itemScope.getValue();
|
|
if (value && itemScope && !itemScope.text && itemScope.select) {
|
|
itemScope.select(value);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
}
|
|
|
|
ui.controller('SearchGridCtrl', SearchGridCtrl);
|
|
|
|
SearchGridCtrl.$inject = ['$scope', '$element', 'ViewService', '$interpolate'];
|
|
function SearchGridCtrl($scope, $element, ViewService, $interpolate) {
|
|
|
|
ui.GridViewCtrl.call(this, $scope, $element);
|
|
$scope._register('grid', $scope);
|
|
|
|
var viewTitles = {};
|
|
|
|
$scope.$watch('_searchView', function searchSchemaWatch(schema) {
|
|
if (!schema) return;
|
|
var view = {
|
|
title: 'Search',
|
|
type: 'grid',
|
|
editIcon: true,
|
|
items: []
|
|
};
|
|
|
|
var objItem = _.findWhere(schema.resultFields, {name: 'object'});
|
|
if (!objItem) {
|
|
view.items.push(objItem = {});
|
|
}
|
|
|
|
objItem = _.extend(objItem, { name : '_modelTitle', title: _t('Object') });
|
|
view.items = view.items.concat(schema.resultFields);
|
|
|
|
if (+(objItem.width) === 0) {
|
|
objItem.hidden = true;
|
|
}
|
|
|
|
var meta = { fields: schema.resultFields };
|
|
ViewService.process(meta);
|
|
|
|
_.each(schema.selects, function (select) {
|
|
viewTitles[select.model] = select.viewTitle;
|
|
});
|
|
|
|
_.each(view.items, function (item) {
|
|
if (item.width) {
|
|
objItem.width = objItem.width || 220;
|
|
}
|
|
});
|
|
|
|
$scope.fields = meta.fields;
|
|
$scope.schema = view;
|
|
$scope.schema.loaded = true;
|
|
});
|
|
|
|
$scope.onEdit = function(force) {
|
|
|
|
var index = _.first(this.selection),
|
|
records = this.getItems(),
|
|
record = this.getItem(index),
|
|
ids, domain, views;
|
|
|
|
ids = _.chain(records).filter(function(rec){
|
|
return rec._model == record._model;
|
|
}).pluck('_id').value();
|
|
|
|
domain = "self.id IN (" + ids.join(',') + ")";
|
|
|
|
views = _.map(['form', 'grid'], function(type){
|
|
var view = { type : type };
|
|
var name = record["_" + type];
|
|
if (name) view.name = name;
|
|
return view;
|
|
});
|
|
|
|
if (force === undefined) {
|
|
force = $scope._forceEdit;
|
|
}
|
|
|
|
var title = viewTitles[record._model];
|
|
if (title) {
|
|
title = $interpolate(title)(record);
|
|
}
|
|
|
|
var tab = {
|
|
action: _.uniqueId('$act'),
|
|
model: record._model,
|
|
title: title || record._modelTitle,
|
|
forceTitle: true,
|
|
domain: domain,
|
|
recordId: record._id,
|
|
forceEdit: force,
|
|
viewType: 'form',
|
|
views: views
|
|
};
|
|
|
|
this.openTab(tab);
|
|
};
|
|
|
|
$scope.onSort = function(event, args) {
|
|
var grid = args.grid;
|
|
var data = grid.getData();
|
|
var sortCols = args.sortCols;
|
|
|
|
var types = {};
|
|
|
|
_.each($scope.fields, function (field) {
|
|
types[field.name] = field.type;
|
|
});
|
|
|
|
data.sort(function(dataRow1, dataRow2) {
|
|
for (var i = 0, l = sortCols.length; i < l; i++) {
|
|
var name = sortCols[i].sortCol.field;
|
|
var sign = sortCols[i].sortAsc ? 1 : -1;
|
|
var value1 = dataRow1[name], value2 = dataRow2[name];
|
|
|
|
switch (types[name]) {
|
|
case "integer":
|
|
case "long":
|
|
value1 = value1 || 0;
|
|
value2 = value2 || 0;
|
|
break;
|
|
default:
|
|
value1 = value1 || "";
|
|
value2 = value2 || "";
|
|
}
|
|
|
|
var result = (value1 == value2 ? 0 : (value1 > value2 ? 1 : -1)) * sign;
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
grid.invalidate();
|
|
grid.render();
|
|
};
|
|
}
|
|
|
|
ui.controller('SearchToolbarCtrl', SearchToolbarCtrl);
|
|
|
|
SearchToolbarCtrl.$inject = ['$scope', '$element', '$http'];
|
|
function SearchToolbarCtrl($scope, $element, $http) {
|
|
|
|
ui.FormViewCtrl.call(this, $scope, $element);
|
|
$scope._register('toolbar', $scope);
|
|
$scope.setEditable();
|
|
|
|
var menus = {};
|
|
|
|
function fetch(key, parent, request, response) {
|
|
|
|
if (menus[key]) {
|
|
return response(menus[key]);
|
|
}
|
|
|
|
var promise = $http.get('ws/search/menu', {
|
|
params: {
|
|
parent: parent
|
|
}
|
|
});
|
|
promise.then(function(res){
|
|
var data = res.data.data;
|
|
data = _.map(data, function(item){
|
|
return {
|
|
value: item.name,
|
|
action: item.action,
|
|
label: item.title
|
|
};
|
|
});
|
|
menus[key] = data;
|
|
response(data);
|
|
});
|
|
}
|
|
|
|
$scope.fetchRootMenus = function(request, response) {
|
|
fetch('menuRoot', null, request, response);
|
|
};
|
|
|
|
$scope.fetchSubMenus = function(request, response) {
|
|
fetch('menuSub', $scope.record.menuRoot, request, response);
|
|
};
|
|
|
|
$scope.fetchItemMenus = function(request, response) {
|
|
fetch('menuItem', $scope.record.menuSub, request, response);
|
|
};
|
|
|
|
$scope.resetSelector = function(a, b) {
|
|
_.each(arguments, function(name){
|
|
if (_.isString(name)) {
|
|
$scope.record[name] = null;
|
|
menus[name] = null;
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.getMenuAction = function() {
|
|
return _.find(menus.menuItem, function(item){
|
|
return item.value === $scope.record.menuItem;
|
|
});
|
|
};
|
|
|
|
$scope.$watch('_searchView', function searchSchemaWatch(schema) {
|
|
|
|
if (!schema) {
|
|
return;
|
|
}
|
|
|
|
var selected = [];
|
|
|
|
$scope.fields = {
|
|
'objectSelect' : {
|
|
type : 'string',
|
|
placeholder: _t('Search Objects'),
|
|
multiple : true,
|
|
selectionList : _.map(schema.selects, function(x) {
|
|
if (x.selected) {
|
|
selected.push(x.model);
|
|
}
|
|
return {
|
|
value : x.model,
|
|
title : x.title
|
|
};
|
|
})
|
|
},
|
|
'menuRoot' : {
|
|
type : 'string',
|
|
placeholder: _t('Action Category'),
|
|
widget: 'select-query',
|
|
attrs: {
|
|
query: 'fetchRootMenus',
|
|
'ng-change': 'resetSelector("menuSub", "menuItem")'
|
|
}
|
|
},
|
|
'menuSub' : {
|
|
placeholder: _t('Action Sub-Category'),
|
|
widget: 'select-query',
|
|
attrs: {
|
|
query: 'fetchSubMenus',
|
|
'ng-change': 'resetSelector($event, "menuItem")'
|
|
}
|
|
},
|
|
'menuItem' : {
|
|
placeholder: _t('Action'),
|
|
widget: 'select-query',
|
|
attrs: {
|
|
query: 'fetchItemMenus'
|
|
}
|
|
}
|
|
};
|
|
|
|
var items1 = [{
|
|
name : 'objectSelect',
|
|
showTitle : false,
|
|
colSpan: 8
|
|
}, {
|
|
type : 'button',
|
|
title : _t('Search'),
|
|
colSpan: 2,
|
|
attrs: {
|
|
'ng-click': 'doSearch()'
|
|
}
|
|
}, {
|
|
type : 'button',
|
|
title : _t('Clear'),
|
|
colSpan: 2,
|
|
attrs: {
|
|
'ng-click': 'doClear(true)'
|
|
}
|
|
}];
|
|
|
|
var items2 = [{
|
|
name : 'menuRoot',
|
|
showTitle : false,
|
|
colSpan: 3
|
|
}, {
|
|
name : 'menuSub',
|
|
showTitle : false,
|
|
colSpan: 3
|
|
}, {
|
|
name : 'menuItem',
|
|
showTitle : false,
|
|
colSpan: 4
|
|
}, {
|
|
type : 'button',
|
|
title : _t('Go'),
|
|
colSpan: 2,
|
|
attrs: {
|
|
'ng-click': 'doAction()'
|
|
}
|
|
}];
|
|
|
|
var item1 = {
|
|
type: "panel",
|
|
colSpan: $scope._hideActions ? 12 : 6,
|
|
items: items1
|
|
};
|
|
|
|
var item2 = {
|
|
type: "panel",
|
|
colSpan: 6,
|
|
items: items2
|
|
};
|
|
|
|
schema = {
|
|
type : 'form',
|
|
items: [{
|
|
type: 'panel',
|
|
items: $scope._hideActions ? [item1] : [item1, item2]
|
|
}]
|
|
};
|
|
|
|
$scope.schema = schema;
|
|
$scope.schema.loaded = true;
|
|
|
|
$scope.doReset = function () {
|
|
var record = $scope.record || {};
|
|
if (selected.length > 0 && _.isEmpty(record.objectSelect)) {
|
|
record.objectSelect = selected.join(', ');
|
|
$scope.edit(record);
|
|
}
|
|
};
|
|
|
|
$scope.$timeout($scope.doReset);
|
|
});
|
|
}
|
|
|
|
angular.module('axelor.ui').directive('uiViewSearch', function(){
|
|
return {
|
|
controller: SearchViewCtrl,
|
|
link: function(scope, element, attrs, ctrl) {
|
|
|
|
element.on('keypress', '.search-view-form form:first', function(event){
|
|
if (event.keyCode == 13 && $(event.target).is('input')){
|
|
scope.doSearch();
|
|
}
|
|
});
|
|
|
|
var grid = element.children('.search-view-grid');
|
|
scope.$onAdjust(function(){
|
|
if (!element.is(':visible'))
|
|
return;
|
|
grid.height(element.height() - grid.position().top);
|
|
});
|
|
}
|
|
};
|
|
});
|
|
|
|
// ActionSelector (TODO: re-use search view toolbar)
|
|
|
|
ActionSelectorCtrl.$inject = ['$scope', '$element', '$attrs', '$http', 'MenuService'];
|
|
function ActionSelectorCtrl($scope, $element, $attrs, $http, MenuService) {
|
|
|
|
ui.FormViewCtrl.call(this, $scope, $element);
|
|
var menus = {},
|
|
category = $attrs.category;
|
|
|
|
function fetch(key, request, response, params) {
|
|
|
|
if (menus[key]) {
|
|
return response(menus[key]);
|
|
}
|
|
|
|
var promise = $http.get('ws/search/menu', {
|
|
params: params
|
|
});
|
|
promise.then(function(res){
|
|
var data = res.data.data;
|
|
data = _.map(data, function(item){
|
|
return {
|
|
value: item.name,
|
|
action: item.action,
|
|
label: item.title
|
|
};
|
|
});
|
|
menus[key] = data;
|
|
response(data);
|
|
});
|
|
}
|
|
|
|
$scope.fetchRootMenus = function(request, response) {
|
|
fetch('$menuRoot', request, response, {
|
|
parent: '',
|
|
category: category
|
|
});
|
|
};
|
|
|
|
$scope.fetchSubMenus = function(request, response) {
|
|
if (!$scope.record.$menuRoot) return;
|
|
fetch('$menuSub', request, response, {
|
|
parent: $scope.record.$menuRoot
|
|
});
|
|
};
|
|
|
|
$scope.fetchItemMenus = function(request, response) {
|
|
if (!$scope.record.$menuSub) return;
|
|
fetch('$menuItem', request, response, {
|
|
parent: $scope.record.$menuSub
|
|
});
|
|
};
|
|
|
|
$scope.resetSelector = function(a, b) {
|
|
_.each(arguments, function(name){
|
|
if (_.isString(name)) {
|
|
$scope.record[name] = null;
|
|
menus[name] = null;
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.getMenuAction = function() {
|
|
return _.find(menus.$menuItem, function(item){
|
|
return item.value === $scope.record.$menuItem;
|
|
});
|
|
};
|
|
|
|
$scope.doAction = function() {
|
|
|
|
var action = $scope.getMenuAction();
|
|
if (!action) {
|
|
return;
|
|
}
|
|
|
|
var context = $scope.$parent.getContext(),
|
|
record;
|
|
|
|
action = action.action;
|
|
record = {
|
|
id : context.id,
|
|
_action: action,
|
|
_model: context._model
|
|
};
|
|
|
|
MenuService.action(action).success(function(result){
|
|
|
|
if (!result.data) {
|
|
return;
|
|
}
|
|
|
|
var view = result.data[0].view;
|
|
var tab = view;
|
|
|
|
tab.action = _.uniqueId('$act');
|
|
tab.viewType = 'form';
|
|
|
|
tab.context = _.extend({}, tab.context, {
|
|
_ref : record
|
|
});
|
|
|
|
$scope.openTab(tab);
|
|
});
|
|
};
|
|
|
|
$scope.fields = {
|
|
'$menuRoot' : {
|
|
type : 'string',
|
|
placeholder: _t('Action Category'),
|
|
widget: 'select-query',
|
|
attrs: {
|
|
query: 'fetchRootMenus',
|
|
'ng-change': 'resetSelector("$menuSub", "$menuItem")'
|
|
}
|
|
},
|
|
'$menuSub' : {
|
|
placeholder: _t('Action Sub-Category'),
|
|
type: 'select-query',
|
|
attrs: {
|
|
query: 'fetchSubMenus',
|
|
'ng-change': 'resetSelector($event, "$menuItem")'
|
|
}
|
|
},
|
|
'$menuItem' : {
|
|
placeholder: _t('Action'),
|
|
widget: 'select-query',
|
|
attrs: {
|
|
query: 'fetchItemMenus'
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.schema = {
|
|
cols : 4,
|
|
colWidths : '30%,30%,30%,10%',
|
|
type : 'form',
|
|
items : [ {
|
|
name : '$menuRoot',
|
|
showTitle : false
|
|
}, {
|
|
name : '$menuSub',
|
|
showTitle : false
|
|
}, {
|
|
name : '$menuItem',
|
|
showTitle : false
|
|
}, {
|
|
type : 'button',
|
|
title : _t('Go'),
|
|
attrs: {
|
|
'ng-click': 'doAction()'
|
|
}
|
|
} ]
|
|
};
|
|
}
|
|
|
|
angular.module('axelor.ui').directive('uiActionSelector', function(){
|
|
return {
|
|
scope: true,
|
|
controller: ActionSelectorCtrl,
|
|
template: '<div ui-view-form x-handler="this"></div>'
|
|
};
|
|
});
|
|
|
|
})();
|