mirror of
https://github.com/wekan/wekan.git
synced 2025-04-23 05:27:14 -04:00
Merge branch 'feuerball11-feature-custom-fields' into devel
This commit is contained in:
commit
85e02010d4
7 changed files with 154 additions and 102 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,3 +1,22 @@
|
|||
# Upcoming Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Markdown support in Custom Fields, and view on minicard](https://github.com/wekan/wekan/pull/1699);
|
||||
* [Fixes to Advanced Filter, you are now able to filter for Dropdown and Numbers,
|
||||
also Dropdown are now correctly displayed on minicard](https://github.com/wekan/wekan/pull/1699).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [Fix data colour changes on cards](https://github.com/wekan/wekan/pull/1698);
|
||||
* [Fix for migration error "title is required" and breaking of Standalone and
|
||||
Sandstorm Wekan](https://github.com/wekan/wekan/commit/8d5cbf1e6c2b6d467fe1c0708cd794fd11b98a2e#commitcomment-29362180);
|
||||
* [Fix Issue with custom fields shown on card](https://github.com/wekan/wekan/issues/1659);
|
||||
* [Fix showing public board in list mode](https://github.com/wekan/wekan/issues/1623);
|
||||
* [Fix for not able to remove Custom Field "Show on Card"](https://github.com/wekan/wekan/pull/1699).
|
||||
|
||||
Thanks to GitHub users feuerball11, oec and xet7 for their contributions.
|
||||
|
||||
# v1.04 2018-06-12 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
|
|
@ -88,11 +88,13 @@ BlazeComponent.extendComponent({
|
|||
|
||||
isViewSwimlanes() {
|
||||
const currentUser = Meteor.user();
|
||||
if (!currentUser) return false;
|
||||
return (currentUser.profile.boardView === 'board-view-swimlanes');
|
||||
},
|
||||
|
||||
isViewLists() {
|
||||
const currentUser = Meteor.user();
|
||||
if (!currentUser) return true;
|
||||
return (currentUser.profile.boardView === 'board-view-lists');
|
||||
},
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ template(name="minicard")
|
|||
.minicard-custom-field-item
|
||||
= definition.name
|
||||
.minicard-custom-field-item
|
||||
= value
|
||||
+viewer
|
||||
= trueValue
|
||||
|
||||
if members
|
||||
.minicard-members.js-minicard-members
|
||||
|
|
|
@ -37,7 +37,7 @@ template(name="createCustomFieldPopup")
|
|||
each dropdownItems.get
|
||||
input.js-dropdown-item(type="text" value=name placeholder="")
|
||||
input.js-dropdown-item.last(type="text" value="" placeholder="{{_ 'custom-field-dropdown-options-placeholder'}}")
|
||||
a.flex.js-field-show-on-card
|
||||
a.flex.js-field-show-on-card(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'show-field-on-card'}}
|
||||
|
@ -49,4 +49,4 @@ template(name="createCustomFieldPopup")
|
|||
|
||||
template(name="deleteCustomFieldPopup")
|
||||
p {{_ "custom-field-delete-pop"}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
|
|
|
@ -145,6 +145,22 @@ class AdvancedFilter {
|
|||
return found._id;
|
||||
}
|
||||
|
||||
_fieldValueToId(field, value)
|
||||
{
|
||||
const found = CustomFields.findOne({ 'name': field });
|
||||
if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0)
|
||||
{
|
||||
for (let i = 0; i < found.settings.dropdownItems.length; i++)
|
||||
{
|
||||
if (found.settings.dropdownItems[i].name === value)
|
||||
{
|
||||
return found.settings.dropdownItems[i]._id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
_arrayToSelector(commands) {
|
||||
try {
|
||||
//let changed = false;
|
||||
|
@ -163,27 +179,27 @@ class AdvancedFilter {
|
|||
if (commands[i].cmd) {
|
||||
switch (commands[i].cmd) {
|
||||
case '(':
|
||||
{
|
||||
level++;
|
||||
if (start === -1) start = i;
|
||||
continue;
|
||||
}
|
||||
{
|
||||
level++;
|
||||
if (start === -1) start = i;
|
||||
continue;
|
||||
}
|
||||
case ')':
|
||||
{
|
||||
level--;
|
||||
commands.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (level > 0) {
|
||||
subcommands.push(commands[i]);
|
||||
{
|
||||
level--;
|
||||
commands.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (level > 0) {
|
||||
subcommands.push(commands[i]);
|
||||
commands.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,86 +221,86 @@ class AdvancedFilter {
|
|||
case '=':
|
||||
case '==':
|
||||
case '===':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': str };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '!=':
|
||||
case '!==':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: str } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '>':
|
||||
case 'gt':
|
||||
case 'Gt':
|
||||
case 'GT':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: str } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '>=':
|
||||
case '>==':
|
||||
case 'gte':
|
||||
case 'Gte':
|
||||
case 'GTE':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: str } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: parseInt(str, 10) } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '<':
|
||||
case 'lt':
|
||||
case 'Lt':
|
||||
case 'LT':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: str } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: parseInt(str, 10) } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '<=':
|
||||
case '<==':
|
||||
case 'lte':
|
||||
case 'Lte':
|
||||
case 'LTE':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: str } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: parseInt(str, 10) } };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -300,44 +316,44 @@ class AdvancedFilter {
|
|||
case 'OR':
|
||||
case '|':
|
||||
case '||':
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = { $or: [op1, op2] };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = { $or: [op1, op2] };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case 'and':
|
||||
case 'And':
|
||||
case 'AND':
|
||||
case '&':
|
||||
case '&&':
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = { $and: [op1, op2] };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = { $and: [op1, op2] };
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'not':
|
||||
case 'Not':
|
||||
case 'NOT':
|
||||
case '!':
|
||||
{
|
||||
const op1 = commands[i + 1];
|
||||
commands[i] = { $not: op1 };
|
||||
commands.splice(i + 1, 1);
|
||||
{
|
||||
const op1 = commands[i + 1];
|
||||
commands[i] = { $not: op1 };
|
||||
commands.splice(i + 1, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,12 +230,26 @@ Cards.helpers({
|
|||
// match right definition to each field
|
||||
if (!this.customFields) return [];
|
||||
return this.customFields.map((customField) => {
|
||||
const definition = definitions.find((definition) => {
|
||||
return definition._id === customField._id;
|
||||
});
|
||||
//search for "True Value" which is for DropDowns other then the Value (which is the id)
|
||||
let trueValue = customField.value;
|
||||
if (definition.settings.dropdownItems && definition.settings.dropdownItems.length > 0)
|
||||
{
|
||||
for (let i = 0; i < definition.settings.dropdownItems.length; i++)
|
||||
{
|
||||
if (definition.settings.dropdownItems[i]._id === customField.value)
|
||||
{
|
||||
trueValue = definition.settings.dropdownItems[i].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
_id: customField._id,
|
||||
value: customField.value,
|
||||
definition: definitions.find((definition) => {
|
||||
return definition._id === customField._id;
|
||||
}),
|
||||
trueValue,
|
||||
definition,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ Migrations.add('add-sort-checklists', () => {
|
|||
noValidate
|
||||
);
|
||||
}
|
||||
checklist.items.find().forEach((item, index) => {
|
||||
checklist.items.forEach((item, index) => {
|
||||
if (!item.hasOwnProperty('sort')) {
|
||||
Checklists.direct.update(
|
||||
{ _id: checklist._id, 'items._id': item._id },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue