summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorRomulus Urakagi Tsai <urakagi@gmail.com>2020-02-13 09:02:26 +0000
committerRomulus Urakagi Tsai <urakagi@gmail.com>2020-02-13 09:02:26 +0000
commit4b196d537896f39fb76090020cb5851a699546eb (patch)
tree28e2e025ce90645ed360bb8c26ab39e6f40214e4 /client
parentb34ed58289a3dae5838d3b621260938a3ecf52d5 (diff)
parent3fcde252f705f9527f7190517082a047714a4eec (diff)
downloadwekan-4b196d537896f39fb76090020cb5851a699546eb.tar.gz
wekan-4b196d537896f39fb76090020cb5851a699546eb.tar.bz2
wekan-4b196d537896f39fb76090020cb5851a699546eb.zip
Merge branch 'master' of https://github.com/wekan/wekan into lib-change
Diffstat (limited to 'client')
-rw-r--r--client/components/activities/activities.jade6
-rw-r--r--client/components/activities/activities.styl2
-rw-r--r--client/components/activities/comments.js3
-rw-r--r--client/components/activities/comments.styl20
-rw-r--r--client/components/boards/boardBody.js65
-rw-r--r--client/components/boards/boardHeader.jade92
-rw-r--r--client/components/boards/boardHeader.js53
-rw-r--r--client/components/cards/attachments.jade29
-rw-r--r--client/components/cards/cardDate.js3
-rw-r--r--client/components/cards/cardDetails.jade475
-rw-r--r--client/components/cards/cardDetails.js102
-rw-r--r--client/components/cards/cardDetails.styl32
-rw-r--r--client/components/cards/checklists.jade4
-rw-r--r--client/components/cards/checklists.js12
-rw-r--r--client/components/cards/minicard.jade17
-rw-r--r--client/components/cards/minicard.js26
-rw-r--r--client/components/cards/subtasks.jade4
-rw-r--r--client/components/cards/subtasks.js9
-rw-r--r--client/components/lists/list.js76
-rw-r--r--client/components/lists/listBody.js38
-rw-r--r--client/components/lists/listHeader.jade57
-rw-r--r--client/components/lists/listHeader.js28
-rw-r--r--client/components/main/header.styl3
-rw-r--r--client/components/rules/actions/boardActions.jade37
-rw-r--r--client/components/rules/actions/boardActions.js30
-rw-r--r--client/components/settings/informationBody.jade8
-rw-r--r--client/components/settings/peopleBody.jade72
-rw-r--r--client/components/settings/peopleBody.styl2
-rw-r--r--client/components/settings/settingBody.jade31
-rw-r--r--client/components/settings/settingBody.js8
-rw-r--r--client/components/settings/settingBody.styl5
-rw-r--r--client/components/sidebar/sidebar.jade214
-rw-r--r--client/components/sidebar/sidebar.js403
-rw-r--r--client/components/sidebar/sidebar.styl2
-rw-r--r--client/components/sidebar/sidebarArchives.jade54
-rw-r--r--client/components/sidebar/sidebarArchives.js9
-rw-r--r--client/components/sidebar/sidebarFilters.jade15
-rw-r--r--client/components/swimlanes/swimlaneHeader.js11
-rw-r--r--client/components/swimlanes/swimlanes.jade62
-rw-r--r--client/components/swimlanes/swimlanes.js95
-rw-r--r--client/components/swimlanes/swimlanes.styl62
-rw-r--r--client/components/users/userAvatar.jade1
-rw-r--r--client/components/users/userHeader.jade65
-rw-r--r--client/components/users/userHeader.js93
-rwxr-xr-xclient/lib/keyboard.js28
-rw-r--r--client/lib/textComplete.js11
-rw-r--r--client/lib/utils.js66
47 files changed, 1979 insertions, 561 deletions
diff --git a/client/components/activities/activities.jade b/client/components/activities/activities.jade
index deb73072..8ecbdee8 100644
--- a/client/components/activities/activities.jade
+++ b/client/components/activities/activities.jade
@@ -201,20 +201,20 @@ template(name="cardActivities")
.activity-checklist(href="{{ card.absoluteUrl }}")
+viewer
= checklistItem.title
-
+
if(currentData.timeKey)
| {{{_ activityType }}}
= ' '
i(title=currentData.timeValue).activity-meta {{ moment currentData.timeValue 'LLL' }}
if (currentData.timeOldValue)
- = ' '
+ = ' '
| {{{_ "previous_as" }}}
= ' '
i(title=currentData.timeOldValue).activity-meta {{ moment currentData.timeOldValue 'LLL' }}
= ' @'
else if(currentData.timeValue)
| {{{_ activityType currentData.timeValue}}}
-
+
if($eq activityType 'deleteComment')
| {{{_ 'activity-deleteComment' currentData.commentId}}}.
diff --git a/client/components/activities/activities.styl b/client/components/activities/activities.styl
index 380e7b40..f3b1acdd 100644
--- a/client/components/activities/activities.styl
+++ b/client/components/activities/activities.styl
@@ -9,7 +9,7 @@
clear: both
.activity
- margin: 10px 0
+ margin: 0.5px 0
display: flex
.member
diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js
index 95084646..50ca019b 100644
--- a/client/components/activities/comments.js
+++ b/client/components/activities/comments.js
@@ -16,9 +16,6 @@ BlazeComponent.extendComponent({
events() {
return [
{
- 'click .js-new-comment:not(.focus)'() {
- commentFormIsOpen.set(true);
- },
'submit .js-new-comment-form'(evt) {
const input = this.getInput();
const text = input.val().trim();
diff --git a/client/components/activities/comments.styl b/client/components/activities/comments.styl
index 22f9c482..ccf24b72 100644
--- a/client/components/activities/comments.styl
+++ b/client/components/activities/comments.styl
@@ -46,3 +46,23 @@
&:is-open
cursor: auto
+
+.comment-item
+ background-color: #fff
+ border: 0
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
+ color: #8c8c8c
+ height: 36px
+ margin: 4px 4px 6px 0
+ width: 92%
+
+ &:hover
+ background: darken(white, 12%)
+
+ &.add-comment
+ display: flex
+ margin: 5px
+
+ a
+ display: block
+ margin: auto
diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js
index 47042ae7..e70a9f67 100644
--- a/client/components/boards/boardBody.js
+++ b/client/components/boards/boardBody.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
const subManager = new SubsManager();
const { calculateIndex, enableClickOnTouch } = Utils;
const swimlaneWhileSortingHeight = 150;
@@ -89,7 +91,6 @@ BlazeComponent.extendComponent({
helper.append(list.clone());
return helper;
},
- handle: '.js-swimlane-header-handle',
items: '.swimlane:not(.placeholder)',
placeholder: 'swimlane placeholder',
distance: 7,
@@ -193,6 +194,32 @@ BlazeComponent.extendComponent({
// ugly touch event hotfix
enableClickOnTouch('.js-swimlane:not(.placeholder)');
+ this.autorun(() => {
+ let showDesktopDragHandles = false;
+ currentUser = Meteor.user();
+ if (currentUser) {
+ showDesktopDragHandles = (currentUser.profile || {})
+ .showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ showDesktopDragHandles = true;
+ } else {
+ showDesktopDragHandles = false;
+ }
+ if (!Utils.isMiniScreen() && showDesktopDragHandles) {
+ $swimlanesDom.sortable({
+ handle: '.js-swimlane-header-handle',
+ });
+ } else if (!Utils.isMiniScreen() && !showDesktopDragHandles) {
+ $swimlanesDom.sortable({
+ handle: '.swimlane-header',
+ });
+ }
+
+ // Disable drag-dropping if the current user is not a board member or is miniscreen
+ $swimlanesDom.sortable('option', 'disabled', !userIsMember());
+ $swimlanesDom.sortable('option', 'disabled', Utils.isMiniScreen());
+ });
+
function userIsMember() {
return (
Meteor.user() &&
@@ -210,21 +237,30 @@ BlazeComponent.extendComponent({
},
isViewSwimlanes() {
- const currentUser = Meteor.user();
- if (!currentUser) return false;
- return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
+ } else {
+ return cookies.get('boardView') === 'board-view-swimlanes';
+ }
},
isViewLists() {
- const currentUser = Meteor.user();
- if (!currentUser) return true;
- return (currentUser.profile || {}).boardView === 'board-view-lists';
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).boardView === 'board-view-lists';
+ } else {
+ return cookies.get('boardView') === 'board-view-lists';
+ }
},
isViewCalendar() {
- const currentUser = Meteor.user();
- if (!currentUser) return false;
- return (currentUser.profile || {}).boardView === 'board-view-cal';
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).boardView === 'board-view-cal';
+ } else {
+ return cookies.get('boardView') === 'board-view-cal';
+ }
},
openNewListForm() {
@@ -381,8 +417,11 @@ BlazeComponent.extendComponent({
};
},
isViewCalendar() {
- const currentUser = Meteor.user();
- if (!currentUser) return false;
- return (currentUser.profile || {}).boardView === 'board-view-cal';
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).boardView === 'board-view-cal';
+ } else {
+ return cookies.get('boardView') === 'board-view-cal';
+ }
},
}).register('calendarView');
diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade
index 175cc2c2..53a74f76 100644
--- a/client/components/boards/boardHeader.jade
+++ b/client/components/boards/boardHeader.jade
@@ -77,10 +77,11 @@ template(name="boardHeaderBar")
i.fa.fa-archive
span {{_ 'archives'}}
- if showSort
- a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}")
- i.fa(class="{{directionClass}}")
- span {{_ 'sort'}}{{_ listSortShortDesc}}
+ //if showSort
+ // a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}")
+ // i.fa(class="{{directionClass}}")
+ // span {{_ 'sort'}}{{_ listSortShortDesc}}
+
a.board-header-btn.js-open-filter-view(
title="{{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}}"
class="{{#if Filter.isActive}}emphasis{{/if}}")
@@ -89,15 +90,6 @@ template(name="boardHeaderBar")
if Filter.isActive
a.board-header-btn-close.js-filter-reset(title="{{_ 'filter-clear'}}")
i.fa.fa-times-thin
-
- if currentUser.isAdmin
- a.board-header-btn.js-open-rules-view(title="{{_ 'rules'}}")
- i.fa.fa-magic
- span {{_ 'rules'}}
- else if currentUser.isBoardAdmin
- a.board-header-btn.js-open-rules-view(title="{{_ 'rules'}}")
- i.fa.fa-magic
- span {{_ 'rules'}}
a.board-header-btn.js-open-search-view(title="{{_ 'search'}}")
i.fa.fa-search
@@ -106,8 +98,14 @@ template(name="boardHeaderBar")
unless currentBoard.isTemplatesBoard
a.board-header-btn.js-toggle-board-view(
title="{{_ 'board-view'}}")
- i.fa.fa-th-large
- span {{#if currentUser.profile.boardView}}{{_ currentUser.profile.boardView}}{{else}}{{_ 'board-view-lists'}}{{/if}}
+ i.fa.fa-caret-down
+ if $eq boardView 'board-view-lists'
+ i.fa.fa-trello
+ if $eq boardView 'board-view-swimlanes'
+ i.fa.fa-th-large
+ if $eq boardView 'board-view-cal'
+ i.fa.fa-calendar
+ span {{#if boardView}}{{_ boardView}}{{else}}{{_ 'board-view-lists'}}{{/if}}
if canModifyBoard
a.board-header-btn.js-multiselection-activate(
@@ -172,6 +170,44 @@ template(name="boardChangeWatchPopup")
i.fa.fa-check
span.sub-name {{_ 'muted-info'}}
+template(name="boardChangeViewPopup")
+ ul.pop-over-list
+ li
+ with "board-view-lists"
+ a.js-open-lists-view
+ i.fa.fa-trello.colorful
+ | {{_ 'board-view-lists'}}
+ if $eq Utils.boardView "board-view-lists"
+ i.fa.fa-check
+ li
+ with "board-view-swimlanes"
+ a.js-open-swimlanes-view
+ i.fa.fa-th-large.colorful
+ | {{_ 'board-view-swimlanes'}}
+ if $eq Utils.boardView "board-view-swimlanes"
+ i.fa.fa-check
+ li
+ with "board-view-cal"
+ a.js-open-cal-view
+ i.fa.fa-calendar.colorful
+ | {{_ 'board-view-cal'}}
+ if $eq Utils.boardView "board-view-cal"
+ i.fa.fa-check
+ if currentUser.isAdmin
+ hr
+ li
+ with "board-view-rules"
+ a.js-open-rules-view(title="{{_ 'rules'}}")
+ i.fa.fa-magic
+ | {{_ 'rules'}}
+ else if currentUser.isBoardAdmin
+ hr
+ li
+ with "board-view-rules"
+ a.js-open-rules-view(title="{{_ 'rules'}}")
+ i.fa.fa-magic
+ | {{_ 'rules'}}
+
template(name="createBoard")
form
label
@@ -198,19 +234,19 @@ template(name="createBoard")
| /
a.js-board-template {{_ 'template'}}
-template(name="listsortPopup")
- h2
- | {{_ 'list-sort-by'}}
- hr
- ul.pop-over-list
- each value in allowedSortValues
- li
- a.js-sort-by(name="{{value.name}}")
- if $eq sortby value.name
- i(class="fa {{Direction}}")
- | {{_ value.label }}{{_ value.shortLabel}}
- if $eq sortby value.name
- i(class="fa fa-check")
+//template(name="listsortPopup")
+// h2
+// | {{_ 'list-sort-by'}}
+// hr
+// ul.pop-over-list
+// each value in allowedSortValues
+// li
+// a.js-sort-by(name="{{value.name}}")
+// if $eq sortby value.name
+// i(class="fa {{Direction}}")
+// | {{_ value.label }}{{_ value.shortLabel}}
+// if $eq sortby value.name
+// i(class="fa fa-check")
template(name="boardChangeTitlePopup")
form
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index e14b1444..9040ed83 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -1,5 +1,7 @@
+/*
const DOWNCLS = 'fa-sort-down';
const UPCLS = 'fa-sort-up';
+*/
Template.boardMenuPopup.events({
'click .js-rename-board': Popup.open('boardChangeTitle'),
'click .js-custom-fields'() {
@@ -28,6 +30,7 @@ Template.boardMenuPopup.events({
'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
+ 'click .js-card-settings': Popup.open('boardCardSettings'),
});
Template.boardMenuPopup.helpers({
@@ -82,6 +85,7 @@ BlazeComponent.extendComponent({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return currentBoard && currentBoard.stars >= 2;
},
+ /*
showSort() {
return Meteor.user().hasSortBy();
},
@@ -101,6 +105,7 @@ BlazeComponent.extendComponent({
listSortShortDesc() {
return `list-label-short-${this.currentListSortBy()}`;
},
+ */
events() {
return [
{
@@ -114,30 +119,14 @@ BlazeComponent.extendComponent({
'click .js-open-archived-board'() {
Modal.open('archivedBoards');
},
- 'click .js-toggle-board-view'() {
- const currentUser = Meteor.user();
- if (
- (currentUser.profile || {}).boardView === 'board-view-swimlanes'
- ) {
- currentUser.setBoardView('board-view-cal');
- } else if (
- (currentUser.profile || {}).boardView === 'board-view-lists'
- ) {
- currentUser.setBoardView('board-view-swimlanes');
- } else if (
- (currentUser.profile || {}).boardView === 'board-view-cal'
- ) {
- currentUser.setBoardView('board-view-lists');
- } else {
- currentUser.setBoardView('board-view-swimlanes');
- }
- },
+ 'click .js-toggle-board-view': Popup.open('boardChangeView'),
'click .js-toggle-sidebar'() {
Sidebar.toggle();
},
'click .js-open-filter-view'() {
Sidebar.setView('filter');
},
+ /*
'click .js-open-sort-view'(evt) {
const target = evt.target;
if (target.tagName === 'I') {
@@ -148,6 +137,7 @@ BlazeComponent.extendComponent({
Popup.open('listsort')(evt);
}
},
+ */
'click .js-filter-reset'(event) {
event.stopPropagation();
Sidebar.setView();
@@ -156,9 +146,6 @@ BlazeComponent.extendComponent({
'click .js-open-search-view'() {
Sidebar.setView('search');
},
- 'click .js-open-rules-view'() {
- Modal.openWide('rulesMain');
- },
'click .js-multiselection-activate'() {
const currentCard = Session.get('currentCard');
MultiSelection.activate();
@@ -186,6 +173,28 @@ Template.boardHeaderBar.helpers({
!Meteor.user().isCommentOnly()
);
},
+ boardView() {
+ return Utils.boardView();
+ },
+});
+
+Template.boardChangeViewPopup.events({
+ 'click .js-open-lists-view'() {
+ Utils.setBoardView('board-view-lists');
+ Popup.close();
+ },
+ 'click .js-open-swimlanes-view'() {
+ Utils.setBoardView('board-view-swimlanes');
+ Popup.close();
+ },
+ 'click .js-open-cal-view'() {
+ Utils.setBoardView('board-view-cal');
+ Popup.close();
+ },
+ 'click .js-open-rules-view'() {
+ Modal.openWide('rulesMain');
+ Popup.close();
+ },
});
const CreateBoard = BlazeComponent.extendComponent({
@@ -308,6 +317,7 @@ BlazeComponent.extendComponent({
},
}).register('boardChangeWatchPopup');
+/*
BlazeComponent.extendComponent({
onCreated() {
//this.sortBy = new ReactiveVar();
@@ -377,3 +387,4 @@ BlazeComponent.extendComponent({
];
},
}).register('listsortPopup');
+*/
diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade
index a5a5c00b..e6e50d7a 100644
--- a/client/components/cards/attachments.jade
+++ b/client/components/cards/attachments.jade
@@ -45,19 +45,22 @@ template(name="attachmentsGalery")
| {{_ 'download'}}
if currentUser.isBoardMember
unless currentUser.isCommentOnly
- if isImage
- a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
- i.fa.fa-thumb-tack
- if($eq ../coverId _id)
- | {{_ 'remove-cover'}}
- else
- | {{_ 'add-cover'}}
- a.js-confirm-delete
- i.fa.fa-close
- | {{_ 'delete'}}
+ unless currentUser.isWorker
+ if isImage
+ a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
+ i.fa.fa-thumb-tack
+ if($eq ../coverId _id)
+ | {{_ 'remove-cover'}}
+ else
+ | {{_ 'add-cover'}}
+ a.js-confirm-delete
+ i.fa.fa-close
+ | {{_ 'delete'}}
if currentUser.isBoardMember
unless currentUser.isCommentOnly
- li.attachment-item.add-attachment
- a.js-add-attachment {{_ 'add-attachment' }}
-
+ unless currentUser.isWorker
+ //li.attachment-item.add-attachment
+ a.js-add-attachment
+ i.fa.fa-paperclip
+ | {{_ 'add-attachment' }}
diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js
index cb54b033..c4b5c6d8 100644
--- a/client/components/cards/cardDate.js
+++ b/client/components/cards/cardDate.js
@@ -97,7 +97,8 @@ Template.dateBadge.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
});
diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade
index 53a264ec..615ae1d5 100644
--- a/client/components/cards/cardDetails.jade
+++ b/client/components/cards/cardDetails.jade
@@ -4,15 +4,27 @@ template(name="cardDetails")
+inlinedForm(classNames="js-card-details-title")
+editCardTitleForm
else
- a.fa.fa-times-thin.close-card-details.js-close-card-details
- if currentUser.isBoardMember
- a.fa.fa-navicon.card-details-menu.js-open-card-details-menu
+ unless isMiniScreen
+ a.fa.fa-times-thin.close-card-details.js-close-card-details
+ if currentUser.isBoardMember
+ a.fa.fa-navicon.card-details-menu.js-open-card-details-menu
+ input.inline-input(type="text" id="cardURL_copy" value="{{ absoluteUrl }}")
+ a.fa.fa-link.card-copy-button.js-copy-link(
+ class="fa-link"
+ title="{{_ 'copy-card-link-to-clipboard'}}"
+ value="{{ absoluteUrl }}"
+ )
+ if isMiniScreen
+ a.fa.fa-times-thin.close-card-details-mobile-web.js-close-card-details
+ if currentUser.isBoardMember
+ a.fa.fa-navicon.card-details-menu-mobile-web.js-open-card-details-menu
+ a.fa.fa-link.card-copy-mobile-button
h2.card-details-title.js-card-title(
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}")
+viewer
= getTitle
- if isWatching
- i.fa.fa-eye.card-details-watch
+ if isWatching
+ i.card-details-watch.fa.fa-eye
.card-details-path
each parentList
| &nbsp; &gt; &nbsp;
@@ -31,70 +43,105 @@ template(name="cardDetails")
p.warning {{_ 'card-archived'}}
.card-details-items
- .card-details-item.card-details-item-received
- h3.card-details-item-title {{_ 'card-received'}}
- if getReceived
- +cardReceivedDate
- else
- if canModifyCard
- a.js-received-date {{_ 'add'}}
-
- .card-details-item.card-details-item-start
- h3.card-details-item-title {{_ 'card-start'}}
- if getStart
- +cardStartDate
- else
- if canModifyCard
- a.js-start-date {{_ 'add'}}
-
- .card-details-item.card-details-item-due
- h3.card-details-item-title {{_ 'card-due'}}
- if getDue
- +cardDueDate
- else
+ if currentBoard.allowsReceivedDate
+ .card-details-item.card-details-item-received
+ h3
+ i.fa.fa-sign-out
+ card-details-item-title {{_ 'card-received'}}
+ if getReceived
+ +cardReceivedDate
+ else
+ if canModifyCard
+ unless currentUser.isWorker
+ a.card-label.add-label.js-received-date
+ i.fa.fa-plus
+
+ if currentBoard.allowsStartDate
+ .card-details-item.card-details-item-start
+ h3
+ i.fa.fa-hourglass-start
+ card-details-item-title {{_ 'card-start'}}
+ if getStart
+ +cardStartDate
+ else
+ if canModifyCard
+ unless currentUser.isWorker
+ a.card-label.add-label.js-start-date
+ i.fa.fa-plus
+
+ if currentBoard.allowsDueDate
+ .card-details-item.card-details-item-due
+ h3
+ i.fa.fa-sign-in
+ card-details-item-title {{_ 'card-due'}}
+ if getDue
+ +cardDueDate
+ else
+ if canModifyCard
+ unless currentUser.isWorker
+ a.card-label.add-label.js-due-date
+ i.fa.fa-plus
+
+ if currentBoard.allowsEndDate
+ .card-details-item.card-details-item-end
+ h3
+ i.fa.fa-hourglass-end
+ card-details-item-title {{_ 'card-end'}}
+ if getEnd
+ +cardEndDate
+ else
+ if canModifyCard
+ unless currentUser.isWorker
+ a.card-label.add-label.js-end-date
+ i.fa.fa-plus
+
+ //.card-details-items
+ if currentBoard.allowsMembers
+ .card-details-item.card-details-item-members
+ h3
+ i.fa.fa-users
+ card-details-item-title {{_ 'members'}}
+ each getMembers
+ +userAvatar(userId=this cardId=../_id)
+ | {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
- a.js-due-date {{_ 'add'}}
-
- .card-details-item.card-details-item-end
- h3.card-details-item-title {{_ 'card-end'}}
- if getEnd
- +cardEndDate
- else
+ unless currentUser.isWorker
+ a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
+ i.fa.fa-plus
+
+ //if assigneeSelected
+ if currentBoard.allowsAssignee
+ .card-details-item.card-details-item-assignees
+ h3
+ i.fa.fa-user
+ card-details-item-title {{_ 'assignee'}}
+ each getAssignees
+ +userAvatarAssignee(userId=this cardId=../_id)
+ | {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
- a.js-end-date {{_ 'add'}}
-
- .card-details-items
- .card-details-item.card-details-item-members
- h3.card-details-item-title {{_ 'members'}}
- each getMembers
- +userAvatar(userId=this cardId=../_id)
- | {{! XXX Hack to hide syntaxic coloration /// }}
- if canModifyCard
- a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
- i.fa.fa-plus
-
- .card-details-item.card-details-item-assignees
- h3.card-details-item-title {{_ 'assignee'}}
- each getAssignees
- +userAvatarAssignee(userId=this cardId=../_id)
- | {{! XXX Hack to hide syntaxic coloration /// }}
- if canModifyCard
- unless assigneeSelected
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
+ if currentUser.isWorker
+ unless assigneeSelected
+ a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
+ i.fa.fa-plus
+
+ if currentBoard.allowsLabels
+ .card-details-item.card-details-item-labels
+ h3
+ i.fa.fa-tags
+ card-details-item-title {{_ 'labels'}}
+ a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
+ each labels
+ span.card-label(class="card-label-{{color}}" title=name)
+ +viewer
+ = name
+ if canModifyCard
+ unless currentUser.isWorker
+ a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
+ i.fa.fa-plus
- .card-details-item.card-details-item-labels
- h3.card-details-item-title {{_ 'labels'}}
- a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
- each labels
- span.card-label(class="card-label-{{color}}" title=name)
- +viewer
- = name
- if canModifyCard
- a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
- i.fa.fa-plus
-
- .card-details-items
+ //.card-details-items
each customFieldsWD
.card-details-item.card-details-item-customfield
h3.card-details-item-title
@@ -102,7 +149,7 @@ template(name="cardDetails")
= definition.name
+cardCustomField
- .card-details-items
+ //.card-details-items
if getSpentTime
.card-details-item.card-details-item-spent
if getIsOvertime
@@ -111,84 +158,103 @@ template(name="cardDetails")
h3.card-details-item-title {{_ 'spent-time-hours'}}
+cardSpentTime
- //- XXX We should use "editable" to avoid repetiting ourselves
- if canModifyCard
- h3.card-details-item-title {{_ 'description'}}
- +inlinedCardDescription(classNames="card-description js-card-description")
- +editor(autofocus=true)
- | {{getUnsavedValue 'cardDescription' _id getDescription}}
- .edit-controls.clearfix
- button.primary(type="submit") {{_ 'save'}}
- a.fa.fa-times-thin.js-close-inlined-form
- else
- a.js-open-inlined-form
- if getDescription
+ //.card-details-items
+ if currentBoard.allowsRequestedBy
+ .card-details-item.card-details-item-name
+ h3
+ i.fa.fa-shopping-cart
+ card-details-item-title {{_ 'requested-by'}}
+ if canModifyCard
+ unless currentUser.isWorker
+ +inlinedForm(classNames="js-card-details-requester")
+ +editCardRequesterForm
+ else
+ a.js-open-inlined-form
+ if getRequestedBy
+ +viewer
+ = getRequestedBy
+ else
+ | {{_ 'add'}}
+ else if getRequestedBy
+viewer
- = getDescription
- else
- | {{_ 'edit'}}
- if (hasUnsavedValue 'cardDescription' _id)
- p.quiet
- | {{_ 'unsaved-description'}}
- a.js-open-inlined-form {{_ 'view-it'}}
- = ' - '
- a.js-close-inlined-form {{_ 'discard'}}
- else if getDescription
- h3.card-details-item-title {{_ 'description'}}
- +viewer
- = getDescription
+ = getRequestedBy
- .card-details-items
- .card-details-item.card-details-item-name
- h3.card-details-item-title {{_ 'requested-by'}}
- if canModifyCard
- +inlinedForm(classNames="js-card-details-requester")
- +editCardRequesterForm
- else
- a.js-open-inlined-form
- if getRequestedBy
- +viewer
- = getRequestedBy
- else
- | {{_ 'add'}}
- else if getRequestedBy
- +viewer
- = getRequestedBy
-
- .card-details-item.card-details-item-name
- h3.card-details-item-title {{_ 'assigned-by'}}
- if canModifyCard
- +inlinedForm(classNames="js-card-details-assigner")
- +editCardAssignerForm
- else
- a.js-open-inlined-form
- if getAssignedBy
- +viewer
- = getAssignedBy
+ if currentBoard.allowsAssignedBy
+ .card-details-item.card-details-item-name
+ h3
+ i.fa.fa-user-plus
+ card-details-item-title {{_ 'assigned-by'}}
+ if canModifyCard
+ unless currentUser.isWorker
+ +inlinedForm(classNames="js-card-details-assigner")
+ +editCardAssignerForm
else
- | {{_ 'add'}}
- else if getRequestedBy
- +viewer
- = getAssignedBy
-
- hr
- +checklists(cardId = _id)
-
- if currentBoard.allowsSubtasks
- hr
- +subtasks(cardId = _id)
-
- hr
- h3
- i.fa.fa-paperclip
- | {{_ 'attachments'}}
+ a.js-open-inlined-form
+ if getAssignedBy
+ +viewer
+ = getAssignedBy
+ else
+ | {{_ 'add'}}
+ else if getRequestedBy
+ +viewer
+ = getAssignedBy
- +attachmentsGalery
+ //- XXX We should use "editable" to avoid repetiting ourselves
+ if canModifyCard
+ unless currentUser.isWorker
+ if currentBoard.allowsDescriptionTitle
+ h3
+ i.fa.fa-align-left
+ card-details-item-title {{_ 'description'}}
+ if currentBoard.allowsDescriptionText
+ +inlinedCardDescription(classNames="card-description js-card-description")
+ +editor(autofocus=true)
+ | {{getUnsavedValue 'cardDescription' _id getDescription}}
+ .edit-controls.clearfix
+ button.primary(type="submit") {{_ 'save'}}
+ a.fa.fa-times-thin.js-close-inlined-form
+ else
+ if currentBoard.allowsDescriptionText
+ a.js-open-inlined-form
+ if getDescription
+ +viewer
+ = getDescription
+ else
+ | {{_ 'edit'}}
+ if (hasUnsavedValue 'cardDescription' _id)
+ p.quiet
+ | {{_ 'unsaved-description'}}
+ a.js-open-inlined-form {{_ 'view-it'}}
+ = ' - '
+ a.js-close-inlined-form {{_ 'discard'}}
+ else if getDescription
+ if currentBoard.allowsDescriptionTitle
+ h3.card-details-item-title {{_ 'description'}}
+ if currentBoard.allowsDescriptionText
+ +viewer
+ = getDescription
+
+ .card-checklist-attachmentGalerys
+ .card-checklist-attachmentGalery.card-checklists
+ if currentBoard.allowsChecklists
+ +checklists(cardId = _id)
+ if currentBoard.allowsSubtasks
+ hr
+ +subtasks(cardId = _id)
+ if currentBoard.allowsAttachments
+ //- hr
+ //- h3
+ //- i.fa.fa-paperclip
+ //- | {{_ 'attachments'}}
+ .card-checklist-attachmentGalery.card-attachmentGalery
+ +attachmentsGalery
hr
unless currentUser.isNoComments
.activity-title
- h3 {{ _ 'activity'}}
+ h3
+ i.fa.fa-history
+ | {{ _ 'activity'}}
if currentUser.isBoardMember
.material-toggle-switch
span.toggle-switch-title {{_ 'hide-system-messages'}}
@@ -197,9 +263,10 @@ template(name="cardDetails")
else
input.toggle-switch(type="checkbox" id="toggleButton")
label.toggle-label(for="toggleButton")
- if currentUser.isBoardMember
- unless currentUser.isNoComments
- +commentForm
+ if currentBoard.allowsComments
+ if currentUser.isBoardMember
+ unless currentUser.isNoComments
+ +commentForm
unless currentUser.isNoComments
if isLoaded.get
if isLinkedCard
@@ -230,32 +297,79 @@ template(name="editCardAssignerForm")
template(name="cardDetailsActionsPopup")
ul.pop-over-list
- li: a.js-toggle-watch-card {{#if isWatching}}{{_ 'unwatch'}}{{else}}{{_ 'watch'}}{{/if}}
+ li
+ a.js-toggle-watch-card
+ if isWatching
+ i.fa.fa-eye
+ | {{_ 'unwatch'}}
+ else
+ i.fa.fa-eye-slash
+ | {{_ 'watch'}}
if canModifyCard
- hr
- ul.pop-over-list
- //li: a.js-members {{_ 'card-edit-members'}}
- //li: a.js-labels {{_ 'card-edit-labels'}}
- //li: a.js-attachments {{_ 'card-edit-attachments'}}
- li: a.js-custom-fields {{_ 'card-edit-custom-fields'}}
- //li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
- //li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
- //li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
- //li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
- li: a.js-spent-time {{_ 'editCardSpentTimePopup-title'}}
- li: a.js-set-card-color {{_ 'setCardColorPopup-title'}}
- hr
- ul.pop-over-list
- li: a.js-move-card-to-top {{_ 'moveCardToTop-title'}}
- li: a.js-move-card-to-bottom {{_ 'moveCardToBottom-title'}}
- hr
+ unless currentUser.isWorker
+ hr
+ ul.pop-over-list
+ //li: a.js-members {{_ 'card-edit-members'}}
+ //li: a.js-labels {{_ 'card-edit-labels'}}
+ //li: a.js-attachments {{_ 'card-edit-attachments'}}
+ li
+ a.js-custom-fields
+ i.fa.fa-list-alt
+ | {{_ 'card-edit-custom-fields'}}
+ //li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
+ //li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
+ //li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
+ //li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
+ li
+ a.js-spent-time
+ i.fa.fa-clock-o
+ | {{_ 'editCardSpentTimePopup-title'}}
+ li
+ a.js-set-card-color
+ i.fa.fa-paint-brush
+ | {{_ 'setCardColorPopup-title'}}
+ hr
ul.pop-over-list
- li: a.js-move-card {{_ 'moveCardPopup-title'}}
- li: a.js-copy-card {{_ 'copyCardPopup-title'}}
- li: a.js-copy-checklist-cards {{_ 'copyChecklistToManyCardsPopup-title'}}
+ li
+ a.js-move-card-to-top
+ i.fa.fa-arrow-up
+ | {{_ 'moveCardToTop-title'}}
+ li
+ a.js-move-card-to-bottom
+ i.fa.fa-arrow-down
+ | {{_ 'moveCardToBottom-title'}}
+ unless currentUser.isWorker
+ hr
+ ul.pop-over-list
+ li
+ a.js-move-card
+ i.fa.fa-arrow-right
+ | {{_ 'moveCardPopup-title'}}
+ li
+ a.js-copy-card
+ i.fa.fa-copy
+ | {{_ 'copyCardPopup-title'}}
+ hr
+ ul.pop-over-list
+ li
+ a.js-copy-checklist-cards
+ i.fa.fa-list
+ i.fa.fa-copy
+ | {{_ 'copyChecklistToManyCardsPopup-title'}}
unless archived
- li: a.js-archive {{_ 'archive-card'}}
- li: a.js-more {{_ 'cardMorePopup-title'}}
+ hr
+ ul.pop-over-list
+ li
+ a.js-archive
+ i.fa.fa-arrow-right
+ i.fa.fa-archive
+ | {{_ 'archive-card'}}
+ hr
+ ul.pop-over-list
+ li
+ a.js-more
+ i.fa.fa-link
+ | {{_ 'cardMorePopup-title'}}
template(name="moveCardPopup")
+boardsAndLists
@@ -307,16 +421,27 @@ template(name="cardMembersPopup")
i.fa.fa-check
template(name="cardAssigneesPopup")
- ul.pop-over-list.js-card-assignee-list
- each board.activeMembers
- li.item(class="{{#if isCardAssignee}}active{{/if}}")
- a.name.js-select-assignee(href="#")
- +userAvatar(userId=user._id)
- span.full-name
- = user.profile.fullname
- | (<span class="username">{{ user.username }}</span>)
- if isCardAssignee
- i.fa.fa-check
+ unless currentUser.isWorker
+ ul.pop-over-list.js-card-assignee-list
+ each board.activeMembers
+ li.item(class="{{#if isCardAssignee}}active{{/if}}")
+ a.name.js-select-assignee(href="#")
+ +userAvatar(userId=user._id)
+ span.full-name
+ = user.profile.fullname
+ | (<span class="username">{{ user.username }}</span>)
+ if isCardAssignee
+ i.fa.fa-check
+ if currentUser.isWorker
+ ul.pop-over-list.js-card-assignee-list
+ li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}")
+ a.name.js-select-assignee(href="#")
+ +userAvatar(userId=currentUser._id)
+ span.full-name
+ = currentUser.profile.fullname
+ | (<span class="username">{{ currentUser.username }}</span>)
+ if currentUser.isCardAssignee
+ i.fa.fa-check
template(name="userAvatarAssignee")
a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})")
@@ -344,11 +469,13 @@ template(name="cardAssigneePopup")
p.quiet @{{ user.username }}
ul.pop-over-list
if currentUser.isNotCommentOnly
+ unless currentUser.isWorker
li: a.js-remove-assignee {{_ 'remove-member-from-card'}}
- if $eq currentUser._id user._id
- with currentUser
- li: a.js-edit-profile {{_ 'edit-profile'}}
+ unless currentUser.isWorker
+ if $eq currentUser._id user._id
+ with currentUser
+ li: a.js-edit-profile {{_ 'edit-profile'}}
template(name="userAvatarAssigneeInitials")
svg.avatar.avatar-assignee-initials(viewBox="0 0 {{viewPortWidth}} 15")
diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js
index 7bb54223..5fdc5579 100644
--- a/client/components/cards/cardDetails.js
+++ b/client/components/cards/cardDetails.js
@@ -51,7 +51,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
@@ -252,6 +253,12 @@ BlazeComponent.extendComponent({
if ($subtasksDom.data('sortable')) {
$subtasksDom.sortable('option', 'disabled', !userIsMember());
}
+ if ($checklistsDom.data('sortable')) {
+ $checklistsDom.sortable('option', 'disabled', Utils.isMiniScreen());
+ }
+ if ($subtasksDom.data('sortable')) {
+ $subtasksDom.sortable('option', 'disabled', Utils.isMiniScreen());
+ }
});
},
@@ -278,6 +285,29 @@ BlazeComponent.extendComponent({
'click .js-close-card-details'() {
Utils.goBoardId(this.data().boardId);
},
+ 'click .js-copy-link'() {
+ StringToCopyElement = document.getElementById('cardURL_copy');
+ StringToCopyElement.select();
+ if (document.execCommand('copy')) {
+ StringToCopyElement.blur();
+ } else {
+ document.getElementById('cardURL_copy').selectionStart = 0;
+ document.getElementById('cardURL_copy').selectionEnd = 999;
+ document.execCommand('copy');
+ if (window.getSelection) {
+ if (window.getSelection().empty) {
+ // Chrome
+ window.getSelection().empty();
+ } else if (window.getSelection().removeAllRanges) {
+ // Firefox
+ window.getSelection().removeAllRanges();
+ }
+ } else if (document.selection) {
+ // IE?
+ document.selection.empty();
+ }
+ }
+ },
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
'submit .js-card-description'(event) {
event.preventDefault();
@@ -291,6 +321,8 @@ BlazeComponent.extendComponent({
.trim();
if (title) {
this.data().setTitle(title);
+ } else {
+ this.data().setTitle('');
}
},
'submit .js-card-details-assigner'(event) {
@@ -300,6 +332,8 @@ BlazeComponent.extendComponent({
.trim();
if (assigner) {
this.data().setAssignedBy(assigner);
+ } else {
+ this.data().setAssignedBy('');
}
},
'submit .js-card-details-requester'(event) {
@@ -309,6 +343,8 @@ BlazeComponent.extendComponent({
.trim();
if (requester) {
this.data().setRequestedBy(requester);
+ } else {
+ this.data().setRequestedBy('');
}
},
'click .js-member': Popup.open('cardMember'),
@@ -364,6 +400,54 @@ Template.cardDetails.helpers({
});
},
+ receivedSelected() {
+ if (this.getReceived().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ startSelected() {
+ if (this.getStart().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ endSelected() {
+ if (this.getEnd().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ dueSelected() {
+ if (this.getDue().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ memberSelected() {
+ if (this.getMembers().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ labelSelected() {
+ if (this.getLabels().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
assigneeSelected() {
if (this.getAssignees().length === 0) {
return false;
@@ -372,6 +456,22 @@ Template.cardDetails.helpers({
}
},
+ requestBySelected() {
+ if (this.getRequestBy().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
+ assigneeBySelected() {
+ if (this.getAssigneeBy().length === 0) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
memberType() {
const user = Users.findOne(this.userId);
return user && user.isBoardAdmin() ? 'admin' : 'normal';
diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl
index e4549e44..80fa87c0 100644
--- a/client/components/cards/cardDetails.styl
+++ b/client/components/cards/cardDetails.styl
@@ -4,6 +4,12 @@
avatar-radius = 50%
+#cardURL_copy
+ // Have clipboard text not visible by moving it to far left
+ position: absolute
+ left: -2000px
+ top: 0px
+
.assignee
border-radius: 3px
display: block
@@ -107,7 +113,11 @@ avatar-radius = 50%
border-bottom: 1px solid darken(white, 14%)
.close-card-details,
- .card-details-menu
+ .card-details-menu,
+ .card-copy-button,
+ .card-copy-mobile-button,
+ .close-card-details-mobile-web,
+ .card-details-menu-mobile-web
float: right
.close-card-details
@@ -115,10 +125,30 @@ avatar-radius = 50%
padding: 5px
margin-right: -8px
+ .close-card-details-mobile-web
+ font-size: 24px
+ padding: 5px
+ margin-right: 40px
+
+ .card-copy-button
+ font-size: 17px
+ padding: 10px
+ margin-right: 10px
+
+ .card-copy-mobile-button
+ font-size: 17px
+ padding: 10px
+ margin-right: 10px
+
.card-details-menu
font-size: 17px
padding: 10px
+ .card-details-menu-mobile-web
+ font-size: 17px
+ padding: 10px
+ margin-right: 30px
+
.card-details-watch
font-size: 17px
padding-left: 7px
diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade
index 279d3671..391769e9 100644
--- a/client/components/cards/checklists.jade
+++ b/client/components/cards/checklists.jade
@@ -1,5 +1,7 @@
template(name="checklists")
- h3 {{_ 'checklists'}}
+ h3
+ i.fa.fa-check
+ | {{_ 'checklists'}}
if toggleDeleteDialog.get
.board-overlay#card-details-overlay
+checklistDeleteDialog(checklist = checklistToDelete)
diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js
index 57939eb8..c88fdd82 100644
--- a/client/components/cards/checklists.js
+++ b/client/components/cards/checklists.js
@@ -60,6 +60,9 @@ BlazeComponent.extendComponent({
if ($itemsDom.data('sortable')) {
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
}
+ if ($itemsDom.data('sortable')) {
+ $(self.itemsDom).sortable('option', 'disabled', Utils.isMiniScreen());
+ }
});
},
@@ -67,7 +70,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
}).register('checklistDetail');
@@ -120,7 +124,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
@@ -228,7 +233,8 @@ Template.checklistItemDetail.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
});
diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade
index 0a35bd3a..6a073424 100644
--- a/client/components/cards/minicard.jade
+++ b/client/components/cards/minicard.jade
@@ -4,8 +4,8 @@ template(name="minicard")
class="{{#if isLinkedBoard}}linked-board{{/if}}"
class="minicard-{{colorClass}}")
if isMiniScreen
- .handle
- .fa.fa-arrows
+ //.handle
+ // .fa.fa-arrows
unless isMiniScreen
if showDesktopDragHandles
.handle
@@ -67,14 +67,15 @@ template(name="minicard")
.minicard-custom-fields
each customFieldsWD
if definition.showOnCard
- .minicard-custom-field
- if definition.showLabelOnMiniCard
+ if trueValue
+ .minicard-custom-field
+ if definition.showLabelOnMiniCard
+ .minicard-custom-field-item
+ +viewer
+ = definition.name
.minicard-custom-field-item
+viewer
- = definition.name
- .minicard-custom-field-item
- +viewer
- = trueValue
+ = trueValue
if getAssignees
.minicard-assignees.js-minicard-assignees
diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js
index 430042f4..200e019d 100644
--- a/client/components/cards/minicard.js
+++ b/client/components/cards/minicard.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
// Template.cards.events({
// 'click .member': Popup.open('cardMember')
// });
@@ -18,7 +20,11 @@ BlazeComponent.extendComponent({
},
{
'click .js-toggle-minicard-label-text'() {
- Meteor.call('toggleMinicardLabelText');
+ if (cookies.has('hiddenMinicardLabelText')) {
+ cookies.remove('hiddenMinicardLabelText'); //true
+ } else {
+ cookies.set('hiddenMinicardLabelText', 'true'); //true
+ }
},
},
];
@@ -27,10 +33,24 @@ BlazeComponent.extendComponent({
Template.minicard.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
hiddenMinicardLabelText() {
- return Meteor.user().hasHiddenMinicardLabelText();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).hiddenMinicardLabelText;
+ } else if (cookies.has('hiddenMinicardLabelText')) {
+ return true;
+ } else {
+ return false;
+ }
},
coverUrl() {
return Attachments.findOne(this.coverId).link('original', '/');
diff --git a/client/components/cards/subtasks.jade b/client/components/cards/subtasks.jade
index 7e64e23f..df35bed3 100644
--- a/client/components/cards/subtasks.jade
+++ b/client/components/cards/subtasks.jade
@@ -1,5 +1,7 @@
template(name="subtasks")
- h3 {{_ 'subtasks'}}
+ h3
+ i.fa.fa-sitemap
+ | {{_ 'subtasks'}}
if toggleDeleteDialog.get
.board-overlay#card-details-overlay
+subtaskDeleteDialog(subtask = subtaskToDelete)
diff --git a/client/components/cards/subtasks.js b/client/components/cards/subtasks.js
index fab860bb..34348fe1 100644
--- a/client/components/cards/subtasks.js
+++ b/client/components/cards/subtasks.js
@@ -3,7 +3,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
}).register('subtaskDetail');
@@ -55,7 +56,8 @@ BlazeComponent.extendComponent({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
@@ -154,7 +156,8 @@ Template.subtaskItemDetail.helpers({
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
});
diff --git a/client/components/lists/list.js b/client/components/lists/list.js
index b7b8b2e0..8574caf7 100644
--- a/client/components/lists/list.js
+++ b/client/components/lists/list.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
const { calculateIndex, enableClickOnTouch } = Utils;
BlazeComponent.extendComponent({
@@ -31,18 +33,6 @@ BlazeComponent.extendComponent({
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
const $cards = this.$('.js-minicards');
- if (Utils.isMiniScreen) {
- $('.js-minicards').sortable({
- handle: '.handle',
- });
- }
-
- if (!Utils.isMiniScreen && showDesktopDragHandles) {
- $('.js-minicards').sortable({
- handle: '.handle',
- });
- }
-
$cards.sortable({
connectWith: '.js-minicards:not(.js-list-full)',
tolerance: 'pointer',
@@ -85,16 +75,15 @@ BlazeComponent.extendComponent({
const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
let swimlaneId = '';
- const boardView = (Meteor.user().profile || {}).boardView;
if (
- boardView === 'board-view-swimlanes' ||
+ Utils.boardView() === 'board-view-swimlanes' ||
currentBoard.isTemplatesBoard()
)
swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id;
else if (
- boardView === 'board-view-lists' ||
- boardView === 'board-view-cal' ||
- !boardView
+ Utils.boardView() === 'board-view-lists' ||
+ Utils.boardView() === 'board-view-cal' ||
+ !Utils.boardView
)
swimlaneId = currentBoard.getDefaultSwimline()._id;
@@ -128,9 +117,49 @@ BlazeComponent.extendComponent({
// ugly touch event hotfix
enableClickOnTouch(itemsSelector);
- // Disable drag-dropping if the current user is not a board member or is comment only
this.autorun(() => {
- $cards.sortable('option', 'disabled', !userIsMember());
+ let showDesktopDragHandles = false;
+ currentUser = Meteor.user();
+ if (currentUser) {
+ showDesktopDragHandles = (currentUser.profile || {})
+ .showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ showDesktopDragHandles = true;
+ } else {
+ showDesktopDragHandles = false;
+ }
+
+ if (!Utils.isMiniScreen() && showDesktopDragHandles) {
+ $cards.sortable({
+ handle: '.handle',
+ });
+ } else if (!Utils.isMiniScreen() && !showDesktopDragHandles) {
+ $cards.sortable({
+ handle: '.minicard',
+ });
+ }
+
+ if ($cards.data('sortable')) {
+ $cards.sortable(
+ 'option',
+ 'disabled',
+ // Disable drag-dropping when user is not member/is miniscreen
+ !userIsMember(),
+ // Not disable drag-dropping while in multi-selection mode
+ // MultiSelection.isActive() || !userIsMember(),
+ );
+ }
+
+ if ($cards.data('sortable')) {
+ $cards.sortable(
+ 'option',
+ 'disabled',
+ // Disable drag-dropping when user is not member/is miniscreen
+ Utils.isMiniScreen(),
+ // Not disable drag-dropping while in multi-selection mode
+ // MultiSelection.isActive() || !userIsMember(),
+ );
+ }
});
// We want to re-run this function any time a card is added.
@@ -163,7 +192,14 @@ BlazeComponent.extendComponent({
Template.list.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
});
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js
index c8e41a0b..89c27ec7 100644
--- a/client/components/lists/listBody.js
+++ b/client/components/lists/listBody.js
@@ -48,7 +48,6 @@ BlazeComponent.extendComponent({
const board = this.data().board();
let linkedId = '';
let swimlaneId = '';
- const boardView = (Meteor.user().profile || {}).boardView;
let cardType = 'cardType-card';
if (title) {
if (board.isTemplatesBoard()) {
@@ -71,14 +70,14 @@ BlazeComponent.extendComponent({
});
cardType = 'cardType-linkedBoard';
}
- } else if (boardView === 'board-view-swimlanes')
+ } else if (Utils.boardView() === 'board-view-swimlanes')
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id;
else if (
- boardView === 'board-view-lists' ||
- boardView === 'board-view-cal' ||
- !boardView
+ Utils.boardView() === 'board-view-lists' ||
+ Utils.boardView() === 'board-view-cal' ||
+ !Utils.boardView
)
swimlaneId = board.getDefaultSwimline()._id;
@@ -157,9 +156,8 @@ BlazeComponent.extendComponent({
},
idOrNull(swimlaneId) {
- const currentUser = Meteor.user();
if (
- (currentUser.profile || {}).boardView === 'board-view-swimlanes' ||
+ Utils.boardView() === 'board-view-swimlanes' ||
this.data()
.board()
.isTemplatesBoard()
@@ -191,7 +189,8 @@ BlazeComponent.extendComponent({
!this.reachedWipLimit() &&
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
@@ -397,10 +396,9 @@ BlazeComponent.extendComponent({
'.js-swimlane',
);
this.swimlaneId = '';
- const boardView = (Meteor.user().profile || {}).boardView;
- if (boardView === 'board-view-swimlanes')
+ if (Utils.boardView() === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
- else if (boardView === 'board-view-lists' || !boardView)
+ else if (Utils.boardView() === 'board-view-lists' || !Utils.boardView)
this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
},
@@ -580,7 +578,7 @@ BlazeComponent.extendComponent({
const swimlane = $(Popup._getTopStack().openerElement).parents(
'.js-swimlane',
);
- if ((Meteor.user().profile || {}).boardView === 'board-view-swimlanes')
+ if (Utils.boardView() === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
// List where to insert card
@@ -709,22 +707,18 @@ BlazeComponent.extendComponent({
if (isSandstorm) {
const user = Meteor.user();
if (user) {
- const boardView = (Meteor.user().profile || {}).boardView;
- if (boardView === 'board-view-swimlanes') {
+ if (Utils.boardView() === 'board-view-swimlanes') {
this.swimlaneId = this.parentComponent()
.parentComponent()
.parentComponent()
.data()._id;
}
}
- } else {
- const boardView = (Meteor.user().profile || {}).boardView;
- if (boardView === 'board-view-swimlanes') {
- this.swimlaneId = this.parentComponent()
- .parentComponent()
- .parentComponent()
- .data()._id;
- }
+ } else if (Utils.boardView() === 'board-view-swimlanes') {
+ this.swimlaneId = this.parentComponent()
+ .parentComponent()
+ .parentComponent()
+ .data()._id;
}
},
diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade
index 064303ee..182fee9e 100644
--- a/client/components/lists/listHeader.jade
+++ b/client/components/lists/listHeader.jade
@@ -10,7 +10,7 @@ template(name="listHeader")
a.list-header-left-icon.fa.fa-angle-left.js-unselect-list
h2.list-header-name(
title="{{ moment modifiedAt 'LLL' }}"
- class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}js-open-inlined-form is-editable{{/unless}}{{/if}}")
+ class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}")
+viewer
= title
if wipLimit.enabled
@@ -30,17 +30,17 @@ template(name="listHeader")
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon
a.fa.fa-navicon.js-open-list-menu
- a.list-header-handle.handle.fa.fa-arrows.js-list-handle
+ //a.list-header-handle.handle.fa.fa-arrows.js-list-handle
else
a.list-header-menu-icon.fa.fa-angle-right.js-select-list
- a.list-header-handle.handle.fa.fa-arrows.js-list-handle
+ //a.list-header-handle.handle.fa.fa-arrows.js-list-handle
else if currentUser.isBoardMember
if isWatching
i.list-header-watch-icon.fa.fa-eye
div.list-header-menu
unless currentUser.isCommentOnly
- if isBoardAdmin
- a.fa.js-list-star.list-header-plus-icon(class="fa-star{{#unless starred}}-o{{/unless}}")
+ //if isBoardAdmin
+ // a.fa.js-list-star.list-header-plus-icon(class="fa-star{{#unless starred}}-o{{/unless}}")
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon
a.fa.fa-navicon.js-open-list-menu
@@ -56,25 +56,47 @@ template(name="editListTitleForm")
template(name="listActionPopup")
ul.pop-over-list
- li: a.js-toggle-watch-list {{#if isWatching}}{{_ 'unwatch'}}{{else}}{{_ 'watch'}}{{/if}}
+ li
+ a.js-toggle-watch-list
+ if isWatching
+ i.fa.fa-eye
+ | {{_ 'unwatch'}}
+ else
+ i.fa.fa-eye-slash
+ | {{_ 'watch'}}
unless currentUser.isCommentOnly
- hr
- ul.pop-over-list
- li: a.js-set-color-list {{_ 'set-color-list'}}
- hr
+ unless currentUser.isWorker
+ ul.pop-over-list
+ li
+ a.js-set-color-list
+ i.fa.fa-paint-brush
+ | {{_ 'set-color-list'}}
ul.pop-over-list
if cards.count
- li: a.js-select-cards {{_ 'list-select-cards'}}
- hr
+ li
+ a.js-select-cards
+ i.fa.fa-check-square
+ | {{_ 'list-select-cards'}}
if currentUser.isBoardAdmin
ul.pop-over-list
- li: a.js-set-wip-limit {{#if isWipLimitEnabled }}{{_ 'edit-wip-limit'}}{{else}}{{_ 'setWipLimitPopup-title'}}{{/if}}
+ li
+ a.js-set-wip-limit
+ i.fa.fa-ban
+ | {{#if isWipLimitEnabled }}{{_ 'edit-wip-limit'}}{{else}}{{_ 'setWipLimitPopup-title'}}{{/if}}
+ unless currentUser.isWorker
hr
- ul.pop-over-list
- li: a.js-close-list {{_ 'archive-list'}}
+ ul.pop-over-list
+ li
+ a.js-close-list
+ i.fa.fa-arrow-right
+ i.fa.fa-archive
+ | {{_ 'archive-list'}}
hr
ul.pop-over-list
- li: a.js-more {{_ 'listMorePopup-title'}}
+ li
+ a.js-more
+ i.fa.fa-link
+ | {{_ 'listMorePopup-title'}}
template(name="boardLists")
ul.pop-over-list
@@ -94,7 +116,8 @@ template(name="listMorePopup")
input.inline-input(type="text" readonly value="{{ rootUrl }}")
| {{_ 'added'}}
span.date(title=list.createdAt) {{ moment createdAt 'LLL' }}
- a.js-delete {{_ 'delete'}}
+ unless currentUser.isWorker
+ a.js-delete {{_ 'delete'}}
template(name="listDeletePopup")
p {{_ "list-delete-pop"}}
diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js
index b524d4e0..46dbd748 100644
--- a/client/components/lists/listHeader.js
+++ b/client/components/lists/listHeader.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
let listsColors;
Meteor.startup(() => {
listsColors = Lists.simpleSchema()._schema.color.allowedValues;
@@ -7,9 +9,10 @@ BlazeComponent.extendComponent({
canSeeAddCard() {
const list = Template.currentData();
return (
- !list.getWipLimit('enabled') ||
- list.getWipLimit('soft') ||
- !this.reachedWipLimit()
+ (!list.getWipLimit('enabled') ||
+ list.getWipLimit('soft') ||
+ !this.reachedWipLimit()) &&
+ !Meteor.user().isWorker()
);
},
@@ -44,14 +47,18 @@ BlazeComponent.extendComponent({
},
limitToShowCardsCount() {
- return Meteor.user().getLimitToShowCardsCount();
+ const currentUser = Meteor.user();
+ if (currentUser) {
+ return Meteor.user().getLimitToShowCardsCount();
+ } else {
+ return false;
+ }
},
cardsCount() {
const list = Template.currentData();
let swimlaneId = '';
- const boardView = (Meteor.user().profile || {}).boardView;
- if (boardView === 'board-view-swimlanes')
+ if (Utils.boardView() === 'board-view-swimlanes')
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id;
@@ -100,7 +107,14 @@ BlazeComponent.extendComponent({
Template.listHeader.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
});
diff --git a/client/components/main/header.styl b/client/components/main/header.styl
index e3c7618d..f77c2aca 100644
--- a/client/components/main/header.styl
+++ b/client/components/main/header.styl
@@ -218,6 +218,9 @@
padding: 10px
margin: -10px 0 -10px -10px
+.announcement .viewer
+ display: inline-block
+
.announcement,
.offline-warning
width: 100%
diff --git a/client/components/rules/actions/boardActions.jade b/client/components/rules/actions/boardActions.jade
index 6034184c..fda15062 100644
--- a/client/components/rules/actions/boardActions.jade
+++ b/client/components/rules/actions/boardActions.jade
@@ -1,29 +1,42 @@
template(name="boardActions")
div.trigger-item
div.trigger-content
- div.trigger-text
+ div.trigger-text
| {{_'r-move-card-to'}}
div.trigger-dropdown
select(id="move-gen-action")
option(value="top") {{_'r-top-of'}}
option(value="bottom") {{_'r-bottom-of'}}
- div.trigger-text
+ div.trigger-text
| {{_'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
+ div.trigger-text
| {{_'r-move-card-to'}}
div.trigger-dropdown
select(id="move-spec-action")
option(value="top") {{_'r-top-of'}}
option(value="bottom") {{_'r-bottom-of'}}
- div.trigger-text
- | {{_'r-list'}}
+ div.trigger-text
+ | {{_'r-the-board'}}
+ div.trigger-dropdown
+ select(id="board-id")
+ each boards
+ if $eq _id currentBoard._id
+ option(value="{{_id}}" selected) {{_ 'current'}}
+ else
+ option(value="{{_id}}") {{title}}
+ div.trigger-text
+ | {{_'r-in-list'}}
div.trigger-dropdown
input(id="listName",type=text,placeholder="{{_'r-name'}}")
+ div.trigger-text
+ | {{_'r-in-swimlane'}}
+ div.trigger-dropdown
+ input(id="swimlaneName",type=text,placeholder="{{_'r-name'}}")
div.trigger-button.js-add-spec-move-action.js-goto-rules
i.fa.fa-plus
@@ -33,14 +46,14 @@ template(name="boardActions")
select(id="arch-action")
option(value="archive") {{_'r-archive'}}
option(value="unarchive") {{_'r-unarchive'}}
- div.trigger-text
+ div.trigger-text
| {{_'r-card'}}
div.trigger-button.js-add-arch-action.js-goto-rules
i.fa.fa-plus
div.trigger-item
div.trigger-content
- div.trigger-text
+ div.trigger-text
| {{_'r-add-swimlane'}}
div.trigger-dropdown
input(id="swimlane-name",type=text,placeholder="{{_'r-name'}}")
@@ -49,15 +62,15 @@ template(name="boardActions")
div.trigger-item
div.trigger-content
- div.trigger-text
+ div.trigger-text
| {{_'r-create-card'}}
div.trigger-dropdown
input(id="card-name",type=text,placeholder="{{_'r-name'}}")
- div.trigger-text
+ div.trigger-text
| {{_'r-in-list'}}
div.trigger-dropdown
input(id="list-name",type=text,placeholder="{{_'r-name'}}")
- div.trigger-text
+ div.trigger-text
| {{_'r-in-swimlane'}}
div.trigger-dropdown
input(id="swimlane-name2",type=text,placeholder="{{_'r-name'}}")
@@ -65,8 +78,8 @@ template(name="boardActions")
i.fa.fa-plus
-
-
+
+
diff --git a/client/components/rules/actions/boardActions.js b/client/components/rules/actions/boardActions.js
index 8568d2bf..c2f2375a 100644
--- a/client/components/rules/actions/boardActions.js
+++ b/client/components/rules/actions/boardActions.js
@@ -1,6 +1,22 @@
BlazeComponent.extendComponent({
onCreated() {},
+ boards() {
+ const boards = Boards.find(
+ {
+ archived: false,
+ 'members.userId': Meteor.userId(),
+ _id: {
+ $ne: Meteor.user().getTemplatesBoardId(),
+ },
+ },
+ {
+ sort: ['title'],
+ },
+ );
+ return boards;
+ },
+
events() {
return [
{
@@ -52,15 +68,18 @@ BlazeComponent.extendComponent({
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#move-spec-action').value;
- const listTitle = this.find('#listName').value;
+ const swimlaneName = this.find('#swimlaneName').value;
+ const listName = this.find('#listName').value;
const boardId = Session.get('currentBoard');
+ const destBoardId = this.find('#board-id').value;
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'top') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToTop',
- listTitle,
- boardId,
+ listName,
+ swimlaneName,
+ boardId: destBoardId,
desc,
});
Rules.insert({
@@ -74,8 +93,9 @@ BlazeComponent.extendComponent({
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToBottom',
- listTitle,
- boardId,
+ listName,
+ swimlaneName,
+ boardId: destBoardId,
desc,
});
Rules.insert({
diff --git a/client/components/settings/informationBody.jade b/client/components/settings/informationBody.jade
index 2c615ffd..0f85dd9c 100644
--- a/client/components/settings/informationBody.jade
+++ b/client/components/settings/informationBody.jade
@@ -4,12 +4,16 @@ template(name='information')
| {{_ 'error-notAuthorized'}}
else
.content-title
- span {{_ 'info'}}
+ span
+ i.fa.fa-info-circle
+ | {{_ 'info'}}
.content-body
.side-menu
ul
li.active
- a.js-setting-menu(data-id="information-display") {{_ 'info'}}
+ a.js-setting-menu(data-id="information-display")
+ i.fa.fa-info-circle
+ | {{_ 'info'}}
.main-body
+statistics
diff --git a/client/components/settings/peopleBody.jade b/client/components/settings/peopleBody.jade
index ff343e37..b8a94337 100644
--- a/client/components/settings/peopleBody.jade
+++ b/client/components/settings/peopleBody.jade
@@ -5,16 +5,22 @@ template(name="people")
else
.content-title.ext-box
.ext-box-left
- span {{_ 'people'}}
+ span
+ i.fa.fa-users
+ | {{_ 'people'}}
input#searchInput(placeholder="{{_ 'search'}}")
- button#searchButton {{_ 'search'}}
+ button#searchButton
+ i.fa.fa-search
+ | {{_ 'search'}}
.ext-box-right
span {{_ 'people-number'}} #{peopleNumber}
.content-body
.side-menu
ul
li.active
- a.js-setting-menu(data-id="people-setting") {{_ 'people'}}
+ a.js-setting-menu(data-id="people-setting")
+ i.fa.fa-users
+ | {{_ 'people'}}
.main-body
if loading.get
+spinner
@@ -39,28 +45,58 @@ template(name="peopleGeneral")
template(name="peopleRow")
tr
- td.username {{ userData.username }}
- td {{ userData.profile.fullname }}
- td
- if userData.isAdmin
- | {{_ 'yes'}}
- else
- | {{_ 'no'}}
- td {{ userData.emails.[0].address }}
- td
- if userData.emails.[0].verified
- | {{_ 'yes'}}
- else
- | {{_ 'no'}}
- td {{ moment userData.createdAt 'LLL' }}
+ if userData.loginDisabled
+ td.username <s>{{ userData.username }}</s>
+ else
+ td.username {{ userData.username }}
+ if userData.loginDisabled
+ td <s>{{ userData.profile.fullname }}</s>
+ else
+ td {{ userData.profile.fullname }}
+ if userData.loginDisabled
+ td
+ if userData.isAdmin
+ | <s>{{_ 'yes'}}</s>
+ else
+ | <s>{{_ 'no'}}</s>
+ else
+ td
+ if userData.isAdmin
+ | {{_ 'yes'}}
+ else
+ | {{_ 'no'}}
+ if userData.loginDisabled
+ td <s>{{ userData.emails.[0].address }}</s>
+ else
+ td {{ userData.emails.[0].address }}
+ if userData.loginDisabled
+ td
+ if userData.emails.[0].verified
+ | <s>{{_ 'yes'}}</s>
+ else
+ | <s>{{_ 'no'}}</s>
+ else
+ td
+ if userData.emails.[0].verified
+ | {{_ 'yes'}}
+ else
+ | {{_ 'no'}}
+ if userData.loginDisabled
+ td <s>{{ moment userData.createdAt 'LLL' }}</s>
+ else
+ td {{ moment userData.createdAt 'LLL' }}
td
if userData.loginDisabled
| {{_ 'no'}}
else
| {{_ 'yes'}}
- td {{_ userData.authenticationMethod }}
+ if userData.loginDisabled
+ td <s>{{_ userData.authenticationMethod }}</s>
+ else
+ td {{_ userData.authenticationMethod }}
td
a.edit-user
+ i.fa.fa-edit
| {{_ 'edit'}}
template(name="editUserPopup")
diff --git a/client/components/settings/peopleBody.styl b/client/components/settings/peopleBody.styl
index 80387611..c223e181 100644
--- a/client/components/settings/peopleBody.styl
+++ b/client/components/settings/peopleBody.styl
@@ -33,7 +33,7 @@ table
padding: 0;
button
- min-width: 60px;
+ min-width: 90px;
.content-wrapper
margin-top: 10px
diff --git a/client/components/settings/settingBody.jade b/client/components/settings/settingBody.jade
index 04b635e8..835a3b81 100644
--- a/client/components/settings/settingBody.jade
+++ b/client/components/settings/settingBody.jade
@@ -4,22 +4,35 @@ template(name="setting")
| {{_ 'error-notAuthorized'}}
else
.content-title
+ i.fa.fa-cog
span {{_ 'settings'}}
.content-body
.side-menu
ul
li.active
- a.js-setting-menu(data-id="registration-setting") {{_ 'registration'}}
+ a.js-setting-menu(data-id="registration-setting")
+ i.fa.fa-sign-in
+ | {{_ 'registration'}}
li
- a.js-setting-menu(data-id="email-setting") {{_ 'email'}}
+ a.js-setting-menu(data-id="email-setting")
+ i.fa.fa-envelope
+ | {{_ 'email'}}
li
- a.js-setting-menu(data-id="account-setting") {{_ 'accounts'}}
+ a.js-setting-menu(data-id="account-setting")
+ i.fa.fa-users
+ | {{_ 'accounts'}}
li
- a.js-setting-menu(data-id="announcement-setting") {{_ 'admin-announcement'}}
+ a.js-setting-menu(data-id="announcement-setting")
+ i.fa.fa-bullhorn
+ | {{_ 'admin-announcement'}}
li
- a.js-setting-menu(data-id="layout-setting") {{_ 'layout'}}
+ a.js-setting-menu(data-id="layout-setting")
+ i.fa.fa-object-group
+ | {{_ 'layout'}}
li
- a.js-setting-menu(data-id="webhook-setting") {{_ 'global-webhook'}}
+ a.js-setting-menu(data-id="webhook-setting")
+ i.fa.fa-globe
+ | {{_ 'global-webhook'}}
.main-body
if loading.get
+spinner
@@ -171,12 +184,6 @@ template(name='layoutSettings')
.title {{_ 'custom-product-name'}}
.form-group
input.wekan-form-control#product-name(type="text", placeholder="" value="{{currentSetting.productName}}")
- li.layout-form
- .title {{_ 'add-custom-html-after-body-start'}}
- textarea#customHTMLafterBodyStart.wekan-form-control= currentSetting.customHTMLafterBodyStart
- li.layout-form
- .title {{_ 'add-custom-html-before-body-end'}}
- textarea#customHTMLbeforeBodyEnd.wekan-form-control= currentSetting.customHTMLbeforeBodyEnd
li
button.js-save-layout.primary {{_ 'save'}}
diff --git a/client/components/settings/settingBody.js b/client/components/settings/settingBody.js
index 4ff5aedd..319c066b 100644
--- a/client/components/settings/settingBody.js
+++ b/client/components/settings/settingBody.js
@@ -171,20 +171,12 @@ BlazeComponent.extendComponent({
const displayAuthenticationMethod =
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
- const customHTMLafterBodyStart = $('#customHTMLafterBodyStart')
- .val()
- .trim();
- const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd')
- .val()
- .trim();
try {
Settings.update(Settings.findOne()._id, {
$set: {
productName,
hideLogo: hideLogoChange,
- customHTMLafterBodyStart,
- customHTMLbeforeBodyEnd,
displayAuthenticationMethod,
defaultAuthenticationMethod,
},
diff --git a/client/components/settings/settingBody.styl b/client/components/settings/settingBody.styl
index bcbd2ea1..d6ac32b2 100644
--- a/client/components/settings/settingBody.styl
+++ b/client/components/settings/settingBody.styl
@@ -41,15 +41,18 @@
&:hover
background #fff
box-shadow 0 1px 2px rgba(0,0,0,0.15);
+
a
@extends .flex
padding: 1rem 0 1rem 1rem
width: 100% - 5rem
-
span
font-size: 13px
+ i
+ margin-right: 20px
+
.main-body
padding: 0.1em 1em
-webkit-user-select: text // Safari 3.1+
diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade
index ccfadc0c..ebcd8486 100644
--- a/client/components/sidebar/sidebar.jade
+++ b/client/components/sidebar/sidebar.jade
@@ -37,11 +37,12 @@ template(name='homeSidebar')
template(name="membersWidget")
.board-widget.board-widget-members
h3
- i.fa.fa-user
+ i.fa.fa-users
| {{_ 'members'}}
unless currentUser.isCommentOnly
- a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
- i.board-header-btn-icon.fa.fa-cog
+ unless currentUser.isWorker
+ a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
+ i.board-header-btn-icon.fa.fa-cog
.board-widget-content
each currentBoard.activeMembers
@@ -71,6 +72,108 @@ template(name="boardChangeColorPopup")
if isSelected
i.fa.fa-check
+template(name="boardCardSettingsPopup")
+ form.board-card-settings
+ h3 {{_ 'show-on-card'}}
+ div.check-div
+ a.flex.js-field-has-receiveddate(class="{{#if allowsReceivedDate}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsReceivedDate}}is-checked{{/if}}")
+ span
+ i.fa.fa-sign-out
+ | {{_ 'card-received'}}
+ div.check-div
+ a.flex.js-field-has-startdate(class="{{#if allowsStartDate}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsStartDate}}is-checked{{/if}}")
+ span
+ i.fa.fa-hourglass-start
+ | {{_ 'card-start'}}
+ div.check-div
+ a.flex.js-field-has-duedate(class="{{#if allowsDueDate}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsDueDate}}is-checked{{/if}}")
+ span
+ i.fa.fa-sign-in
+ | {{_ 'card-due'}}
+ div.check-div
+ a.flex.js-field-has-enddate(class="{{#if allowsEndDate}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsEndDate}}is-checked{{/if}}")
+ span
+ i.fa.fa-hourglass-end
+ | {{_ 'card-end'}}
+ div.check-div
+ a.flex.js-field-has-members(class="{{#if allowsMembers}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsMembers}}is-checked{{/if}}")
+ span
+ i.fa.fa-users
+ | {{_ 'members'}}
+ div.check-div
+ a.flex.js-field-has-assignee(class="{{#if allowsAssignee}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsAssignee}}is-checked{{/if}}")
+ span
+ i.fa.fa-user
+ | {{_ 'assignee'}}
+ div.check-div
+ a.flex.js-field-has-assigned-by(class="{{#if allowsAssignedBy}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsAssignedBy}}is-checked{{/if}}")
+ span
+ i.fa.fa-shopping-cart
+ | {{_ 'assigned-by'}}
+ div.check-div
+ a.flex.js-field-has-requested-by(class="{{#if allowsRequestedBy}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsRequestedBy}}is-checked{{/if}}")
+ span
+ i.fa.fa-user-plus
+ | {{_ 'requested-by'}}
+ div.check-div
+ a.flex.js-field-has-labels(class="{{#if allowsLabels}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsLabels}}is-checked{{/if}}")
+ span
+ i.fa.fa-tags
+ | {{_ 'labels'}}
+ div.check-div
+ a.flex.js-field-has-description-title(class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsDescriptionTitle}}is-checked{{/if}}")
+ span
+ i.fa.fa-align-left
+ | {{_ 'description'}}
+ | {{_ 'title'}}
+ div.check-div
+ a.flex.js-field-has-description-text(class="{{#if allowsDescriptionText}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsDescriptionText}}is-checked{{/if}}")
+ span
+ i.fa.fa-align-left
+ | {{_ 'description'}}
+ | {{_ 'custom-field-text'}}
+ div.check-div
+ a.flex.js-field-has-checklists(class="{{#if allowsChecklists}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsChecklists}}is-checked{{/if}}")
+ span
+ i.fa.fa-check
+ | {{_ 'checklists'}}
+ div.check-div
+ a.flex.js-field-has-subtasks(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsSubtasks}}is-checked{{/if}}")
+ span
+ i.fa.fa-sitemap
+ | {{_ 'subtasks'}}
+ div.check-div
+ a.flex.js-field-has-attachments(class="{{#if allowsAttachments}}is-checked{{/if}}")
+ .materialCheckBox(class="{{#if allowsAttachments}}is-checked{{/if}}")
+ span
+ i.fa.fa-paperclip
+ | {{_ 'attachments'}}
+ //div.check-div
+ // a.flex.js-field-has-comments(class="{{#if allowsComments}}is-checked{{/if}}")
+ // .materialCheckBox(class="{{#if allowsComments}}is-checked{{/if}}")
+ // span
+ // i.fa.fa-comment-o
+ // | {{_ 'comment'}}
+ //div.check-div
+ // a.flex.js-field-has-activities(class="{{#if allowsActivities}}is-checked{{/if}}")
+ // .materialCheckBox(class="{{#if allowsActivities}}is-checked{{/if}}")
+ // span
+ // i.fa.fa-history
+ // | {{_ 'activities'}}
+
template(name="boardSubtaskSettingsPopup")
form.board-subtask-settings
h3 {{_ 'show-parent-in-minicard'}}
@@ -130,7 +233,9 @@ template(name="chooseBoardSource")
template(name="archiveBoardPopup")
p {{_ 'close-board-pop'}}
- button.js-confirm.negate.full(type="submit") {{_ 'archive'}}
+ button.js-confirm.negate.full(type="submit")
+ i.fa.fa-archive
+ | {{_ 'archive'}}
template(name="outgoingWebhooksPopup")
each integrations
@@ -163,37 +268,88 @@ template(name="outgoingWebhooksPopup")
template(name="boardMenuPopup")
ul.pop-over-list
li: a.js-custom-fields {{_ 'custom-fields'}}
- li: a.js-open-archives {{_ 'archived-items'}}
+ li
+ a.js-open-archives
+ i.fa.fa-archive
+ | {{_ 'archived-items'}}
if currentUser.isBoardAdmin
- li: a.js-change-board-color {{_ 'board-change-color'}}
+ li
+ a.js-change-board-color
+ i.fa.fa-paint-brush
+ | {{_ 'board-change-color'}}
+
//-
XXX Language should be handled by sandstorm, but for now display a
language selection link in the board menu. This link is normally present
in the header bar that is not displayed on sandstorm.
if isSandstorm
- li: a.js-change-language {{_ 'language'}}
+ li
+ a.js-change-language
+ i.fa.fa-flag
+ | {{_ 'language'}}
unless isSandstorm
if currentUser.isBoardAdmin
hr
ul.pop-over-list
- li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
- unless currentBoard.isTemplatesBoard
- li: a.js-archive-board {{_ 'archive-board'}}
- li: a.js-outgoing-webhooks {{_ 'outgoing-webhooks'}}
- hr
- ul.pop-over-list
- li: a.js-subtask-settings {{_ 'subtask-settings'}}
+ li
+ a(href="{{exportUrl}}", download="{{exportFilename}}")
+ i.fa.fa-share-alt
+ | {{_ 'export-board'}}
+ li
+ a.js-outgoing-webhooks
+ i.fa.fa-globe
+ | {{_ 'outgoing-webhooks'}}
+ li
+ a.js-card-settings
+ i.fa.fa-id-card-o
+ | {{_ 'card-settings'}}
+ li
+ a.js-subtask-settings
+ i.fa.fa-sitemap
+ | {{_ 'subtask-settings'}}
+ unless currentBoard.isTemplatesBoard
+ hr
+ ul.pop-over-list
+ li
+ a.js-archive-board
+ i.fa.fa-arrow-right
+ i.fa.fa-archive
+ | {{_ 'archive-board'}}
if isSandstorm
hr
ul.pop-over-list
- li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
- li: a.js-import-board {{_ 'import-board-c'}}
- li: a.js-archive-board {{_ 'archive-board'}}
- li: a.js-outgoing-webhooks {{_ 'outgoing-webhooks'}}
+ li
+ a(href="{{exportUrl}}", download="{{exportFilename}}")
+ i.fa.fa-share-alt
+ i.fa.fa-sign-out
+ | {{_ 'export-board'}}
+ li
+ a.js-import-board
+ i.fa.fa-share-alt
+ i.fa.fa-sign-in
+ | {{_ 'import-board-c'}}
+ li
+ a.js-archive-board
+ i.fa.fa-arrow-right
+ i.fa.fa-archive
+ | {{_ 'archive-board'}}
+ li
+ a.js-outgoing-webhooks
+ i.fa.fa-globe
+ | {{_ 'outgoing-webhooks'}}
+ hr
+ ul.pop-over-list
+ li
+ a.js-card-settings
+ i.fa.fa-id-card-o
+ | {{_ 'card-settings'}}
hr
ul.pop-over-list
- li: a.js-subtask-settings {{_ 'subtask-settings'}}
+ li
+ a.js-subtask-settings
+ i.fa.fa-sitemap
+ | {{_ 'subtask-settings'}}
template(name="labelsWidget")
.board-widget.board-widget-labels
@@ -203,7 +359,7 @@ template(name="labelsWidget")
.board-widget-content
each currentBoard.labels
a.card-label(class="card-label-{{color}}"
- class="{{#if currentUser.isNotCommentOnly}}js-label{{/if}}")
+ class="{{#if currentUser.isNotCommentOnly}}{{#if currentUser.isNotWorker}}js-label{{/if}}{{/if}}")
span.card-label-name
+viewer
= name
@@ -232,12 +388,12 @@ template(name="memberPopup")
a.js-change-role
| {{_ 'change-permissions'}}
span.quiet (#{memberType})
- li
- if $eq currentUser._id userId
- a.js-leave-member {{_ 'leave-board'}}
- else if currentUser.isBoardAdmin
- a.js-remove-member {{_ 'remove-from-board'}}
-
+ unless currentUser.isWorker
+ li
+ if $eq currentUser._id userId
+ a.js-leave-member {{_ 'leave-board'}}
+ else if currentUser.isBoardAdmin
+ a.js-remove-member {{_ 'remove-from-board'}}
template(name="removeMemberPopup")
p {{_ 'remove-member-pop' name=user.profile.fullname username=user.username boardTitle=board.title}}
@@ -301,6 +457,12 @@ template(name="changePermissionsPopup")
if isCommentOnly
i.fa.fa-check
span.sub-name {{_ 'comment-only-desc'}}
+ li
+ a(class="{{#if isLastAdmin}}disabled{{else}}js-set-worker{{/if}}")
+ | {{_ 'worker'}}
+ if isWorker
+ i.fa.fa-check
+ span.sub-name {{_ 'worker-desc'}}
if isLastAdmin
hr
p.quiet.bottom {{_ 'last-admin-desc'}}
diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js
index f1ccfb1e..8e640564 100644
--- a/client/components/sidebar/sidebar.js
+++ b/client/components/sidebar/sidebar.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
Sidebar = null;
const defaultView = 'home';
@@ -107,7 +109,14 @@ BlazeComponent.extendComponent({
'click .js-toggle-sidebar': this.toggle,
'click .js-back-home': this.setView,
'click .js-toggle-minicard-label-text'() {
- Meteor.call('toggleMinicardLabelText');
+ currentUser = Meteor.user();
+ if (currentUser) {
+ Meteor.call('toggleMinicardLabelText');
+ } else if (cookies.has('hiddenMinicardLabelText')) {
+ cookies.remove('hiddenMinicardLabelText');
+ } else {
+ cookies.set('hiddenMinicardLabelText', 'true');
+ }
},
'click .js-shortcuts'() {
FlowRouter.go('shortcuts');
@@ -121,7 +130,14 @@ Blaze.registerHelper('Sidebar', () => Sidebar);
Template.homeSidebar.helpers({
hiddenMinicardLabelText() {
- return Meteor.user().hasHiddenMinicardLabelText();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).hiddenMinicardLabelText;
+ } else if (cookies.has('hiddenMinicardLabelText')) {
+ return true;
+ } else {
+ return false;
+ }
},
});
@@ -145,10 +161,13 @@ Template.memberPopup.helpers({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const commentOnly = currentBoard.hasCommentOnly(this.userId);
const noComments = currentBoard.hasNoComments(this.userId);
+ const worker = currentBoard.hasWorker(this.userId);
if (commentOnly) {
return TAPi18n.__('comment-only').toLowerCase();
} else if (noComments) {
return TAPi18n.__('no-comments').toLowerCase();
+ } else if (worker) {
+ return TAPi18n.__('worker').toLowerCase();
} else {
return TAPi18n.__(type).toLowerCase();
}
@@ -189,6 +208,7 @@ Template.boardMenuPopup.events({
'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
+ 'click .js-card-settings': Popup.open('boardCardSettings'),
});
Template.boardMenuPopup.helpers({
@@ -251,6 +271,14 @@ Template.membersWidget.helpers({
const user = Meteor.user();
return user && user.isInvitedTo(Session.get('currentBoard'));
},
+ isWorker() {
+ const user = Meteor.user();
+ if (user) {
+ return Meteor.call(Boards.hasWorker(user.memberId));
+ } else {
+ return false;
+ }
+ },
});
Template.membersWidget.events({
@@ -445,6 +473,10 @@ BlazeComponent.extendComponent({
return this.currentBoard.allowsSubtasks;
},
+ allowsReceivedDate() {
+ return this.currentBoard.allowsReceivedDate;
+ },
+
isBoardSelected() {
return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
},
@@ -560,6 +592,359 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {
+ this.currentBoard = Boards.findOne(Session.get('currentBoard'));
+ },
+
+ allowsReceivedDate() {
+ return this.currentBoard.allowsReceivedDate;
+ },
+
+ allowsStartDate() {
+ return this.currentBoard.allowsStartDate;
+ },
+
+ allowsDueDate() {
+ return this.currentBoard.allowsDueDate;
+ },
+
+ allowsEndDate() {
+ return this.currentBoard.allowsEndDate;
+ },
+
+ allowsSubtasks() {
+ return this.currentBoard.allowsSubtasks;
+ },
+
+ allowsMembers() {
+ return this.currentBoard.allowsMembers;
+ },
+
+ allowsAssignee() {
+ return this.currentBoard.allowsAssignee;
+ },
+
+ allowsAssignedBy() {
+ return this.currentBoard.allowsAssignedBy;
+ },
+
+ allowsRequestedBy() {
+ return this.currentBoard.allowsRequestedBy;
+ },
+
+ allowsLabels() {
+ return this.currentBoard.allowsLabels;
+ },
+
+ allowsChecklists() {
+ return this.currentBoard.allowsChecklists;
+ },
+
+ allowsAttachments() {
+ return this.currentBoard.allowsAttachments;
+ },
+
+ allowsComments() {
+ return this.currentBoard.allowsComments;
+ },
+
+ allowsDescriptionTitle() {
+ return this.currentBoard.allowsDescriptionTitle;
+ },
+
+ allowsDescriptionText() {
+ return this.currentBoard.allowsDescriptionText;
+ },
+
+ isBoardSelected() {
+ return this.currentBoard.dateSettingsDefaultBoardID;
+ },
+
+ isNullBoardSelected() {
+ return (
+ this.currentBoard.dateSettingsDefaultBoardId === null ||
+ this.currentBoard.dateSettingsDefaultBoardId === undefined
+ );
+ },
+
+ boards() {
+ return Boards.find(
+ {
+ archived: false,
+ 'members.userId': Meteor.userId(),
+ },
+ {
+ sort: ['title'],
+ },
+ );
+ },
+
+ lists() {
+ return Lists.find(
+ {
+ boardId: this.currentBoard._id,
+ archived: false,
+ },
+ {
+ sort: ['title'],
+ },
+ );
+ },
+
+ hasLists() {
+ return this.lists().count() > 0;
+ },
+
+ isListSelected() {
+ return (
+ this.currentBoard.dateSettingsDefaultBoardId === this.currentData()._id
+ );
+ },
+
+ events() {
+ return [
+ {
+ 'click .js-field-has-receiveddate'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsReceivedDate = !this.currentBoard
+ .allowsReceivedDate;
+ this.currentBoard.setAllowsReceivedDate(
+ this.currentBoard.allowsReceivedDate,
+ );
+ $(`.js-field-has-receiveddate ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsReceivedDate,
+ );
+ $('.js-field-has-receiveddate').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsReceivedDate,
+ );
+ },
+ 'click .js-field-has-startdate'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsStartDate = !this.currentBoard
+ .allowsStartDate;
+ this.currentBoard.setAllowsStartDate(
+ this.currentBoard.allowsStartDate,
+ );
+ $(`.js-field-has-startdate ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsStartDate,
+ );
+ $('.js-field-has-startdate').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsStartDate,
+ );
+ },
+ 'click .js-field-has-enddate'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsEndDate = !this.currentBoard.allowsEndDate;
+ this.currentBoard.setAllowsEndDate(this.currentBoard.allowsEndDate);
+ $(`.js-field-has-enddate ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsEndDate,
+ );
+ $('.js-field-has-enddate').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsEndDate,
+ );
+ },
+ 'click .js-field-has-duedate'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsDueDate = !this.currentBoard.allowsDueDate;
+ this.currentBoard.setAllowsDueDate(this.currentBoard.allowsDueDate);
+ $(`.js-field-has-duedate ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDueDate,
+ );
+ $('.js-field-has-duedate').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDueDate,
+ );
+ },
+ 'click .js-field-has-subtasks'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
+ this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
+ $(`.js-field-has-subtasks ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsSubtasks,
+ );
+ $('.js-field-has-subtasks').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsSubtasks,
+ );
+ },
+ 'click .js-field-has-members'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsMembers = !this.currentBoard.allowsMembers;
+ this.currentBoard.setAllowsMembers(this.currentBoard.allowsMembers);
+ $(`.js-field-has-members ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsMembers,
+ );
+ $('.js-field-has-members').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsMembers,
+ );
+ },
+ 'click .js-field-has-assignee'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsAssignee = !this.currentBoard.allowsAssignee;
+ this.currentBoard.setAllowsAssignee(this.currentBoard.allowsAssignee);
+ $(`.js-field-has-assignee ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAssignee,
+ );
+ $('.js-field-has-assignee').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAssignee,
+ );
+ },
+ 'click .js-field-has-assigned-by'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsAssignedBy = !this.currentBoard
+ .allowsAssignedBy;
+ this.currentBoard.setAllowsAssignedBy(
+ this.currentBoard.allowsAssignedBy,
+ );
+ $(`.js-field-has-assigned-by ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAssignedBy,
+ );
+ $('.js-field-has-assigned-by').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAssignedBy,
+ );
+ },
+ 'click .js-field-has-requested-by'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsRequestedBy = !this.currentBoard
+ .allowsRequestedBy;
+ this.currentBoard.setAllowsRequestedBy(
+ this.currentBoard.allowsRequestedBy,
+ );
+ $(`.js-field-has-requested-by ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsRequestedBy,
+ );
+ $('.js-field-has-requested-by').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsRequestedBy,
+ );
+ },
+ 'click .js-field-has-labels'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsLabels = !this.currentBoard.allowsLabels;
+ this.currentBoard.setAllowsLabels(this.currentBoard.allowsLabels);
+ $(`.js-field-has-labels ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAssignee,
+ );
+ $('.js-field-has-labels').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsLabels,
+ );
+ },
+ 'click .js-field-has-description-title'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsDescriptionTitle = !this.currentBoard
+ .allowsDescriptionTitle;
+ this.currentBoard.setAllowsDescriptionTitle(
+ this.currentBoard.allowsDescriptionTitle,
+ );
+ $(`.js-field-has-description-title ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDescriptionTitle,
+ );
+ $('.js-field-has-description-title').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDescriptionTitle,
+ );
+ },
+ 'click .js-field-has-description-text'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsDescriptionText = !this.currentBoard
+ .allowsDescriptionText;
+ this.currentBoard.setAllowsDescriptionText(
+ this.currentBoard.allowsDescriptionText,
+ );
+ $(`.js-field-has-description-text ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDescriptionText,
+ );
+ $('.js-field-has-description-text').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsDescriptionText,
+ );
+ },
+ 'click .js-field-has-checklists'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsChecklists = !this.currentBoard
+ .allowsChecklists;
+ this.currentBoard.setAllowsChecklists(
+ this.currentBoard.allowsChecklists,
+ );
+ $(`.js-field-has-checklists ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsChecklists,
+ );
+ $('.js-field-has-checklists').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsChecklists,
+ );
+ },
+ 'click .js-field-has-attachments'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsAttachments = !this.currentBoard
+ .allowsAttachments;
+ this.currentBoard.setAllowsAttachments(
+ this.currentBoard.allowsAttachments,
+ );
+ $(`.js-field-has-attachments ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAttachments,
+ );
+ $('.js-field-has-attachments').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsAttachments,
+ );
+ },
+ 'click .js-field-has-comments'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsComments = !this.currentBoard.allowsComments;
+ this.currentBoard.setAllowsComments(this.currentBoard.allowsComments);
+ $(`.js-field-has-comments ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsComments,
+ );
+ $('.js-field-has-comments').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsComments,
+ );
+ },
+ 'click .js-field-has-activities'(evt) {
+ evt.preventDefault();
+ this.currentBoard.allowsActivities = !this.currentBoard
+ .allowsActivities;
+ this.currentBoard.setAllowsActivities(
+ this.currentBoard.allowsActivities,
+ );
+ $(`.js-field-has-activities ${MCB}`).toggleClass(
+ CKCLS,
+ this.currentBoard.allowsActivities,
+ );
+ $('.js-field-has-activities').toggleClass(
+ CKCLS,
+ this.currentBoard.allowsActivities,
+ );
+ },
+ },
+ ];
+ },
+}).register('boardCardSettingsPopup');
+
+BlazeComponent.extendComponent({
+ onCreated() {
this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false);
},
@@ -628,7 +1013,7 @@ BlazeComponent.extendComponent({
}).register('addMemberPopup');
Template.changePermissionsPopup.events({
- 'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(
+ 'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
event,
) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
@@ -638,11 +1023,13 @@ Template.changePermissionsPopup.events({
'js-set-comment-only',
);
const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
+ const isWorker = $(event.currentTarget).hasClass('js-set-worker');
currentBoard.setMemberPermission(
memberId,
isAdmin,
isNoComments,
isCommentOnly,
+ isWorker,
);
Popup.back(1);
},
@@ -659,7 +1046,8 @@ Template.changePermissionsPopup.helpers({
return (
!currentBoard.hasAdmin(this.userId) &&
!currentBoard.hasNoComments(this.userId) &&
- !currentBoard.hasCommentOnly(this.userId)
+ !currentBoard.hasCommentOnly(this.userId) &&
+ !currentBoard.hasWorker(this.userId)
);
},
@@ -679,6 +1067,13 @@ Template.changePermissionsPopup.helpers({
);
},
+ isWorker() {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ return (
+ !currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
+ );
+ },
+
isLastAdmin() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return (
diff --git a/client/components/sidebar/sidebar.styl b/client/components/sidebar/sidebar.styl
index 740186b5..c1047277 100644
--- a/client/components/sidebar/sidebar.styl
+++ b/client/components/sidebar/sidebar.styl
@@ -109,7 +109,7 @@
color: darken(white, 40%)
.board-sidebar
- width: 248px
+ width: 548px
right: -@width
transition: top .1s, right .1s, width .1s
diff --git a/client/components/sidebar/sidebarArchives.jade b/client/components/sidebar/sidebarArchives.jade
index 466d2cb0..56423ad7 100644
--- a/client/components/sidebar/sidebarArchives.jade
+++ b/client/components/sidebar/sidebarArchives.jade
@@ -2,54 +2,60 @@ template(name="archivesSidebar")
if isArchiveReady.get
+basicTabs(tabs=tabs)
+tabContent(slug="cards")
- p.quiet
- a.js-restore-all-cards {{_ 'restore-all'}}
- | -
- a.js-delete-all-cards {{_ 'delete-all'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-all-cards {{_ 'restore-all'}}
+ | -
+ a.js-delete-all-cards {{_ 'delete-all'}}
each archivedCards
.minicard-wrapper.js-minicard
+minicard(this)
if currentUser.isBoardMember
- p.quiet
- a.js-restore-card {{_ 'restore'}}
- | -
- a.js-delete-card {{_ 'delete'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-card {{_ 'restore'}}
+ | -
+ a.js-delete-card {{_ 'delete'}}
if cardIsInArchivedList
p.quiet.small ({{_ 'warn-list-archived'}})
else
p.no-items-message {{_ 'no-archived-cards'}}
+tabContent(slug="lists")
- p.quiet
- a.js-restore-all-lists {{_ 'restore-all'}}
- | -
- a.js-delete-all-lists {{_ 'delete-all'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-all-lists {{_ 'restore-all'}}
+ | -
+ a.js-delete-all-lists {{_ 'delete-all'}}
ul.archived-lists
each archivedLists
li.archived-lists-item
= title
if currentUser.isBoardMember
- p.quiet
- a.js-restore-list {{_ 'restore'}}
- | -
- a.js-delete-list {{_ 'delete'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-list {{_ 'restore'}}
+ | -
+ a.js-delete-list {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-lists'}}
+tabContent(slug="swimlanes")
- p.quiet
- a.js-restore-all-swimlanes {{_ 'restore-all'}}
- | -
- a.js-delete-all-swimlanes {{_ 'delete-all'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-all-swimlanes {{_ 'restore-all'}}
+ | -
+ a.js-delete-all-swimlanes {{_ 'delete-all'}}
ul.archived-lists
each archivedSwimlanes
li.archived-lists-item
= title
if currentUser.isBoardMember
- p.quiet
- a.js-restore-swimlane {{_ 'restore'}}
- | -
- a.js-delete-swimlane {{_ 'delete'}}
+ unless isWorker
+ p.quiet
+ a.js-restore-swimlane {{_ 'restore'}}
+ | -
+ a.js-delete-swimlane {{_ 'delete'}}
else
li.no-items-message {{_ 'no-archived-swimlanes'}}
else
diff --git a/client/components/sidebar/sidebarArchives.js b/client/components/sidebar/sidebarArchives.js
index a4846561..75b694e9 100644
--- a/client/components/sidebar/sidebarArchives.js
+++ b/client/components/sidebar/sidebarArchives.js
@@ -139,3 +139,12 @@ BlazeComponent.extendComponent({
];
},
}).register('archivesSidebar');
+
+Template.archivesSidebar.helpers({
+ isWorker() {
+ const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ return (
+ !currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
+ );
+ },
+});
diff --git a/client/components/sidebar/sidebarFilters.jade b/client/components/sidebar/sidebarFilters.jade
index 5f929cb9..7f31dada 100644
--- a/client/components/sidebar/sidebarFilters.jade
+++ b/client/components/sidebar/sidebarFilters.jade
@@ -117,13 +117,14 @@ template(name="multiselectionSidebar")
i.fa.fa-check
else if someSelectedElementHave 'member' _id
i.fa.fa-ellipsis-h
- hr
- a.sidebar-btn.js-move-selection
- i.fa.fa-share
- span {{_ 'move-selection'}}
- a.sidebar-btn.js-archive-selection
- i.fa.fa-archive
- span {{_ 'archive-selection'}}
+ unless currentUser.isWorker
+ hr
+ a.sidebar-btn.js-move-selection
+ i.fa.fa-share
+ span {{_ 'move-selection'}}
+ a.sidebar-btn.js-archive-selection
+ i.fa.fa-archive
+ span {{_ 'archive-selection'}}
template(name="disambiguateMultiLabelPopup")
p {{_ 'what-to-do'}}
diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js
index 6f8029fd..3032966d 100644
--- a/client/components/swimlanes/swimlaneHeader.js
+++ b/client/components/swimlanes/swimlaneHeader.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
const { calculateIndexData } = Utils;
let swimlaneColors;
@@ -30,7 +32,14 @@ BlazeComponent.extendComponent({
Template.swimlaneHeader.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
});
diff --git a/client/components/swimlanes/swimlanes.jade b/client/components/swimlanes/swimlanes.jade
index 9eab6054..9b00d9e8 100644
--- a/client/components/swimlanes/swimlanes.jade
+++ b/client/components/swimlanes/swimlanes.jade
@@ -1,24 +1,25 @@
template(name="swimlane")
.swimlane
+swimlaneHeader
- .swimlane.js-lists.js-swimlane
- if isMiniScreen
- if currentListIsInThisSwimlane _id
- +list(currentList)
- unless currentList
+ unless collapseSwimlane
+ .swimlane.js-lists.js-swimlane
+ if isMiniScreen
+ if currentListIsInThisSwimlane _id
+ +list(currentList)
+ unless currentList
+ each lists
+ +miniList(this)
+ if currentUser.isBoardMember
+ unless currentUser.isCommentOnly
+ +addListForm
+ else
each lists
- +miniList(this)
+ +list(this)
+ if currentCardIsInThisList _id ../_id
+ +cardDetails(currentCard)
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
- else
- each lists
- +list(this)
- if currentCardIsInThisList _id ../_id
- +cardDetails(currentCard)
- if currentUser.isBoardMember
- unless currentUser.isCommentOnly
- +addListForm
template(name="listsGroup")
.swimlane.list-group.js-lists
@@ -42,19 +43,20 @@ template(name="listsGroup")
+addListForm
template(name="addListForm")
- .list.list-composer.js-list-composer(class="{{#if isMiniScreen}}mini-list{{/if}}")
- .list-header-add
- +inlinedForm(autoclose=false)
- input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
- autocomplete="off" autofocus)
- .edit-controls.clearfix
- button.primary.confirm(type="submit") {{_ 'save'}}
- unless currentBoard.isTemplatesBoard
- unless currentBoard.isTemplateBoard
- span.quiet
- | {{_ 'or'}}
- a.js-list-template {{_ 'template'}}
- else
- a.open-list-composer.js-open-inlined-form
- i.fa.fa-plus
- | {{_ 'add-list'}}
+ unless currentUser.isWorker
+ .list.list-composer.js-list-composer(class="{{#if isMiniScreen}}mini-list{{/if}}")
+ .list-header-add
+ +inlinedForm(autoclose=false)
+ input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
+ autocomplete="off" autofocus)
+ .edit-controls.clearfix
+ button.primary.confirm(type="submit") {{_ 'save'}}
+ unless currentBoard.isTemplatesBoard
+ unless currentBoard.isTemplateBoard
+ span.quiet
+ | {{_ 'or'}}
+ a.js-list-template {{_ 'template'}}
+ else
+ a.open-list-composer.js-open-inlined-form
+ i.fa.fa-plus
+ | {{_ 'add-list'}}
diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js
index 8faad870..b7a55ce6 100644
--- a/client/components/swimlanes/swimlanes.js
+++ b/client/components/swimlanes/swimlanes.js
@@ -1,3 +1,5 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
const { calculateIndex, enableClickOnTouch } = Utils;
function currentListIsInThisSwimlane(swimlaneId) {
@@ -14,7 +16,7 @@ function currentCardIsInThisList(listId, swimlaneId) {
if (
currentUser &&
currentUser.profile &&
- currentUser.profile.boardView === 'board-view-swimlanes'
+ Utils.boardView() === 'board-view-swimlanes'
)
return (
currentCard &&
@@ -53,18 +55,6 @@ function initSortable(boardComponent, $listsDom) {
},
};
- if (Utils.isMiniScreen) {
- $listsDom.sortable({
- handle: '.js-list-handle',
- });
- }
-
- if (!Utils.isMiniScreen && showDesktopDragHandles) {
- $listsDom.sortable({
- handle: '.js-list-header',
- });
- }
-
$listsDom.sortable({
tolerance: 'pointer',
helper: 'clone',
@@ -104,19 +94,64 @@ function initSortable(boardComponent, $listsDom) {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
}
- // Disable drag-dropping while in multi-selection mode, or if the current user
- // is not a board member
boardComponent.autorun(() => {
+ let showDesktopDragHandles = false;
+ currentUser = Meteor.user();
+ if (currentUser) {
+ showDesktopDragHandles = (currentUser.profile || {})
+ .showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ showDesktopDragHandles = true;
+ } else {
+ showDesktopDragHandles = false;
+ }
+
+ if (!Utils.isMiniScreen() && showDesktopDragHandles) {
+ $listsDom.sortable({
+ handle: '.js-list-handle',
+ });
+ } else if (!Utils.isMiniScreen() && !showDesktopDragHandles) {
+ $listsDom.sortable({
+ handle: '.js-list-header',
+ });
+ }
+
const $listDom = $listsDom;
if ($listDom.data('sortable')) {
$listsDom.sortable(
'option',
'disabled',
- MultiSelection.isActive() || !userIsMember(),
+ // Disable drag-dropping when user is not member/is worker/is miniscreen
+ !userIsMember(),
+ // Not disable drag-dropping while in multi-selection mode
+ // MultiSelection.isActive() || !userIsMember(),
+ );
+ }
+
+ if ($listDom.data('sortable')) {
+ $listsDom.sortable(
+ 'option',
+ 'disabled',
+ // Disable drag-dropping when user is not member/is worker/is miniscreen
+ Meteor.user().isWorker(),
+ // Not disable drag-dropping while in multi-selection mode
+ // MultiSelection.isActive() || !userIsMember(),
+ );
+ }
+
+ if ($listDom.data('sortable')) {
+ $listsDom.sortable(
+ 'option',
+ 'disabled',
+ // Disable drag-dropping when user is not member/is worker/is miniscreen
+ Utils.isMiniScreen(),
+ // Not disable drag-dropping while in multi-selection mode
+ // MultiSelection.isActive() || !userIsMember(),
);
}
});
@@ -163,8 +198,20 @@ BlazeComponent.extendComponent({
// the user will legitimately expect to be able to select some text with
// his mouse.
+ let showDesktopDragHandles = false;
+ currentUser = Meteor.user();
+ if (currentUser) {
+ showDesktopDragHandles = (currentUser.profile || {})
+ .showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ showDesktopDragHandles = true;
+ } else {
+ showDesktopDragHandles = false;
+ }
+
const noDragInside = ['a', 'input', 'textarea', 'p'].concat(
- Util.isMiniScreen || (!Util.isMiniScreen && showDesktopDragHandles)
+ Utils.isMiniScreen() ||
+ (!Utils.isMiniScreen() && showDesktopDragHandles)
? ['.js-list-handle', '.js-swimlane-header-handle']
: ['.js-list-header'],
);
@@ -245,13 +292,21 @@ BlazeComponent.extendComponent({
Template.swimlane.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
canSeeAddList() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
- !Meteor.user().isCommentOnly()
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
);
},
});
diff --git a/client/components/swimlanes/swimlanes.styl b/client/components/swimlanes/swimlanes.styl
index 164c66d5..ca5611cc 100644
--- a/client/components/swimlanes/swimlanes.styl
+++ b/client/components/swimlanes/swimlanes.styl
@@ -1,5 +1,41 @@
@import 'nib'
+/*
+// Minimize swimlanes start https://www.w3schools.com/howto/howto_js_accordion.asp
+
+.accordion
+ cursor: pointer
+ width: 30px
+ height: 20px
+ border: none
+ outline: none
+ font-size: 18px
+ transition: 0.4s
+ padding-top: 0px
+ margin-top: 0px
+
+.accordion:after
+ // Unicode triagle right:
+ content: '\25B6'
+ color: #777
+ font-weight: bold
+ float: left
+
+.active:after
+ // Unicode triangle down:
+ content: '\25BC'
+
+.panel
+ width: 100%
+ max-height: 0
+ overflow: hidden
+ transition: max-height 0.2s ease-out
+ margin: 0px
+ padding: 0px
+
+// Minimize swimlanes end https://www.w3schools.com/howto/howto_js_accordion.asp
+*/
+
.swimlane
// Even if this background color is the same as the body we can't leave it
// transparent, because that won't work during a swimlane drag.
@@ -25,22 +61,22 @@
cursor: grabbing
.swimlane-header-wrap
- display: flex;
- flex-direction: row;
- flex: 1 0 100%;
- background-color: #ccc;
+ display: flex
+ flex-direction: row
+ flex: 1 0 100%
+ background-color: #ccc
.swimlane-header
- font-size: 14px;
+ font-size: 14px
padding: 5px 5px
- font-weight: bold;
- min-height: 9px;
- width: 100%;
- overflow: hidden;
- -o-text-overflow: ellipsis;
- text-overflow: ellipsis;
- word-wrap: break-word;
- text-align: center;
+ font-weight: bold
+ min-height: 9px
+ width: 100%
+ overflow: hidden
+ -o-text-overflow: ellipsis
+ text-overflow: ellipsis
+ word-wrap: break-word
+ text-align: center
.swimlane-header-menu
position: absolute
diff --git a/client/components/users/userAvatar.jade b/client/components/users/userAvatar.jade
index ebfa48ba..7f2067ce 100644
--- a/client/components/users/userAvatar.jade
+++ b/client/components/users/userAvatar.jade
@@ -73,6 +73,7 @@ template(name="cardMemberPopup")
p.quiet @{{ user.username }}
ul.pop-over-list
if currentUser.isNotCommentOnly
+ if currentUser.isNotWorker
li: a.js-remove-member {{_ 'remove-member-from-card'}}
if $eq currentUser._id user._id
diff --git a/client/components/users/userHeader.jade b/client/components/users/userHeader.jade
index 50a80396..9306d21d 100644
--- a/client/components/users/userHeader.jade
+++ b/client/components/users/userHeader.jade
@@ -13,21 +13,46 @@ template(name="headerUserBar")
template(name="memberMenuPopup")
ul.pop-over-list
with currentUser
- li: a.js-edit-profile {{_ 'edit-profile'}}
- li: a.js-change-settings {{_ 'change-settings'}}
- li: a.js-change-avatar {{_ 'edit-avatar'}}
+ li
+ a.js-edit-profile
+ i.fa.fa-user
+ | {{_ 'edit-profile'}}
+ li
+ a.js-change-settings
+ i.fa.fa-cog
+ | {{_ 'change-settings'}}
+ li
+ a.js-change-avatar
+ i.fa.fa-picture-o
+ | {{_ 'edit-avatar'}}
unless isSandstorm
- li: a.js-change-password {{_ 'changePasswordPopup-title'}}
- li: a.js-change-language {{_ 'changeLanguagePopup-title'}}
+ li
+ a.js-change-password
+ i.fa.fa-key
+ | {{_ 'changePasswordPopup-title'}}
+ li
+ a.js-change-language
+ i.fa.fa-flag
+ | {{_ 'changeLanguagePopup-title'}}
if currentUser.isAdmin
- li: a.js-go-setting(href="{{pathFor 'setting'}}") {{_ 'admin-panel'}}
- hr
- ul.pop-over-list
- li: a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}") {{_ 'templates'}}
+ li
+ a.js-go-setting(href="{{pathFor 'setting'}}")
+ i.fa.fa-lock
+ | {{_ 'admin-panel'}}
+ unless currentUser.isWorker
+ hr
+ ul.pop-over-list
+ li
+ a(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
+ i.fa.fa-clone
+ | {{_ 'templates'}}
unless isSandstorm
hr
ul.pop-over-list
- li: a.js-logout {{_ 'log-out'}}
+ li
+ a.js-logout
+ i.fa.fa-sign-out
+ | {{_ 'log-out'}}
template(name="editProfilePopup")
form
@@ -75,21 +100,25 @@ template(name="changeSettingsPopup")
ul.pop-over-list
li
a.js-toggle-system-messages
+ i.fa.fa-comments-o
| {{_ 'hide-system-messages'}}
if hiddenSystemMessages
i.fa.fa-check
li
a.js-toggle-desktop-drag-handles
+ i.fa.fa-arrows
| {{_ 'show-desktop-drag-handles'}}
if showDesktopDragHandles
i.fa.fa-check
- li
- label.bold
- | {{_ 'show-cards-minimum-count'}}
- input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
- input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
-
+ unless currentUser.isWorker
+ li
+ label.bold
+ i.fa.fa-sort-numeric-asc
+ | {{_ 'show-cards-minimum-count'}}
+ input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
+ input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
template(name="userDeletePopup")
- p {{_ 'delete-user-confirm-popup'}}
- button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
+ unless currentUser.isWorker
+ p {{_ 'delete-user-confirm-popup'}}
+ button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
diff --git a/client/components/users/userHeader.js b/client/components/users/userHeader.js
index 194f990f..847d30fb 100644
--- a/client/components/users/userHeader.js
+++ b/client/components/users/userHeader.js
@@ -1,3 +1,6 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
+
Template.headerUserBar.events({
'click .js-open-header-member-menu': Popup.open('memberMenu'),
'click .js-change-avatar': Popup.open('changeAvatar'),
@@ -5,10 +8,22 @@ Template.headerUserBar.events({
Template.memberMenuPopup.helpers({
templatesBoardId() {
- return Meteor.user().getTemplatesBoardId();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return Meteor.user().getTemplatesBoardId();
+ } else {
+ // No need to getTemplatesBoardId on public board
+ return false;
+ }
},
templatesBoardSlug() {
- return Meteor.user().getTemplatesBoardSlug();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return Meteor.user().getTemplatesBoardSlug();
+ } else {
+ // No need to getTemplatesBoardSlug() on public board
+ return false;
+ }
},
});
@@ -30,13 +45,31 @@ Template.memberMenuPopup.events({
Template.editProfilePopup.helpers({
allowEmailChange() {
- return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
+ Meteor.call('AccountSettings.allowEmailChange', (_, result) => {
+ if (result) {
+ return true;
+ } else {
+ return false;
+ }
+ });
},
allowUserNameChange() {
- return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue;
+ Meteor.call('AccountSettings.allowUserNameChange', (_, result) => {
+ if (result) {
+ return true;
+ } else {
+ return false;
+ }
+ });
},
allowUserDelete() {
- return AccountSettings.findOne('accounts-allowUserDelete').booleanValue;
+ Meteor.call('AccountSettings.allowUserDelete', (_, result) => {
+ if (result) {
+ return true;
+ } else {
+ return false;
+ }
+ });
},
});
@@ -162,22 +195,55 @@ Template.changeLanguagePopup.events({
Template.changeSettingsPopup.helpers({
showDesktopDragHandles() {
- return Meteor.user().hasShowDesktopDragHandles();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).showDesktopDragHandles;
+ } else if (cookies.has('showDesktopDragHandles')) {
+ return true;
+ } else {
+ return false;
+ }
},
hiddenSystemMessages() {
- return Meteor.user().hasHiddenSystemMessages();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).hasHiddenSystemMessages;
+ } else if (cookies.has('hasHiddenSystemMessages')) {
+ return true;
+ } else {
+ return false;
+ }
},
showCardsCountAt() {
- return Meteor.user().getLimitToShowCardsCount();
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return Meteor.user().getLimitToShowCardsCount();
+ } else {
+ return cookies.get('limitToShowCardsCount');
+ }
},
});
Template.changeSettingsPopup.events({
'click .js-toggle-desktop-drag-handles'() {
- Meteor.call('toggleDesktopDragHandles');
+ currentUser = Meteor.user();
+ if (currentUser) {
+ Meteor.call('toggleDesktopDragHandles');
+ } else if (cookies.has('showDesktopDragHandles')) {
+ cookies.remove('showDesktopDragHandles');
+ } else {
+ cookies.set('showDesktopDragHandles', 'true');
+ }
},
'click .js-toggle-system-messages'() {
- Meteor.call('toggleSystemMessages');
+ currentUser = Meteor.user();
+ if (currentUser) {
+ Meteor.call('toggleSystemMessages');
+ } else if (cookies.has('hasHiddenSystemMessages')) {
+ cookies.remove('hasHiddenSystemMessages');
+ } else {
+ cookies.set('hasHiddenSystemMessages', 'true');
+ }
},
'click .js-apply-show-cards-at'(event, templateInstance) {
event.preventDefault();
@@ -186,7 +252,12 @@ Template.changeSettingsPopup.events({
10,
);
if (!isNaN(minLimit)) {
- Meteor.call('changeLimitToShowCardsCount', minLimit);
+ currentUser = Meteor.user();
+ if (currentUser) {
+ Meteor.call('changeLimitToShowCardsCount', minLimit);
+ } else {
+ cookies.set('limitToShowCardsCount', minLimit);
+ }
Popup.back();
}
},
diff --git a/client/lib/keyboard.js b/client/lib/keyboard.js
index d3f974be..da33f806 100755
--- a/client/lib/keyboard.js
+++ b/client/lib/keyboard.js
@@ -70,6 +70,30 @@ Mousetrap.bind('space', evt => {
}
});
+// XXX This shortcut should also work when hovering over a card in board view
+Mousetrap.bind('c', evt => {
+ if (!Session.get('currentCard')) {
+ return;
+ }
+
+ const currentUserId = Meteor.userId();
+ if (currentUserId === null) {
+ return;
+ }
+
+ if (
+ Meteor.user().isBoardMember() &&
+ !Meteor.user().isCommentOnly() &&
+ !Meteor.user().isWorker()
+ ) {
+ const card = Cards.findOne(Session.get('currentCard'));
+ card.archive();
+ // We should prevent scrolling in card when spacebar is clicked
+ // This should do it according to Mousetrap docs, but it doesn't
+ evt.preventDefault();
+ }
+});
+
Template.keyboardShortcuts.helpers({
mapping: [
{
@@ -104,5 +128,9 @@ Template.keyboardShortcuts.helpers({
keys: ['SPACE'],
action: 'shortcut-assign-self',
},
+ {
+ keys: ['C'],
+ action: 'archive-card',
+ },
],
});
diff --git a/client/lib/textComplete.js b/client/lib/textComplete.js
index 8b6dc1f7..e97d3853 100644
--- a/client/lib/textComplete.js
+++ b/client/lib/textComplete.js
@@ -48,6 +48,11 @@ $.fn.escapeableTextComplete = function(strategies, options, ...otherArgs) {
return this;
};
-EscapeActions.register('textcomplete', () => {}, () => dropdownMenuIsOpened, {
- noClickEscapeOn: '.textcomplete-dropdown',
-});
+EscapeActions.register(
+ 'textcomplete',
+ () => {},
+ () => dropdownMenuIsOpened,
+ {
+ noClickEscapeOn: '.textcomplete-dropdown',
+ },
+);
diff --git a/client/lib/utils.js b/client/lib/utils.js
index 213124f1..d712cc73 100644
--- a/client/lib/utils.js
+++ b/client/lib/utils.js
@@ -1,4 +1,40 @@
+import { Cookies } from 'meteor/ostrio:cookies';
+const cookies = new Cookies();
+
Utils = {
+ setBoardView(view) {
+ currentUser = Meteor.user();
+ if (currentUser) {
+ Meteor.user().setBoardView(view);
+ } else if (view === 'board-view-lists') {
+ cookies.set('boardView', 'board-view-lists'); //true
+ } else if (view === 'board-view-swimlanes') {
+ cookies.set('boardView', 'board-view-swimlanes'); //true
+ } else if (view === 'board-view-cal') {
+ cookies.set('boardView', 'board-view-cal'); //true
+ }
+ },
+
+ unsetBoardView() {
+ cookies.remove('boardView');
+ cookies.remove('collapseSwimlane');
+ },
+
+ boardView() {
+ currentUser = Meteor.user();
+ if (currentUser) {
+ return (currentUser.profile || {}).boardView;
+ } else if (cookies.get('boardView') === 'board-view-lists') {
+ return 'board-view-lists';
+ } else if (cookies.get('boardView') === 'board-view-swimlanes') {
+ return 'board-view-swimlanes';
+ } else if (cookies.get('boardView') === 'board-view-cal') {
+ return 'board-view-cal';
+ } else {
+ return false;
+ }
+ },
+
// XXX We should remove these two methods
goBoardId(_id) {
const board = Boards.findOne(_id);
@@ -117,8 +153,38 @@ Utils = {
// in a small window (even on desktop), Wekan run in compact mode.
// we can easily debug with a small window of desktop browser. :-)
isMiniScreen() {
+ // OLD WINDOW WIDTH DETECTION:
this.windowResizeDep.depend();
return $(window).width() <= 800;
+
+ // NEW TOUCH DEVICE DETECTION:
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
+
+ /*
+ var hasTouchScreen = false;
+ if ("maxTouchPoints" in navigator) {
+ hasTouchScreen = navigator.maxTouchPoints > 0;
+ } else if ("msMaxTouchPoints" in navigator) {
+ hasTouchScreen = navigator.msMaxTouchPoints > 0;
+ } else {
+ var mQ = window.matchMedia && matchMedia("(pointer:coarse)");
+ if (mQ && mQ.media === "(pointer:coarse)") {
+ hasTouchScreen = !!mQ.matches;
+ } else if ('orientation' in window) {
+ hasTouchScreen = true; // deprecated, but good fallback
+ } else {
+ // Only as a last resort, fall back to user agent sniffing
+ var UA = navigator.userAgent;
+ hasTouchScreen = (
+ /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) ||
+ /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA)
+ );
+ }
+ }
+ */
+ //if (hasTouchScreen)
+ // document.getElementById("exampleButton").style.padding="1em";
+ //return false;
},
calculateIndexData(prevData, nextData, nItems = 1) {