mirror of
https://github.com/wekan/wekan.git
synced 2025-04-23 13:37:09 -04:00
Fixed rule allows
This commit is contained in:
parent
1f5f429fc4
commit
34b37116cf
25 changed files with 345 additions and 260 deletions
|
@ -67,9 +67,6 @@ BlazeComponent.extendComponent({
|
|||
lastLabel(){
|
||||
const lastLabelId = this.currentData().labelId;
|
||||
const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(lastLabelId);
|
||||
console.log("LAST");
|
||||
console.log(lastLabel);
|
||||
|
||||
if(lastLabel.name == undefined || lastLabel.name == ""){
|
||||
return lastLabel.color;
|
||||
}else{
|
||||
|
|
|
@ -89,7 +89,7 @@ template(name="boardHeaderBar")
|
|||
i.fa.fa-times-thin
|
||||
|
||||
a.board-header-btn.js-open-rules-view(title="{{_ 'rules'}}")
|
||||
i.fa.fa-cutlery
|
||||
i.fa.fa-magic
|
||||
span {{_ 'rules'}}
|
||||
|
||||
a.board-header-btn.js-open-search-view(title="{{_ 'search'}}")
|
||||
|
|
|
@ -64,7 +64,7 @@ body
|
|||
|
||||
.modal-content-wide
|
||||
width: 800px
|
||||
min-height: 160px
|
||||
min-height: 0px
|
||||
margin: 42px auto
|
||||
padding: 12px
|
||||
border-radius: 4px
|
||||
|
|
|
@ -2,28 +2,28 @@ template(name="boardActions")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| Move card to
|
||||
| {{{_'r-move-card-to'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="move-gen-action")
|
||||
option(value="top") Top of
|
||||
option(value="bottom") Bottom of
|
||||
option(value="top") {{{_'r-top-of'}}}
|
||||
option(value="bottom") {{{_'r-bottom-of'}}}
|
||||
div.trigger-text
|
||||
| its list
|
||||
| {{{_'r-its-list'}}}
|
||||
div.trigger-button.js-add-gen-move-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| Move card to
|
||||
| {{{_'r-move-card-to'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="move-spec-action")
|
||||
option(value="top") Top of
|
||||
option(value="bottom") Bottom of
|
||||
option(value="top") {{{_'r-top-of'}}}
|
||||
option(value="bottom") {{{_'r-bottom-of'}}}
|
||||
div.trigger-text
|
||||
| list
|
||||
| {{{_'r-list'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="listName",type=text,placeholder="List Name")
|
||||
input(id="listName",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-button.js-add-spec-move-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
@ -31,10 +31,10 @@ template(name="boardActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="arch-action")
|
||||
option(value="archive") Archive
|
||||
option(value="unarchive") Unarchive
|
||||
option(value="archive") {{{_'r-archive'}}}
|
||||
option(value="unarchive") {{{_'r-unarchive'}}}
|
||||
div.trigger-text
|
||||
| card
|
||||
| {{{_'r-card'}}}
|
||||
div.trigger-button.js-add-arch-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
|
|
@ -12,48 +12,53 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#move-spec-action').value;
|
||||
const listTitle = this.find('#listName').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
|
||||
if(actionSelected == "top"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToTop","listTitle":listTitle});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "moveCardToTop","listTitle":listTitle,"boardId":boardId});
|
||||
console.log("Action inserted");
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "bottom"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToBottom","listTitle":listTitle});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "moveCardToBottom","listTitle":listTitle,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
'click .js-add-gen-move-action'(event) {
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#move-gen-action').value;
|
||||
if(actionSelected == "top"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToTop","listTitle":"*"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
}
|
||||
if(actionSelected == "bottom"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToBottom","listTitle":"*"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
}
|
||||
},
|
||||
'click .js-add-arch-action'(event) {
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#arch-action').value;
|
||||
if(actionSelected == "archive"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "archive"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
}
|
||||
if(actionSelected == "unarchive"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "unarchive"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
}
|
||||
},
|
||||
}];
|
||||
const boardId = Session.get('currentBoard');
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#move-gen-action').value;
|
||||
if(actionSelected == "top"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToTop","listTitle":"*","boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "bottom"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "moveCardToBottom","listTitle":"*","boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
'click .js-add-arch-action'(event) {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#arch-action').value;
|
||||
if(actionSelected == "archive"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "archive"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "unarchive"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "unarchive"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
}];
|
||||
},
|
||||
|
||||
}).register('boardActions');
|
|
@ -3,10 +3,10 @@ template(name="cardActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="label-action")
|
||||
option(value="add") Add
|
||||
option(value="remove") Remove
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
div.trigger-text
|
||||
| label
|
||||
| {{{_'r-label'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="label-id")
|
||||
each labels
|
||||
|
@ -19,19 +19,19 @@ template(name="cardActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="member-action")
|
||||
option(value="add") Add
|
||||
option(value="remove") Removed
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
div.trigger-text
|
||||
| member
|
||||
| {{{_'r-member'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="member-name",type=text,placeholder="Member name")
|
||||
input(id="member-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-button.js-add-member-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| Remove all member from the card
|
||||
| {{{_'r-remove-all'}}}
|
||||
div.trigger-button.js-add-removeall-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
|
|
@ -24,16 +24,17 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#label-action').value;
|
||||
const labelId = this.find('#label-id').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
|
||||
if(actionSelected == "add"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "addLabel","labelId":labelId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "addLabel","labelId":labelId,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "remove"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "removeLabel","labelId":labelId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "removeLabel","labelId":labelId,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -42,23 +43,25 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#member-action').value;
|
||||
const memberName = this.find('#member-name').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
if(actionSelected == "add"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "addMember","memberName":memberName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "addMember","memberName":memberName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "remove"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "removeMember","memberName":memberName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "removeMember","memberName":memberName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
'click .js-add-removeall-action'(event) {
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const trigger = this.data().triggerVar.get();
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "removeMember","memberName":"*"});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const boardId = Session.get('currentBoard');
|
||||
const actionId = Actions.insert({actionType: "removeMember","memberName":"*","boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
},
|
||||
}];
|
||||
},
|
||||
|
|
|
@ -3,12 +3,12 @@ template(name="checklistActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="check-action")
|
||||
option(value="add") Add
|
||||
option(value="remove") Remove
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
div.trigger-text
|
||||
| checklist
|
||||
| {{{_'r-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name",type=text,placeholder="name")
|
||||
input(id="checklist-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-button.js-add-checklist-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
@ -16,12 +16,12 @@ template(name="checklistActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="checkall-action")
|
||||
option(value="check") Check all
|
||||
option(value="uncheck") Unchek all
|
||||
option(value="check") {{{_'r-check-all'}}}
|
||||
option(value="uncheck") {{{_'r-uncheck-all'}}}
|
||||
div.trigger-text
|
||||
| items of checklist
|
||||
| {{{_'r-items-check'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name2",type=text,placeholder="name")
|
||||
input(id="checklist-name2",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-button.js-add-checkall-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
@ -30,16 +30,16 @@ template(name="checklistActions")
|
|||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="check-item-action")
|
||||
option(value="check") Check
|
||||
option(value="uncheck") Unchek
|
||||
option(value="check") {{{_'r-check'}}}
|
||||
option(value="uncheck") {{{_'r-uncheck'}}}
|
||||
div.trigger-text
|
||||
| item
|
||||
| {{{_'r-item'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="checkitem-name",type=text,placeholder="name")
|
||||
input(id="checkitem-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-text
|
||||
| of checklist
|
||||
| {{{_'r-of-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name3",type=text,placeholder="name")
|
||||
input(id="checklist-name3",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-button.js-add-check-item-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
|
|
|
@ -9,16 +9,17 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#check-action').value;
|
||||
const checklistName = this.find('#checklist-name').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
|
||||
if(actionSelected == "add"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "addChecklist","checklistName":checklistName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "addChecklist","checklistName":checklistName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "remove"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "removeChecklist","checklistName":checklistName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "removeChecklist","checklistName":checklistName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -27,15 +28,16 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const actionSelected = this.find('#checkall-action').value;
|
||||
const checklistName = this.find('#checklist-name2').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
if(actionSelected == "check"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "checkAll","checklistName":checklistName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "checkAll","checklistName":checklistName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "uncheck"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "uncheckAll","checklistName":checklistName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "uncheckAll","checklistName":checklistName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
'click .js-add-check-item-action'(event) {
|
||||
|
@ -44,15 +46,16 @@ BlazeComponent.extendComponent({
|
|||
const checkItemName = this.find("#checkitem-name");
|
||||
const checklistName = this.find("#checklist-name3");
|
||||
const actionSelected = this.find('#check-item-action').value;
|
||||
const boardId = Session.get('currentBoard');
|
||||
if(actionSelected == "check"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "checkItem","checklistName":checklistName,"checkItemName":checkItemName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "checkItem","checklistName":checklistName,"checkItemName":checkItemName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
if(actionSelected == "uncheck"){
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "uncheckItem","checklistName":checklistName,"checkItemName":checkItemName});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const actionId = Actions.insert({actionType: "uncheckItem","checklistName":checklistName,"checkItemName":checkItemName,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
}
|
||||
},
|
||||
}];
|
||||
|
|
|
@ -2,10 +2,10 @@ template(name="mailActions")
|
|||
div.trigger-item.trigger-item-mail
|
||||
div.trigger-content.trigger-content-mail
|
||||
div.trigger-text.trigger-text-email
|
||||
| Send an email
|
||||
| {{{_'r-send-email'}}}
|
||||
div.trigger-dropdown-mail
|
||||
input(id="email-to",type=text,placeholder="to")
|
||||
input(id="email-subject",type=text,placeholder="subject")
|
||||
input(id="email-to",type=text,placeholder="{{{_'r-to'}}}")
|
||||
input(id="email-subject",type=text,placeholder="{{{_'r-subject'}}}")
|
||||
textarea(id="email-msg")
|
||||
div.trigger-button.trigger-button-email.js-mail-action.js-goto-rules
|
||||
i.fa.fa-plus
|
|
@ -12,8 +12,9 @@ BlazeComponent.extendComponent({
|
|||
const trigger = this.data().triggerVar.get();
|
||||
const ruleName = this.data().ruleName.get();
|
||||
const triggerId = Triggers.insert(trigger);
|
||||
const actionId = Actions.insert({actionType: "sendEmail","emailTo":emailTo,"emailSubject":emailSubject,"emailMsg":emailMsg});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId});
|
||||
const boardId = Session.get('currentBoard');
|
||||
const actionId = Actions.insert({actionType: "sendEmail","emailTo":emailTo,"emailSubject":emailSubject,"emailMsg":emailMsg,"boardId":boardId});
|
||||
Rules.insert({title: ruleName, triggerId: triggerId, actionId: actionId,"boardId":boardId});
|
||||
},
|
||||
}];
|
||||
},
|
||||
|
|
8
client/components/rules/ruleDetails.jade
Normal file
8
client/components/rules/ruleDetails.jade
Normal file
|
@ -0,0 +1,8 @@
|
|||
template(name="ruleDetails")
|
||||
.rules
|
||||
h2
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule-details' }}}
|
||||
|
||||
| trigger
|
||||
| action
|
28
client/components/rules/ruleDetails.js
Normal file
28
client/components/rules/ruleDetails.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('allRules');
|
||||
},
|
||||
|
||||
trigger(){
|
||||
const rule = Rules.findOne({_id:ruleId});
|
||||
return Triggers.findOne({_id:rule.triggerId});
|
||||
},
|
||||
action(){
|
||||
const rule = Rules.findOne({_id:ruleId});
|
||||
return Triggers.findOne({_id:rule.actionId});
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
}];
|
||||
},
|
||||
|
||||
}).register('ruleDetails');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
template(name="rulesActions")
|
||||
h2
|
||||
i.fa.fa-cutlery
|
||||
| Rule "#{data.ruleName.get}" - Add action
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule' }}} "#{data.ruleName.get}" - {{{_ 'r-add-action'}}}
|
||||
.triggers-content
|
||||
.triggers-body
|
||||
.triggers-side-menu
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
template(name="rulesList")
|
||||
.rules
|
||||
h2
|
||||
i.fa.fa-cutlery
|
||||
| Project rules
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-board-rules' }}}
|
||||
|
||||
ul.rules-list
|
||||
each rules
|
||||
|
@ -12,14 +12,16 @@ template(name="rulesList")
|
|||
div.rules-btns-group
|
||||
button
|
||||
i.fa.fa-eye
|
||||
| View rule
|
||||
button.js-delete-rule
|
||||
i.fa.fa-trash-o
|
||||
| Delete rule
|
||||
| {{{_ 'r-view-rule'}}}
|
||||
if currentUser.isAdmin
|
||||
button.js-delete-rule
|
||||
i.fa.fa-trash-o
|
||||
| {{{_ 'r-delete-rule'}}}
|
||||
else
|
||||
li.no-items-message No rules
|
||||
div.rules-add
|
||||
button.js-goto-trigger
|
||||
i.fa.fa-plus
|
||||
| Add rule
|
||||
input(type=text,placeholder="New rule name",id="ruleTitle")
|
||||
li.no-items-message {{{_ 'r-no-rules' }}}
|
||||
if currentUser.isAdmin
|
||||
div.rules-add
|
||||
button.js-goto-trigger
|
||||
i.fa.fa-plus
|
||||
| {{{_ 'r-add-rule'}}}
|
||||
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
|
|
@ -1,7 +1,7 @@
|
|||
template(name="rulesMain")
|
||||
if rulesListVar.get
|
||||
if($eq rulesCurrentTab.get 'rulesList')
|
||||
+rulesList
|
||||
else if rulesTriggerVar.get
|
||||
if($eq rulesCurrentTab.get 'trigger')
|
||||
+rulesTriggers(ruleName=ruleName triggerVar=triggerVar)
|
||||
else if rulesActionVar.get
|
||||
if($eq rulesCurrentTab.get 'action')
|
||||
+rulesActions(ruleName=ruleName triggerVar=triggerVar)
|
|
@ -1,28 +1,24 @@
|
|||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.rulesListVar = new ReactiveVar(true);
|
||||
this.rulesTriggerVar = new ReactiveVar(false);
|
||||
this.rulesActionVar = new ReactiveVar(false);
|
||||
this.rulesCurrentTab = new ReactiveVar("rulesList")
|
||||
this.ruleName = new ReactiveVar("");
|
||||
this.triggerVar = new ReactiveVar();
|
||||
this.ruleId = new ReactiveVar();
|
||||
},
|
||||
|
||||
setTrigger() {
|
||||
this.rulesListVar.set(false);
|
||||
this.rulesTriggerVar.set(true);
|
||||
this.rulesActionVar.set(false);
|
||||
this.rulesCurrentTab.set("trigger")
|
||||
},
|
||||
|
||||
setRulesList() {
|
||||
this.rulesListVar.set(true);
|
||||
this.rulesTriggerVar.set(false);
|
||||
this.rulesActionVar.set(false);
|
||||
this.rulesCurrentTab.set("rulesList")
|
||||
},
|
||||
|
||||
setAction() {
|
||||
this.rulesListVar.set(false);
|
||||
this.rulesTriggerVar.set(false);
|
||||
this.rulesActionVar.set(true);
|
||||
this.rulesCurrentTab.set("action")
|
||||
},
|
||||
setRuleDetails() {
|
||||
this.rulesCurrentTab.set("ruleDetails")
|
||||
},
|
||||
|
||||
events() {
|
||||
|
@ -48,6 +44,10 @@ BlazeComponent.extendComponent({
|
|||
event.preventDefault();
|
||||
this.setRulesList();
|
||||
},
|
||||
'click .js-goto-details'(event) {
|
||||
event.preventDefault();
|
||||
this.setRuleDetails();
|
||||
},
|
||||
|
||||
|
||||
}];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
template(name="rulesTriggers")
|
||||
h2
|
||||
i.fa.fa-cutlery
|
||||
| Rule "#{data.ruleName.get}" - Add trigger
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule' }}} "#{data.ruleName.get}" - {{{_ 'r-add-trigger'}}}
|
||||
.triggers-content
|
||||
.triggers-body
|
||||
.triggers-side-menu
|
||||
|
|
|
@ -2,54 +2,54 @@ template(name="boardTriggers")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a card is
|
||||
| {{{_'r-when-a-card-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="gen-action")
|
||||
option(value="created") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="created") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-added-to'}}}
|
||||
div.trigger-text
|
||||
| the board
|
||||
| {{{_'r-the-board'}}}
|
||||
div.trigger-button.js-add-gen-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a card is
|
||||
| {{{_'r-when-a-card-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="create-action")
|
||||
option(value="created") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="created") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-added-to'}}}
|
||||
div.trigger-text
|
||||
| list
|
||||
| {{{_'r-list'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="create-list-name",type=text,placeholder="List Name")
|
||||
input(id="create-list-name",type=text,placeholder="{{{_'r-list-name'}}}")
|
||||
div.trigger-button.js-add-create-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a card is
|
||||
| {{{_'r-when-a-card-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="move-action")
|
||||
option(value="moved-to") Moved to
|
||||
option(value="moved-from") Moved from
|
||||
option(value="moved-to") {{{_'r-moved-to'}}}
|
||||
option(value="moved-from") {{{_'r-moved-from'}}}
|
||||
div.trigger-text
|
||||
| list
|
||||
| {{{_'r-list'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="move-list-name",type=text,placeholder="List Name")
|
||||
input(id="move-list-name",type=text,placeholder="{{{_'r-list-name'}}}")
|
||||
div.trigger-button.js-add-moved-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a card is
|
||||
| {{{_'r-when-a-card-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="arch-action")
|
||||
option(value="archived") Archived
|
||||
option(value="unarchived") Unarchived
|
||||
option(value="archived") {{{_'r-archived'}}}
|
||||
option(value="unarchived") {{{_'r-unarchived'}}}
|
||||
div.trigger-button.js-add-arch-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
|
|
|
@ -2,20 +2,20 @@ template(name="cardTriggers")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a label is
|
||||
| {{{_'r-when-a-label-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="label-action")
|
||||
option(value="added") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="added") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-gen-label-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When the label
|
||||
| {{{_'r-when-the-label-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="spec-label")
|
||||
each labels
|
||||
|
@ -25,23 +25,23 @@ template(name="cardTriggers")
|
|||
| is
|
||||
div.trigger-dropdown
|
||||
select(id="spec-label-action")
|
||||
option(value="added") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="added") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-spec-label-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a member is
|
||||
| {{{_'r-when-a-member'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="gen-member-action")
|
||||
option(value="added") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="added") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-gen-member-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
|
@ -49,31 +49,31 @@ template(name="cardTriggers")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When the member
|
||||
| {{{_'r-when-the-member'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="spec-member",type=text,placeholder="name")
|
||||
input(id="spec-member",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-text
|
||||
| is
|
||||
| {{{_'r-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="spec-member-action")
|
||||
option(value="added") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="added") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-spec-member-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When an attachment
|
||||
| {{{_'r-when-a-attach'}}}
|
||||
div.trigger-text
|
||||
| is
|
||||
| {{{_'r-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="attach-action")
|
||||
option(value="added") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="added") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-attachment-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
|
@ -2,13 +2,13 @@ template(name="checklistTriggers")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a checklist is
|
||||
| {{{_'r-when-a-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="gen-check-action")
|
||||
option(value="created") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="created") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-gen-check-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
|
@ -16,68 +16,68 @@ template(name="checklistTriggers")
|
|||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When the checklist
|
||||
| {{{_'r-when-the-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="check-name",type=text,placeholder="Name")
|
||||
input(id="check-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-text
|
||||
| is
|
||||
| {{{_'r-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="spec-check-action")
|
||||
option(value="created") Added to
|
||||
option(value="removed") Removed from
|
||||
option(value="created") {{{_'r-added-to'}}}
|
||||
option(value="removed") {{{_'r-removed-from'}}}
|
||||
div.trigger-text
|
||||
| a card
|
||||
| {{{_'r-a-card'}}}
|
||||
div.trigger-button.js-add-spec-check-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a checklist is
|
||||
| {{{_'r-when-a-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="gen-comp-check-action")
|
||||
option(value="completed") Completed
|
||||
option(value="uncompleted") Made incomplete
|
||||
option(value="completed") {{{_'r-completed'}}}
|
||||
option(value="uncompleted") {{{_'r-made-incomplete'}}}
|
||||
div.trigger-button.js-add-gen-comp-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When the checklist
|
||||
| {{{_'r-when-the-checklist'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="spec-comp-check-name",type=text,placeholder="Name")
|
||||
input(id="spec-comp-check-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-text
|
||||
| is
|
||||
| {{{_'r-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="spec-comp-check-action")
|
||||
option(value="completed") Completed
|
||||
option(value="uncompleted") Made incomplete
|
||||
option(value="completed") {{{_'r-completed'}}}
|
||||
option(value="uncompleted") {{{_'r-made-incomplete'}}}
|
||||
div.trigger-button.js-add-spec-comp-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When a checklist item is
|
||||
| {{{_'r-when-a-item'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="check-item-gen-action")
|
||||
option(value="checked") Checked
|
||||
option(value="unchecked") Unchecked
|
||||
option(value="checked") {{{_'r-checked'}}}
|
||||
option(value="unchecked") {{{_'r-unchecked'}}}
|
||||
div.trigger-button.js-add-gen-check-item-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| When the checklist item
|
||||
| {{{_'r-when-the-item'}}}
|
||||
div.trigger-dropdown
|
||||
input(id="check-item-name",type=text,placeholder="Name")
|
||||
input(id="check-item-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
div.trigger-text
|
||||
| is
|
||||
| {{{_'r-is'}}}
|
||||
div.trigger-dropdown
|
||||
select(id="check-item-spec-action")
|
||||
option(value="checked") Checked
|
||||
option(value="unchecked") Unchecked
|
||||
option(value="checked") {{{_'r-checked'}}}
|
||||
option(value="unchecked") {{{_'r-unchecked'}}}
|
||||
div.trigger-button.js-add-spec-check-item-trigger.js-goto-action
|
||||
i.fa.fa-plus
|
|
@ -515,6 +515,77 @@
|
|||
"activity-delete-attach": "deleted an attachment from %s",
|
||||
"activity-added-label-card": "added label '%s'",
|
||||
"activity-removed-label-card": "removed label '%s'",
|
||||
"activity-delete-attach-card": "deleted an attachment"
|
||||
"activity-delete-attach-card": "deleted an attachment",
|
||||
"r-rule": "Rule",
|
||||
"r-add-trigger": "Add trigger",
|
||||
"r-add-action": "Add action",
|
||||
"r-board-rules": "Board rules",
|
||||
"r-add-rule": "Add rule",
|
||||
"r-view-rule": "View rule",
|
||||
"r-delete-rule": "Delete rule",
|
||||
"r-new-rule-name": "Add new rule",
|
||||
"r-no-rules": "No rules",
|
||||
"r-when-a-card-is": "When a card is",
|
||||
"r-added-to": "Added to",
|
||||
"r-removed-from": "Removed from",
|
||||
"r-the-board": "the board",
|
||||
"r-list": "list",
|
||||
"r-moved-to": "Moved to",
|
||||
"r-moved-from": "Moved from",
|
||||
"r-archived": "Archived",
|
||||
"r-unarchived": "Unarchived",
|
||||
"r-a-card": "a card",
|
||||
"r-when-a-label-is": "When a label is",
|
||||
"r-when-the-label-is": "When the label is",
|
||||
"r-list-name": "List name",
|
||||
"r-when-a-member": "When a member is",
|
||||
"r-when-the-member": "When the member is",
|
||||
"r-name": "name",
|
||||
"r-is": "is",
|
||||
"r-when-a-attach": "When an attachment",
|
||||
"r-when-a-checklist": "When a checklist is",
|
||||
"r-when-the-checklist": "When the checklist",
|
||||
"r-completed": "Completed",
|
||||
"r-made-incomplete": "Made incomplete",
|
||||
"r-when-a-item": "When a checklist item is",
|
||||
"r-when-the-item": "When the checklist item is",
|
||||
"r-checked": "Checked",
|
||||
"r-unchecked": "Unchecked",
|
||||
"r-move-card-to": "Move card to",
|
||||
"r-top-of": "Top of",
|
||||
"r-bottom-of": "Bottom of",
|
||||
"r-its-list": "its list",
|
||||
"r-list": "list",
|
||||
"r-archive": "Archive",
|
||||
"r-unarchive": "Unarchive",
|
||||
"r-card": "card",
|
||||
"r-add": "Add",
|
||||
"r-remove": "Remove",
|
||||
"r-label": "label",
|
||||
"r-member": "member",
|
||||
"r-remove-all": "Remove all members from the card",
|
||||
"r-checklist": "checklist",
|
||||
"r-check-all": "Check all",
|
||||
"r-uncheck-all": "Uncheck all",
|
||||
"r-item-check": "Items of checklist",
|
||||
"r-check": "Check",
|
||||
"r-uncheck": "Uncheck",
|
||||
"r-item": "item",
|
||||
"r-of-checklist": "of checlist",
|
||||
"r-send-email": "Send an email",
|
||||
"r-to": "to",
|
||||
"r-subject": "subject",
|
||||
"r-rule-details": "Rule details"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,52 +1,19 @@
|
|||
Actions = new Mongo.Collection('actions');
|
||||
|
||||
|
||||
|
||||
Actions.mutations({
|
||||
rename(description) {
|
||||
return { $set: { description } };
|
||||
},
|
||||
});
|
||||
|
||||
Actions.allow({
|
||||
update: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
insert(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
insert: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
update(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
remove: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
remove(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Actions.helpers({
|
||||
fromList() {
|
||||
return Lists.findOne(this.fromId);
|
||||
},
|
||||
|
||||
toList() {
|
||||
return Lists.findOne(this.toId);
|
||||
},
|
||||
|
||||
findList(title) {
|
||||
return Lists.findOne({title:title});
|
||||
},
|
||||
|
||||
labels() {
|
||||
const boardLabels = this.board().labels;
|
||||
const cardLabels = _.filter(boardLabels, (label) => {
|
||||
return _.contains(this.labelIds, label._id);
|
||||
});
|
||||
return cardLabels;
|
||||
}});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,15 +3,19 @@ Rules = new Mongo.Collection('rules');
|
|||
Rules.attachSchema(new SimpleSchema({
|
||||
title: {
|
||||
type: String,
|
||||
optional: true,
|
||||
optional: false,
|
||||
},
|
||||
triggerId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
optional: false,
|
||||
},
|
||||
actionId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
optional: false,
|
||||
},
|
||||
boardId: {
|
||||
type: String,
|
||||
optional: false,
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -25,22 +29,21 @@ Rules.helpers({
|
|||
getAction(){
|
||||
return Actions.findOne({_id:this.actionId});
|
||||
},
|
||||
getTrigger(){
|
||||
return Triggers.findOne({_id:this.triggerId});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
Rules.allow({
|
||||
update: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
insert(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
remove: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
},
|
||||
insert: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
update(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
remove(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -9,17 +9,14 @@ Triggers.mutations({
|
|||
});
|
||||
|
||||
Triggers.allow({
|
||||
update: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
insert(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
insert: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
update(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
},
|
||||
remove: function () {
|
||||
// add custom authentication code here
|
||||
return true;
|
||||
remove(userId, doc) {
|
||||
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue