merge wefork

This commit is contained in:
Béranger Campardou 2017-01-13 11:16:37 +01:00
commit f7f5f4a35d
58 changed files with 3757 additions and 544 deletions

View file

@ -12,10 +12,12 @@ BlazeComponent.extendComponent({
const capitalizedMode = Utils.capitalize(mode);
const id = Session.get(`current${capitalizedMode}`);
const limit = this.page.get() * activitiesPerPage;
const user = Meteor.user();
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
if (id === null)
return;
this.subscribe('activities', mode, id, limit, () => {
this.subscribe('activities', mode, id, limit, hideSystem, () => {
this.loadNextPageLocked = false;
// If the sibear peak hasn't increased, that mean that there are no more

View file

@ -0,0 +1,20 @@
template(name="editCardDate")
.edit-card-date
form.edit-date
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="text" name="date" value=showDate placeholder=dateFormat autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="text" name="time" value=showTime placeholder=timeFormat)
.js-datepicker
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
template(name="dateBadge")
a.js-edit-date.card-date(title="{{showTitle}}" class="{{classes}}")
time(datetime="{{showISODate}}")
| {{showDate}}

View file

@ -0,0 +1,228 @@
// Edit start & due dates
const EditCardDate = BlazeComponent.extendComponent({
template() {
return 'editCardDate';
},
onCreated() {
this.error = new ReactiveVar('');
this.card = this.data();
this.date = new ReactiveVar(moment.invalid());
},
onRendered() {
const $picker = this.$('.js-datepicker').datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
}).on('changeDate', function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
this.find('#time').focus();
}.bind(this));
if (this.date.get().isValid()) {
$picker.datepicker('update', this.date.get().toDate());
}
},
showDate() {
if (this.date.get().isValid())
return this.date.get().format('L');
return '';
},
showTime() {
if (this.date.get().isValid())
return this.date.get().format('LT');
return '';
},
dateFormat() {
return moment.localeData().longDateFormat('L');
},
timeFormat() {
return moment.localeData().longDateFormat('LT');
},
events() {
return [{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(this.find('#time').value, 'LT', true);
if (dateMoment.isValid()) {
this.error.set('');
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
// if no time was given, init with 12:00
const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT');
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
this._storeDate(newDate.toDate());
Popup.close();
}
else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
}];
},
});
// editCardStartDatePopup
(class extends EditCardDate {
onCreated() {
super.onCreated();
this.data().startAt && this.date.set(moment(this.data().startAt));
}
_storeDate(date) {
this.card.setStart(date);
}
_deleteDate() {
this.card.unsetStart();
}
}).register('editCardStartDatePopup');
// editCardDueDatePopup
(class extends EditCardDate {
onCreated() {
super.onCreated();
this.data().dueAt && this.date.set(moment(this.data().dueAt));
}
onRendered() {
super.onRendered();
if (moment.isDate(this.card.startAt)) {
this.$('.js-datepicker').datepicker('setStartDate', this.card.startAt);
}
}
_storeDate(date) {
this.card.setDue(date);
}
_deleteDate() {
this.card.unsetDue();
}
}).register('editCardDueDatePopup');
// Display start & due dates
const CardDate = BlazeComponent.extendComponent({
template() {
return 'dateBadge';
},
onCreated() {
const self = this;
self.date = ReactiveVar();
self.now = ReactiveVar(moment());
window.setInterval(() => {
self.now.set(moment());
}, 60000);
},
showDate() {
// this will start working once mquandalle:moment
// is updated to at least moment.js 2.10.5
// until then, the date is displayed in the "L" format
return this.date.get().calendar(null, {
sameElse: 'llll',
});
},
showISODate() {
return this.date.get().toISOString();
},
});
class CardStartDate extends CardDate {
onCreated() {
super.onCreated();
const self = this;
self.autorun(() => {
self.date.set(moment(self.data().startAt));
});
}
classes() {
if (this.date.get().isBefore(this.now.get(), 'minute') &&
this.now.get().isBefore(this.data().dueAt)) {
return 'current';
}
return '';
}
showTitle() {
return `${TAPi18n.__('card-start-on')} ${this.date.get().format('LLLL')}`;
}
events() {
return super.events().concat({
'click .js-edit-date': Popup.open('editCardStartDate'),
});
}
}
CardStartDate.register('cardStartDate');
class CardDueDate extends CardDate {
onCreated() {
super.onCreated();
const self = this;
self.autorun(() => {
self.date.set(moment(self.data().dueAt));
});
}
classes() {
if (this.now.get().diff(this.date.get(), 'days') >= 2)
return 'long-overdue';
else if (this.now.get().diff(this.date.get(), 'minute') >= 0)
return 'due';
else if (this.now.get().diff(this.date.get(), 'days') >= -1)
return 'almost-due';
return '';
}
showTitle() {
return `${TAPi18n.__('card-due-on')} ${this.date.get().format('LLLL')}`;
}
events() {
return super.events().concat({
'click .js-edit-date': Popup.open('editCardDueDate'),
});
}
}
CardDueDate.register('cardDueDate');
(class extends CardStartDate {
showDate() {
return this.date.get().format('l');
}
}).register('minicardStartDate');
(class extends CardDueDate {
showDate() {
return this.date.get().format('l');
}
}).register('minicardDueDate');

View file

@ -0,0 +1,58 @@
.edit-card-date
.fields
.left
width: 56%
.right
width: 38%
.datepicker
width: 100%
table
width: 100%
border: none
border-spacing: 0
border-collapse: collapse
thead
background: none
td, th
box-sizing: border-box
.card-date
display: block
border-radius: 4px
padding: 1px 3px
background-color: #dbdbdb
&:hover, &.is-active
background-color: #b3b3b3
&.current, &.almost-due, &.due, &.long-overdue
color: #fff
&.current
background-color: #5ba639
&:hover, &.is-active
background-color: darken(#5ba639, 10)
&.almost-due
background-color: #edc909
&:hover, &.is-active
background-color: darken(#edc909, 10)
&.due
background-color: #fa3f00
&:hover, &.is-active
background-color: darken(#fa3f00, 10)
&.long-overdue
background-color: #fd5d47
&:hover, &.is-active
background-color: darken(#fd5d47, 7)
time
&::before
font: normal normal normal 14px/1 FontAwesome
font-size: inherit
-webkit-font-smoothing: antialiased
content: "\f017" // clock symbol
margin-right: 0.3em

View file

@ -35,6 +35,17 @@ template(name="cardDetails")
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
if startAt
.card-details-item.card-details-item-start
h3.card-details-item-title {{_ 'card-start'}}
+cardStartDate
if dueAt
.card-details-item.card-details-item-due
h3.card-details-item-title {{_ 'card-due'}}
+cardDueDate
//- XXX We should use "editable" to avoid repetiting ourselves
if currentUser.isBoardMember
h3.card-details-item-title {{_ 'description'}}
@ -91,6 +102,8 @@ template(name="cardDetailsActionsPopup")
li: a.js-members {{_ 'card-edit-members'}}
li: a.js-labels {{_ 'card-edit-labels'}}
li: a.js-attachments {{_ 'card-edit-attachments'}}
li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
hr
ul.pop-over-list
li: a.js-move-card-to-top {{_ 'moveCardToTop-title'}}

View file

@ -65,6 +65,9 @@ BlazeComponent.extendComponent({
[`${CSSEvents.transitionend} .js-card-details`]() {
this.isLoaded.set(true);
},
[`${CSSEvents.animationend} .js-card-details`]() {
this.isLoaded.set(true);
},
};
return [{
@ -143,6 +146,8 @@ Template.cardDetailsActionsPopup.events({
'click .js-members': Popup.open('cardMembers'),
'click .js-labels': Popup.open('cardLabels'),
'click .js-attachments': Popup.open('cardAttachments'),
'click .js-start-date': Popup.open('editCardStartDate'),
'click .js-due-date': Popup.open('editCardDueDate'),
'click .js-move-card': Popup.open('moveCard'),
'click .js-move-card-to-top'(evt) {
evt.preventDefault();

View file

@ -73,8 +73,13 @@
margin: 15px 0
.card-details-item
margin-right: 0.5em
&:last-child
margin-right: 0
&.card-details-item-labels,
&.card-details-item-members
&.card-details-item-members,
&.card-details-item-start,
&.card-details-item-due
width: 50%
flex-shrink: 1

View file

@ -23,3 +23,9 @@ template(name="minicard")
.badge
span.badge-icon.fa.fa-paperclip
span.badge-text= attachments.count
if startAt
.badge
+minicardStartDate
if dueAt
.badge
+minicardDueDate

View file

@ -91,10 +91,13 @@
margin-right: 11px
margin-bottom: 3px
font-size: 0.9em
&:last-of-type
margin-right: 0
.badge-icon,
.badge-text
vertical-align: top
vertical-align: middle
.badge-text
font-size: 0.9em

View file

@ -6,6 +6,10 @@ template(name="listHeader")
h2.list-header-name(
class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}")
= title
if showCardsCountForList cards.count
= cards.count
span.lowercase
| {{_ 'cards'}}
if currentUser.isBoardMember
if isWatching
i.list-header-watch-icon.fa.fa-eye

View file

@ -13,6 +13,14 @@ BlazeComponent.extendComponent({
return list.findWatcher(Meteor.userId());
},
limitToShowCardsCount() {
return Meteor.user().getLimitToShowCardsCount();
},
showCardsCountForList(count) {
return count > this.limitToShowCardsCount();
},
events() {
return [{
'click .js-open-list-menu': Popup.open('listAction'),

View file

@ -374,3 +374,8 @@ a
.wrapper
height: 100%
margin: 0px
.inline-input
height: 37px
margin: 8px 10px 0 0
width: 50px

View file

@ -30,10 +30,13 @@ template(name="membersWidget")
.board-widget-content
each currentBoard.activeMembers
+userAvatar(userId=this.userId showStatus=true)
unless isSandstorm
if currentUser.isBoardAdmin
a.member.add-member.js-manage-board-members
if isSandstorm
if currentUser.isBoardMember
a.member.add-member.sandstorm-powerbox-request-identity
i.fa.fa-plus
else if currentUser.isBoardAdmin
a.member.add-member.js-manage-board-members
i.fa.fa-plus
.clearfix
if isInvited
hr

View file

@ -163,6 +163,9 @@ Template.membersWidget.helpers({
Template.membersWidget.events({
'click .js-member': Popup.open('member'),
'click .js-manage-board-members': Popup.open('addMember'),
'click .sandstorm-powerbox-request-identity'() {
window.sandstormRequestIdentity();
},
'click .js-member-invite-accept'() {
const boardId = Session.get('currentBoard');
Meteor.user().removeInvite(boardId);

View file

@ -51,6 +51,7 @@
.member, .card-label
margin-right: 7px
margin-top: 5px
.sidebar-list-item-description
flex: 1

View file

@ -5,6 +5,12 @@
template(name="filterSidebar")
ul.sidebar-list
li(class="{{#if Filter.labelIds.isSelected undefined}}active{{/if}}")
a.name.js-toggle-label-filter
span.sidebar-list-item-description
{{_ 'filter-no-label'}}
if Filter.labelIds.isSelected undefined
i.fa.fa-check
each currentBoard.labels
li
a.name.js-toggle-label-filter
@ -18,6 +24,12 @@ template(name="filterSidebar")
i.fa.fa-check
hr
ul.sidebar-list
li(class="{{#if Filter.members.isSelected undefined}}active{{/if}}")
a.name.js-toggle-member-filter
span.sidebar-list-item-description
{{_ 'filter-no-member'}}
if Filter.members.isSelected undefined
i.fa.fa-check
each currentBoard.activeMembers
with getUser userId
li(class="{{#if Filter.members.isSelected _id}}active{{/if}}")

View file

@ -12,10 +12,11 @@ template(name="memberMenuPopup")
ul.pop-over-list
with currentUser
li: a.js-edit-profile {{_ 'edit-profile'}}
li: a.js-change-avatar {{_ 'edit-avatar'}}
li: a.js-change-password {{_ 'changePasswordPopup-title'}}
li: a.js-change-language {{_ 'changeLanguagePopup-title'}}
li: a.js-edit-notification {{_ 'editNotificationPopup-title'}}
li: a.js-change-settings {{_ 'change-settings'}}
li: a.js-change-avatar {{_ 'edit-avatar'}}
li: a.js-change-password {{_ 'changePasswordPopup-title'}}
li: a.js-change-language {{_ 'changeLanguagePopup-title'}}
li: a.js-edit-notification {{_ 'editNotificationPopup-title'}}
hr
ul.pop-over-list
li: a.js-logout {{_ 'log-out'}}
@ -27,6 +28,8 @@ template(name="editProfilePopup")
input.js-profile-fullname(type="text" value=profile.fullname autofocus)
label
| {{_ 'username'}}
span.error.hide.username-taken
| {{_ 'error-username-taken'}}
input.js-profile-username(type="text" value=username)
label
| {{_ 'initials'}}
@ -61,3 +64,16 @@ template(name="changeLanguagePopup")
= name
if isCurrentLanguage
i.fa.fa-check
template(name="changeSettingsPopup")
ul.pop-over-list
li
a.js-toggle-system-messages
| {{_ 'hide-system-messages'}}
if hiddenSystemMessages
i.fa.fa-check
li
label.bold
| {{_ 'show-cards-minimum-count'}}
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="1" max="99" onkeydown="return false")
input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")

View file

@ -5,6 +5,7 @@ Template.headerUserBar.events({
Template.memberMenuPopup.events({
'click .js-edit-profile': Popup.open('editProfile'),
'click .js-change-settings': Popup.open('changeSettings'),
'click .js-change-avatar': Popup.open('changeAvatar'),
'click .js-change-password': Popup.open('changePassword'),
'click .js-change-language': Popup.open('changeLanguage'),
@ -26,11 +27,18 @@ Template.editProfilePopup.events({
'profile.fullname': fullname,
'profile.initials': initials,
}});
// XXX We should report the error to the user.
if (username !== Meteor.user().username) {
Meteor.call('setUsername', username);
}
Popup.back();
Meteor.call('setUsername', username, function(error) {
const messageElement = tpl.$('.username-taken');
if (error) {
messageElement.show();
} else {
messageElement.hide();
Popup.back();
}
});
} else Popup.back();
},
});
@ -82,3 +90,26 @@ Template.changeLanguagePopup.events({
evt.preventDefault();
},
});
Template.changeSettingsPopup.helpers({
hiddenSystemMessages() {
return Meteor.user().hasHiddenSystemMessages();
},
showCardsCountAt() {
return Meteor.user().getLimitToShowCardsCount();
},
});
Template.changeSettingsPopup.events({
'click .js-toggle-system-messages'() {
Meteor.call('toggleSystemMessages');
},
'click .js-apply-show-cards-at'(evt, tpl) {
evt.preventDefault();
const minLimit = parseInt(tpl.$('#show-cards-count-at').val(), 10);
if (!isNaN(minLimit)) {
Meteor.call('changeLimitToShowCardsCount', minLimit);
Popup.back();
}
},
});