mirror of https://github.com/wekan/wekan
The Open Source kanban (built with Meteor). Keep variable/table/field names camelCase. For translations, only add Pull Request changes to wekan/i18n/en.i18n.json , other translations are done at https://transifex.com/wekan/wekan only.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
3.5 KiB
90 lines
3.5 KiB
import { Meteor } from 'meteor/meteor';
|
|
import { check, Match } from 'meteor/check';
|
|
import { ReactiveCache } from '/imports/reactiveCache';
|
|
import { RulesHelper } from '/server/rulesHelper';
|
|
import Rules from '/models/rules';
|
|
import Triggers from '/models/triggers';
|
|
import Actions from '/models/actions';
|
|
|
|
// Button rules are manual: a user clicks a card/board button and we run the
|
|
// rule's action immediately. This method runs one button rule on demand.
|
|
Meteor.methods({
|
|
async 'rules.runButton'(ruleId, cardId) {
|
|
check(ruleId, String);
|
|
check(cardId, Match.Optional(String));
|
|
|
|
const rule = await ReactiveCache.getRule(ruleId);
|
|
if (!rule) throw new Meteor.Error('not-found', 'Rule not found');
|
|
|
|
const trigger = await ReactiveCache.getTrigger(rule.triggerId);
|
|
if (!trigger || trigger.activityType !== 'button') {
|
|
throw new Meteor.Error('not-a-button', 'Rule is not a button rule');
|
|
}
|
|
|
|
// The user must be a member of the board the rule belongs to.
|
|
const board = await ReactiveCache.getBoard(rule.boardId);
|
|
if (!board || !board.hasMember(this.userId)) {
|
|
throw new Meteor.Error('not-authorized', 'Not a board member');
|
|
}
|
|
|
|
const action = await ReactiveCache.getAction(rule.actionId);
|
|
if (!action) throw new Meteor.Error('not-found', 'Action not found');
|
|
|
|
await RulesHelper.performAction(
|
|
{
|
|
activityType: 'button',
|
|
cardId,
|
|
boardId: rule.boardId,
|
|
userId: this.userId,
|
|
},
|
|
action,
|
|
);
|
|
return true;
|
|
},
|
|
|
|
// Create a rule (trigger + action + rule) on the server in one call. The rule
|
|
// wizard previously did three client-side Collection.insert() calls; those are
|
|
// optimistic writes whose documents end up in client-minimongo limbo once the
|
|
// wizard's `boardRules` subscription stops on navigation, so a freshly created
|
|
// board-button's trigger never re-published to the board view (the button only
|
|
// appeared after a full page reload). Inserting on the server avoids the
|
|
// optimistic-ghost reconciliation problem entirely.
|
|
async 'rules.createRule'(boardId, title, trigger, action) {
|
|
check(boardId, String);
|
|
check(title, Match.Optional(String));
|
|
check(trigger, Object);
|
|
check(action, Object);
|
|
|
|
const board = await ReactiveCache.getBoard(boardId);
|
|
if (!board) throw new Meteor.Error('not-found', 'Board not found');
|
|
if (!board.hasAdmin(this.userId)) {
|
|
throw new Meteor.Error('not-authorized', 'Must be a board admin');
|
|
}
|
|
|
|
const clean = doc => {
|
|
const { _id, ...rest } = doc || {};
|
|
return rest;
|
|
};
|
|
|
|
const triggerId = await Triggers.insertAsync({ ...clean(trigger), boardId });
|
|
const actionId = await Actions.insertAsync({ ...clean(action), boardId });
|
|
const ruleDoc = {
|
|
title: title || 'Rule',
|
|
triggerId,
|
|
actionId,
|
|
boardId,
|
|
};
|
|
// Denormalise manual-button metadata onto the rule. The board view renders
|
|
// its board/card buttons from the rule document alone, because in this Meteor
|
|
// 3 setup the schemaless `triggers` collection's documents do not reach the
|
|
// client over the board subscription (the schema-backed `rules` collection
|
|
// does), so reading the label off the published trigger would leave the
|
|
// button blank/absent.
|
|
if (trigger && trigger.activityType === 'button') {
|
|
ruleDoc.buttonType = trigger.buttonType || 'card';
|
|
ruleDoc.buttonLabel = trigger.buttonLabel || title || 'Run';
|
|
}
|
|
const ruleId = await Rules.insertAsync(ruleDoc);
|
|
return { _id: ruleId, triggerId, actionId };
|
|
},
|
|
});
|
|
|