mirror of https://github.com/rancher/dashboard.git
279 lines
6.5 KiB
JavaScript
279 lines
6.5 KiB
JavaScript
import { isArray, filterBy, removeObjects, addObjects } from '@/utils/array';
|
|
|
|
export const state = function() {
|
|
return {
|
|
show: false,
|
|
tableSelected: [],
|
|
tableAll: [],
|
|
resources: [],
|
|
elem: null,
|
|
event: null,
|
|
actionOfInterest: null
|
|
};
|
|
};
|
|
|
|
// default to initial state in args below in case something is called before registerModule
|
|
const stateSchema = state();
|
|
|
|
export const getters = {
|
|
showing: (state = stateSchema) => state.show,
|
|
elem: (state = stateSchema) => state.elem,
|
|
event: (state = stateSchema) => state.event,
|
|
tableSelected: (state = stateSchema) => state.tableSelected || [],
|
|
|
|
forTable(state = stateSchema) {
|
|
let disableAll = false;
|
|
let selected = state.tableSelected;
|
|
const all = state.tableAll;
|
|
|
|
if ( !selected ) {
|
|
return [];
|
|
}
|
|
|
|
if ( !selected.length ) {
|
|
if ( !all ) {
|
|
return [];
|
|
}
|
|
|
|
const firstNode = all[0];
|
|
|
|
selected = firstNode ? [firstNode] : [];
|
|
disableAll = true;
|
|
}
|
|
|
|
const map = {};
|
|
|
|
// Find and add all the actions for all the nodes so that we know
|
|
// what all the possible actions are
|
|
for ( const node of all ) {
|
|
if (node.availableActions) {
|
|
for ( const act of node.availableActions ) {
|
|
if ( act.bulkable ) {
|
|
_add(map, act, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Go through all the selected items and add the actions (which were already identified above)
|
|
// as available for some (or all) of the selected nodes
|
|
for ( const node of selected ) {
|
|
if (node.availableActions) {
|
|
for ( const act of node.availableActions ) {
|
|
if ( act.bulkable && act.enabled ) {
|
|
_add(map, act, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there's no items actually selected, we want to see all the actions
|
|
// so you know what exists, but have them all be disabled since there's nothing to do them on.
|
|
const out = _filter(map, disableAll);
|
|
|
|
// Enable a bulkaction if some of the selected items can perform the action
|
|
out.forEach((bulkAction) => {
|
|
const actionEnabledForSomeSelected = state.tableSelected.some((node) => {
|
|
const availableActions = node.availableActions || [];
|
|
|
|
return availableActions.some(action => action.action === bulkAction.action && action.enabled);
|
|
});
|
|
|
|
bulkAction.enabled = state.tableSelected.length > 0 && actionEnabledForSomeSelected;
|
|
});
|
|
|
|
return out.sort((a, b) => (b.weight || 0) - (a.weight || 0));
|
|
},
|
|
|
|
options(state = stateSchema) {
|
|
let selected = state.resources;
|
|
|
|
if ( !selected ) {
|
|
return [];
|
|
}
|
|
|
|
if ( !isArray(selected) ) {
|
|
selected = [];
|
|
}
|
|
|
|
const map = {};
|
|
|
|
for ( const node of selected ) {
|
|
if (node.availableActions) {
|
|
for ( const act of node.availableActions ) {
|
|
_add(map, act);
|
|
}
|
|
}
|
|
}
|
|
|
|
const out = _filter(map);
|
|
|
|
return { ...out };
|
|
},
|
|
|
|
isSelected: (state = stateSchema) => (resource) => {
|
|
return state.tableSelected.includes(resource);
|
|
},
|
|
|
|
canRunBulkActionOfInterest: (state = stateSchema) => (resource) => {
|
|
if (!state.actionOfInterest) {
|
|
return false;
|
|
}
|
|
|
|
const matchingResourceAction = resource.availableActions.find(action => action.action === state.actionOfInterest.action);
|
|
|
|
return matchingResourceAction?.enabled;
|
|
}
|
|
};
|
|
|
|
export const mutations = {
|
|
setTable(state = stateSchema, { table, clearSelection = false }) {
|
|
const selected = state.tableSelected;
|
|
|
|
state.tableAll = table;
|
|
|
|
if ( clearSelection ) {
|
|
state.tableSelected = [];
|
|
} else {
|
|
// Remove items that are no longer visible from the selection
|
|
const toRemove = [];
|
|
|
|
for ( const cur of state.tableSelected ) {
|
|
if ( !table.includes(cur) ) {
|
|
toRemove.push(cur);
|
|
}
|
|
}
|
|
|
|
removeObjects(selected, toRemove);
|
|
}
|
|
},
|
|
|
|
update(state = stateSchema, { toAdd, toRemove }) {
|
|
const selected = state.tableSelected || [];
|
|
|
|
if (toRemove && toRemove.length) {
|
|
removeObjects(selected, toRemove);
|
|
}
|
|
|
|
if (toAdd.length) {
|
|
addObjects(selected, toAdd);
|
|
}
|
|
},
|
|
|
|
show(state = stateSchema, { resources, elem, event }) {
|
|
if ( !isArray(resources) ) {
|
|
resources = [resources];
|
|
}
|
|
|
|
state.resources = resources;
|
|
state.elem = elem;
|
|
state.event = event;
|
|
state.show = true;
|
|
},
|
|
|
|
hide(state = stateSchema) {
|
|
state.show = false;
|
|
state.resources = null;
|
|
state.elem = null;
|
|
},
|
|
|
|
setBulkActionOfInterest(state = stateSchema, action) {
|
|
if (!action || action.enabled) {
|
|
state.actionOfInterest = action;
|
|
}
|
|
},
|
|
};
|
|
|
|
export const actions = {
|
|
executeTable({ state }, { action, args, opts }) {
|
|
const executableSelection = state.tableSelected.filter(getters.canRunBulkActionOfInterest(state));
|
|
|
|
return _execute(executableSelection, action, args, opts);
|
|
},
|
|
|
|
execute({ state }, { action, args }) {
|
|
return _execute(state.resources, action, args);
|
|
},
|
|
};
|
|
|
|
export default {
|
|
state, actions, getters, mutations, namespaced: true
|
|
};
|
|
|
|
// -----------------------------
|
|
|
|
let anon = 0;
|
|
|
|
function _add(map, act, incrementCounts = true) {
|
|
let id = act.action;
|
|
|
|
if ( !id ) {
|
|
id = `anon${ anon }`;
|
|
anon++;
|
|
}
|
|
|
|
let obj = map[id];
|
|
|
|
if ( !obj ) {
|
|
obj = Object.assign({}, act);
|
|
map[id] = obj;
|
|
obj.allEnabled = false;
|
|
}
|
|
|
|
if ( act.enabled === false ) {
|
|
obj.allEnabled = false;
|
|
} else {
|
|
obj.anyEnabled = true;
|
|
}
|
|
|
|
if ( incrementCounts ) {
|
|
obj.available = (obj.available || 0) + (act.enabled === false ? 0 : 1 );
|
|
obj.total = (obj.total || 0) + 1;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function _filter(map, disableAll = false) {
|
|
const out = filterBy(Object.values(map), 'anyEnabled', true);
|
|
|
|
for ( const act of out ) {
|
|
if ( disableAll ) {
|
|
act.enabled = false;
|
|
} else {
|
|
act.enabled = ( act.available >= act.total );
|
|
}
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
function _execute(resources, action, args, opts = {}) {
|
|
args = args || [];
|
|
if ( resources.length > 1 && action.bulkAction && !opts.alt ) {
|
|
const fn = resources[0][action.bulkAction];
|
|
|
|
if ( fn ) {
|
|
return fn.call(resources[0], resources, ...args);
|
|
}
|
|
}
|
|
|
|
const promises = [];
|
|
|
|
for ( const resource of resources ) {
|
|
let fn;
|
|
|
|
if (opts.alt && action.altAction) {
|
|
fn = resource[action.altAction];
|
|
} else {
|
|
fn = resource[action.action];
|
|
}
|
|
|
|
if ( fn ) {
|
|
promises.push(fn.apply(resource, args));
|
|
}
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
}
|