mirror of
https://github.com/wekan/wekan.git
synced 2025-04-23 13:37:09 -04:00
Provide a default date for lists and cards creation date
See https://github.com/wekan/wekan/pull/362#issuecomment-149645497 for motivation. This commit also contains cosmetic changes to the import Popup and on the code style to be more consistent with the code base.
This commit is contained in:
parent
8e0ad91191
commit
118b434a5a
5 changed files with 59 additions and 45 deletions
|
@ -107,8 +107,9 @@ template(name="createBoardPopup")
|
|||
| {{{_ 'board-private-info'}}}
|
||||
a.js-change-visibility {{_ 'change'}}.
|
||||
input.primary.wide(type="submit" value="{{_ 'create'}}")
|
||||
| {{_ 'or'}}
|
||||
a.js-import {{_ 'import-board'}}
|
||||
span.quiet
|
||||
| {{_ 'or'}}
|
||||
a.js-import {{_ 'import-board'}}
|
||||
|
||||
|
||||
template(name="boardChangeTitlePopup")
|
||||
|
|
|
@ -2,7 +2,6 @@ template(name="importPopup")
|
|||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
form
|
||||
label
|
||||
| {{_ getLabel}}
|
||||
textarea.js-card-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
|
||||
p: label(for='import-textarea') {{_ getLabel}}
|
||||
textarea#import-textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
|
||||
input.primary.wide(type="submit" value="{{_ 'import'}}")
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
/**
|
||||
* Abstract root for all import popup screens.
|
||||
* Descendants must define:
|
||||
* - getMethodName(): return the Meteor method to call for import, passing json data decoded as object
|
||||
* and additional data (see below)
|
||||
* - getAdditionalData(): return object containing additional data passed to Meteor method
|
||||
* (like list ID and position for a card import)
|
||||
* - getLabel(): i18n key for the text displayed in the popup, usually to explain how to get the data out of the
|
||||
* source system.
|
||||
*/
|
||||
/// Abstract root for all import popup screens.
|
||||
/// Descendants must define:
|
||||
/// - getMethodName(): return the Meteor method to call for import, passing json
|
||||
/// data decoded as object and additional data (see below);
|
||||
/// - getAdditionalData(): return object containing additional data passed to
|
||||
/// Meteor method (like list ID and position for a card import);
|
||||
/// - getLabel(): i18n key for the text displayed in the popup, usually to
|
||||
/// explain how to get the data out of the source system.
|
||||
const ImportPopup = BlazeComponent.extendComponent({
|
||||
template() {return 'importPopup';},
|
||||
template() {
|
||||
return 'importPopup';
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit': (evt) => {
|
||||
evt.preventDefault();
|
||||
const dataJson = $(evt.currentTarget).find('textarea').val();
|
||||
const dataJson = $(evt.currentTarget).find('.js-import-json').val();
|
||||
let dataObject;
|
||||
try {
|
||||
dataObject = JSON.parse(dataJson);
|
||||
|
@ -52,7 +53,8 @@ const ImportPopup = BlazeComponent.extendComponent({
|
|||
ImportPopup.extendComponent({
|
||||
getAdditionalData() {
|
||||
const listId = this.data()._id;
|
||||
const firstCardDom = $(`#js-list-${this.currentData()._id} .js-minicard:first`).get(0);
|
||||
const selector = `#js-list-${this.currentData()._id} .js-minicard:first`;
|
||||
const firstCardDom = $(selector).get(0);
|
||||
const sortIndex = Utils.calculateIndex(null, firstCardDom).base;
|
||||
const result = {listId, sortIndex};
|
||||
return result;
|
||||
|
|
|
@ -17,9 +17,11 @@ $popupWidth = 300px
|
|||
margin: 4px -10px
|
||||
width: $popupWidth
|
||||
|
||||
p,
|
||||
textarea,
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
input[type="password"]
|
||||
input[type="password"],
|
||||
input[type="file"]
|
||||
margin: 4px 0 12px
|
||||
width: 100%
|
||||
|
@ -30,8 +32,6 @@ $popupWidth = 300px
|
|||
|
||||
textarea
|
||||
height: 72px
|
||||
margin: 4px 0 12px
|
||||
width: 100%
|
||||
|
||||
.header
|
||||
height: 36px
|
||||
|
|
|
@ -5,17 +5,18 @@ const DateString = Match.Where(function (dateAsString) {
|
|||
|
||||
class TrelloCreator {
|
||||
constructor() {
|
||||
// the object creation dates, indexed by Trello id (so we only parse actions once!)
|
||||
// The object creation dates, indexed by Trello id (so we only parse actions
|
||||
// once!)
|
||||
this.createdAt = {
|
||||
board: null,
|
||||
cards: {},
|
||||
lists: {},
|
||||
};
|
||||
// map of labels Trello ID => Wekan ID
|
||||
// Map of labels Trello ID => Wekan ID
|
||||
this.labels = {};
|
||||
// map of lists Trello ID => Wekan ID
|
||||
// Map of lists Trello ID => Wekan ID
|
||||
this.lists = {};
|
||||
// the comments, indexed by Trello card id (to map when importing cards)
|
||||
// The comments, indexed by Trello card id (to map when importing cards)
|
||||
this.comments = {};
|
||||
}
|
||||
|
||||
|
@ -33,9 +34,12 @@ class TrelloCreator {
|
|||
closed: Boolean,
|
||||
name: String,
|
||||
prefs: Match.ObjectIncluding({
|
||||
// XXX refine control by validating 'background' against a list of allowed values (is it worth the maintenance?)
|
||||
// XXX refine control by validating 'background' against a list of
|
||||
// allowed values (is it worth the maintenance?)
|
||||
background: String,
|
||||
permissionLevel: Match.Where((value) => {return ['org', 'private', 'public'].indexOf(value)>= 0;}),
|
||||
permissionLevel: Match.Where((value) => {
|
||||
return ['org', 'private', 'public'].indexOf(value)>= 0;
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
@ -54,7 +58,8 @@ class TrelloCreator {
|
|||
|
||||
checkLabels(trelloLabels) {
|
||||
check(trelloLabels, [Match.ObjectIncluding({
|
||||
// XXX refine control by validating 'color' against a list of allowed values (is it worth the maintenance?)
|
||||
// XXX refine control by validating 'color' against a list of allowed
|
||||
// values (is it worth the maintenance?)
|
||||
color: String,
|
||||
name: String,
|
||||
})]);
|
||||
|
@ -67,9 +72,7 @@ class TrelloCreator {
|
|||
})]);
|
||||
}
|
||||
|
||||
/**
|
||||
* must call parseActions before calling this one
|
||||
*/
|
||||
// You must call parseActions before calling this one.
|
||||
createBoardAndLabels(trelloBoard) {
|
||||
const createdAt = this.createdAt.board;
|
||||
const boardToCreate = {
|
||||
|
@ -93,7 +96,8 @@ class TrelloCreator {
|
|||
color: label.color,
|
||||
name: label.name,
|
||||
};
|
||||
// we need to remember them by Trello ID, as this is the only ref we have when importing cards
|
||||
// We need to remember them by Trello ID, as this is the only ref we have
|
||||
// when importing cards.
|
||||
this.labels[label.id] = labelToCreate._id;
|
||||
boardToCreate.labels.push(labelToCreate);
|
||||
});
|
||||
|
@ -110,15 +114,14 @@ class TrelloCreator {
|
|||
system: 'Trello',
|
||||
url: trelloBoard.url,
|
||||
},
|
||||
// we attribute the import to current user, not the one from the original object
|
||||
// We attribute the import to current user, not the one from the original
|
||||
// object.
|
||||
userId: Meteor.userId(),
|
||||
});
|
||||
return boardId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create labels if they do not exist and load this.labels.
|
||||
*/
|
||||
// Create labels if they do not exist and load this.labels.
|
||||
createLabels(trelloLabels, board) {
|
||||
trelloLabels.forEach((label) => {
|
||||
const color = label.color;
|
||||
|
@ -138,7 +141,11 @@ class TrelloCreator {
|
|||
const listToCreate = {
|
||||
archived: list.closed,
|
||||
boardId,
|
||||
createdAt: this.createdAt.lists[list.id],
|
||||
// We are being defensing here by providing a default date (now) if the
|
||||
// creation date wasn't found on the action log. This happen on old
|
||||
// Trello boards (eg from 2013) that didn't log the 'createList' action
|
||||
// we require.
|
||||
createdAt: new Date(this.createdAt.lists[list.id] || Date.now()),
|
||||
title: list.name,
|
||||
userId: Meteor.userId(),
|
||||
};
|
||||
|
@ -156,7 +163,8 @@ class TrelloCreator {
|
|||
id: list.id,
|
||||
system: 'Trello',
|
||||
},
|
||||
// we attribute the import to current user, not the one from the original object
|
||||
// We attribute the import to current user, not the one from the
|
||||
// original object
|
||||
userId: Meteor.userId(),
|
||||
});
|
||||
});
|
||||
|
@ -168,7 +176,7 @@ class TrelloCreator {
|
|||
const cardToCreate = {
|
||||
archived: card.closed,
|
||||
boardId,
|
||||
createdAt: this.createdAt.cards[card.id],
|
||||
createdAt: new Date(this.createdAt.cards[card.id] || Date.now()),
|
||||
dateLastActivity: new Date(),
|
||||
description: card.desc,
|
||||
listId: this.lists[card.idList],
|
||||
|
@ -197,7 +205,8 @@ class TrelloCreator {
|
|||
system: 'Trello',
|
||||
url: card.url,
|
||||
},
|
||||
// we attribute the import to current user, not the one from the original card
|
||||
// we attribute the import to current user, not the one from the
|
||||
// original card
|
||||
userId: Meteor.userId(),
|
||||
});
|
||||
// add comments
|
||||
|
@ -212,7 +221,8 @@ class TrelloCreator {
|
|||
// XXX use the original comment user instead
|
||||
userId: Meteor.userId(),
|
||||
};
|
||||
// dateLastActivity will be set from activity insert, no need to update it ourselves
|
||||
// dateLastActivity will be set from activity insert, no need to
|
||||
// update it ourselves
|
||||
const commentId = CardComments.direct.insert(commentToCreate);
|
||||
Activities.direct.insert({
|
||||
activityType: 'addComment',
|
||||
|
@ -251,7 +261,8 @@ class TrelloCreator {
|
|||
if(trelloPermissionCode === 'public') {
|
||||
return 'public';
|
||||
}
|
||||
// Wekan does NOT have organization level, so we default both 'private' and 'org' to private.
|
||||
// Wekan does NOT have organization level, so we default both 'private' and
|
||||
// 'org' to private.
|
||||
return 'private';
|
||||
}
|
||||
|
||||
|
@ -302,8 +313,8 @@ Meteor.methods({
|
|||
throw new Meteor.Error('error-json-schema');
|
||||
}
|
||||
|
||||
// 2. check parameters are ok from a business point of view (exist & authorized)
|
||||
// nothing to check, everyone can import boards in their account
|
||||
// 2. check parameters are ok from a business point of view (exist &
|
||||
// authorized) nothing to check, everyone can import boards in their account
|
||||
|
||||
// 3. create all elements
|
||||
trelloCreator.parseActions(trelloBoard.actions);
|
||||
|
@ -330,7 +341,8 @@ Meteor.methods({
|
|||
throw new Meteor.Error('error-json-schema');
|
||||
}
|
||||
|
||||
// 2. check parameters are ok from a business point of view (exist & authorized)
|
||||
// 2. check parameters are ok from a business point of view (exist &
|
||||
// authorized)
|
||||
const list = Lists.findOne(data.listId);
|
||||
if(!list) {
|
||||
throw new Meteor.Error('error-list-doesNotExist');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue