mirror of
https://github.com/wekan/wekan.git
synced 2026-03-03 04:10:16 +01:00
Renaissance
_,,ad8888888888bba,_
,ad88888I888888888888888ba,
,88888888I88888888888888888888a,
,d888888888I8888888888888888888888b,
d88888PP"""" ""YY88888888888888888888b,
,d88"'__,,--------,,,,.;ZZZY8888888888888,
,8IIl'" ;;l"ZZZIII8888888888,
,I88l;' ;lZZZZZ888III8888888,
,II88Zl;. ;llZZZZZ888888I888888,
,II888Zl;. .;;;;;lllZZZ888888I8888b
,II8888Z;; `;;;;;''llZZ8888888I8888,
II88888Z;' .;lZZZ8888888I888b
II88888Z; _,aaa, .,aaaaa,__.l;llZZZ88888888I888
II88888IZZZZZZZZZ, .ZZZZZZZZZZZZZZ;llZZ88888888I888,
II88888IZZ<'(@@>Z| |ZZZ<'(@@>ZZZZ;;llZZ888888888I88I
,II88888; `""" ;| |ZZ; `""" ;;llZ8888888888I888
II888888l `;; .;llZZ8888888888I888,
,II888888Z; ;;; .;;llZZZ8888888888I888I
III888888Zl; .., `;; ,;;lllZZZ88888888888I888
II88888888Z;;...;(_ _) ,;;;llZZZZ88888888888I888,
II88888888Zl;;;;;' `--'Z;. .,;;;;llZZZZ88888888888I888b
]I888888888Z;;;;' ";llllll;..;;;lllZZZZ88888888888I8888,
II888888888Zl.;;"Y88bd888P";;,..;lllZZZZZ88888888888I8888I
II8888888888Zl;.; `"PPP";;;,..;lllZZZZZZZ88888888888I88888
II888888888888Zl;;. `;;;l;;;;lllZZZZZZZZW88888888888I88888
`II8888888888888Zl;. ,;;lllZZZZZZZZWMZ88888888888I88888
II8888888888888888ZbaalllZZZZZZZZZWWMZZZ8888888888I888888,
`II88888888888888888b"WWZZZZZWWWMMZZZZZZI888888888I888888b
`II88888888888888888;ZZMMMMMMZZZZZZZZllI888888888I8888888
`II8888888888888888 `;lZZZZZZZZZZZlllll888888888I8888888,
II8888888888888888, `;lllZZZZllllll;;.Y88888888I8888888b,
,II8888888888888888b .;;lllllll;;;.;..88888888I88888888b,
II888888888888888PZI;. .`;;;.;;;..; ...88888888I8888888888,
II888888888888PZ;;';;. ;. .;. .;. .. Y8888888I88888888888b,
,II888888888PZ;;' `8888888I8888888888888b,
II888888888' 888888I8888888888888888
,II888888888 ,888888I8888888888888888
,d88888888888 d888888I8888888888ZZZZZZ
,ad888888888888I 8888888I8888ZZZZZZZZZZZZ
888888888888888' 888888IZZZZZZZZZZZZZZZZZ
8888888888P'8P' Y888ZZZZZZZZZZZZZZZZZZZZ
888888888, " ,ZZZZZZZZZZZZZZZZZZZZZZZ
8888888888, ,ZZZZZZZZZZZZZZZZZZZZZZZZZZ
888888888888a, _ ,ZZZZZZZZZZZZZZZZZZZZ88888888
888888888888888ba,_d' ,ZZZZZZZZZZZZZZZZZ8888888888888
8888888888888888888888bbbaaa,,,______,ZZZZZZZZZZZZZZZ88888888888888888
88888888888888888888888888888888888ZZZZZZZZZZZZZZZ88888888888888888888
8888888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888
888888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888
8888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888
88888888888888888888888888888ZZZZZZZZZZZZZZ888888888888888888888888888
8888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888 Normand 8
88888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888 Veilleux 8
8888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888888888
This commit is contained in:
commit
2dbea30842
128 changed files with 10521 additions and 0 deletions
47
client/components/cards/details.jade
Normal file
47
client/components/cards/details.jade
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
template(name="cardSidebar")
|
||||
.card-sidebar.sidebar
|
||||
.card-detail.sidebar-content.js-card-sidebar-content
|
||||
if cover
|
||||
.card-detail-cover(style="background-image: url({{ card.cover.url }})")
|
||||
.card-detail-header(class="{{#if currentUser.isBoardMember}}editable{{/if}}")
|
||||
a.js-close-card-detail
|
||||
i.fa.fa-times
|
||||
h2.card-detail-title.js-card-title= title
|
||||
p.card-detail-list.js-move-card
|
||||
| {{_ 'in-list'}}
|
||||
a.card-detail-list-title(
|
||||
class="{{#if currentUser.isBoardMember}}js-open-move-from-header is-editable{{/if}}")
|
||||
= list.title
|
||||
hr
|
||||
//- if card.members
|
||||
.card-detail-item.card-detail-item-members.clearfix.js-card-detail-members
|
||||
h3.card-detail-item-header {{_ 'members'}}
|
||||
.js-card-detail-members-list.clearfix
|
||||
each members
|
||||
+userAvatar(userId=this size="small" cardId=../_id)
|
||||
a.card-detail-item-add-button.dark-hover.js-details-edit-members
|
||||
i.fa.fa-plus
|
||||
//- We should use "editable" to avoide repetiting ourselves
|
||||
.clearfix
|
||||
if currentUser.isBoardMember
|
||||
h3 Description
|
||||
+inlinedForm(classNames="js-card-description")
|
||||
i.fa.fa-times.js-close-inlined-form
|
||||
textarea(autofocus)= description
|
||||
button(type="submit") {{_ 'edit'}}
|
||||
else
|
||||
.js-open-inlined-form
|
||||
a {{_ 'edit'}}
|
||||
+viewer
|
||||
= description
|
||||
else if description
|
||||
h3 Description
|
||||
+viewer
|
||||
= description
|
||||
hr
|
||||
if attachments.count
|
||||
+WindowAttachmentsModule(card=this)
|
||||
+WindowActivityModule(card=this)
|
||||
|
||||
template(name="moveCardPopup")
|
||||
+boardLists
|
||||
103
client/components/cards/details.js
Normal file
103
client/components/cards/details.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
BlazeComponent.extendComponent({
|
||||
template: function() {
|
||||
return 'cardSidebar';
|
||||
},
|
||||
|
||||
mixins: function() {
|
||||
return [Mixins.InfiniteScrolling];
|
||||
},
|
||||
|
||||
calculateNextPeak: function() {
|
||||
var altitude = this.find('.js-card-sidebar-content').scrollHeight;
|
||||
this.callFirstWith(this, 'setNextPeak', altitude);
|
||||
},
|
||||
|
||||
reachNextPeak: function() {
|
||||
var activitiesComponent = this.componentChildren('activities')[0];
|
||||
activitiesComponent.loadNextPage();
|
||||
},
|
||||
|
||||
events: function() {
|
||||
return [{
|
||||
'click .js-move-card': Popup.open('moveCard'),
|
||||
'submit .js-card-description': function(evt) {
|
||||
evt.preventDefault();
|
||||
var cardId = Session.get('currentCard');
|
||||
var form = this.componentChildren('inlinedForm')[0];
|
||||
var newDescription = form.getValue();
|
||||
Cards.update(cardId, {
|
||||
$set: {
|
||||
description: newDescription
|
||||
}
|
||||
});
|
||||
form.close();
|
||||
},
|
||||
'click .js-close-card-detail': function() {
|
||||
Utils.goBoardId(Session.get('currentBoard'));
|
||||
},
|
||||
'click .editable .js-card-title': function(event, t) {
|
||||
var editable = t.$('.card-detail-title');
|
||||
|
||||
// add class editing and focus
|
||||
$('.editing').removeClass('editing');
|
||||
editable.addClass('editing');
|
||||
editable.find('#title').focus();
|
||||
},
|
||||
'click .js-edit-desc': function(event, t) {
|
||||
var editable = t.$('.card-detail-item');
|
||||
|
||||
// editing remove based and add current editing.
|
||||
$('.editing').removeClass('editing');
|
||||
editable.addClass('editing');
|
||||
editable.find('#desc').focus();
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-cancel-edit': function(event, t) {
|
||||
// remove editing hide.
|
||||
$('.editing').removeClass('editing');
|
||||
},
|
||||
'submit #WindowTitleEdit': function(event, t) {
|
||||
var title = t.find('#title').value;
|
||||
if ($.trim(title)) {
|
||||
Cards.update(this.card._id, {
|
||||
$set: {
|
||||
title: title
|
||||
}
|
||||
}, function (err, res) {
|
||||
if (!err) $('.editing').removeClass('editing');
|
||||
});
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
'submit #WindowDescEdit': function(event, t) {
|
||||
Cards.update(this.card._id, {
|
||||
$set: {
|
||||
description: t.find('#desc').value
|
||||
}
|
||||
}, function(err) {
|
||||
if (!err) $('.editing').removeClass('editing');
|
||||
});
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .member': Popup.open('cardMember'),
|
||||
'click .js-details-edit-members': Popup.open('cardMembers'),
|
||||
'click .js-details-edit-labels': Popup.open('cardLabels')
|
||||
}];
|
||||
}
|
||||
}).register('cardSidebar');
|
||||
|
||||
Template.moveCardPopup.events({
|
||||
'click .js-select-list': function() {
|
||||
// XXX We should *not* get the currentCard from the global state, but
|
||||
// instead from a “component” state.
|
||||
var cardId = Session.get('currentCard');
|
||||
var newListId = this._id;
|
||||
Cards.update(cardId, {
|
||||
$set: {
|
||||
listId: newListId
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
161
client/components/cards/details.styl
Normal file
161
client/components/cards/details.styl
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
@import 'nib'
|
||||
|
||||
.card-detail.sidebar-content
|
||||
width: 496px - 2 * 20px
|
||||
top: -46px !important
|
||||
z-index: 20 !important
|
||||
// XXX Animate apparition
|
||||
|
||||
.card-detail-header
|
||||
background: #F7F7F7
|
||||
border-bottom: 1px solid darken(white, 10%)
|
||||
position: absolute
|
||||
min-height: 38px
|
||||
top: 0
|
||||
left: 0
|
||||
right: 0
|
||||
padding 7px 20px 0
|
||||
|
||||
i.fa
|
||||
float: right
|
||||
font-size: 1.3em
|
||||
color: darken(white, 35%)
|
||||
margin-top: 7px
|
||||
|
||||
.card-detail-title
|
||||
font-weight: bold
|
||||
font-size: 1.7em
|
||||
margin: 3px 0 0
|
||||
padding: 0
|
||||
|
||||
.card-detail-list
|
||||
font-size: 0.85em
|
||||
margin-bottom: 3px
|
||||
|
||||
a.card-detail-list-title
|
||||
font-weight: bold
|
||||
|
||||
&.is-editable
|
||||
display: inline-block
|
||||
background: darken(white, 10%)
|
||||
border-radius: 3px
|
||||
padding: 0px 5px
|
||||
|
||||
.new-comment
|
||||
position: relative
|
||||
margin: 0 0 20px 38px
|
||||
|
||||
.member
|
||||
opacity: .7
|
||||
position: absolute
|
||||
top: 1px
|
||||
left: -38px
|
||||
|
||||
.helper
|
||||
bottom: 0
|
||||
display: none
|
||||
position: absolute
|
||||
right: 9px
|
||||
|
||||
&.focus
|
||||
|
||||
.member
|
||||
opacity: 1
|
||||
|
||||
.helper
|
||||
display: inline-block
|
||||
|
||||
.new-comment-input
|
||||
min-height: 108px
|
||||
color: #4d4d4d
|
||||
cursor: auto
|
||||
overflow: hidden
|
||||
word-wrap: break-word
|
||||
|
||||
.too-long
|
||||
margin-top: 8px
|
||||
|
||||
.new-comment-input
|
||||
background-color: #fff
|
||||
border: 0
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
|
||||
color: #8c8c8c
|
||||
height: 36px
|
||||
margin: 4px 4px 6px 0
|
||||
padding: 9px 11px
|
||||
width: 100%
|
||||
|
||||
&:hover,
|
||||
&:focus
|
||||
background-color: #fff
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, .33)
|
||||
border: 0
|
||||
cursor: pointer
|
||||
|
||||
&:focus
|
||||
cursor: auto
|
||||
|
||||
.list-voters.compact .voter
|
||||
position: relative
|
||||
min-height: 36px
|
||||
|
||||
.member
|
||||
left: 0
|
||||
position: absolute
|
||||
top: 0
|
||||
|
||||
.title
|
||||
display: block
|
||||
line-height: 30px
|
||||
left: 0
|
||||
overflow: hidden
|
||||
padding-left: 38px
|
||||
position: absolute
|
||||
text-overflow: ellipsis
|
||||
top: 0
|
||||
white-space: nowrap
|
||||
width: 230px
|
||||
|
||||
.list-voters .title
|
||||
display: none
|
||||
|
||||
.card-composer
|
||||
padding-bottom: 8px
|
||||
|
||||
.cc-controls
|
||||
margin-top: 1px
|
||||
|
||||
input[type="submit"]
|
||||
float: left
|
||||
margin-top: 0
|
||||
padding: 5px 18px
|
||||
|
||||
.icon-lg
|
||||
float: left
|
||||
|
||||
.cc-opt
|
||||
float: right
|
||||
|
||||
.minicard-placeholder,
|
||||
.minicard.placeholder
|
||||
background: silver
|
||||
border: none
|
||||
min-height: 18px
|
||||
|
||||
.hook
|
||||
height: 18px
|
||||
position: absolute
|
||||
right: 0
|
||||
top: 0
|
||||
width: 18px
|
||||
|
||||
input[type="text"].attachment-add-link-input
|
||||
float: left
|
||||
margin: 0 0 8px
|
||||
width: 80%
|
||||
|
||||
input[type="submit"].attachment-add-link-submit
|
||||
float: left
|
||||
margin: 0 0 8px 4px
|
||||
padding: 6px 12px
|
||||
width: 18%
|
||||
285
client/components/cards/events.js
Normal file
285
client/components/cards/events.js
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
// Template.cards.events({
|
||||
// // 'click .js-cancel': function(event, t) {
|
||||
// // var composer = t.$('.card-composer');
|
||||
|
||||
// // // Keep the old value in memory to display it again next time
|
||||
// // var inputCacheKey = "addCard-" + this.listId;
|
||||
// // var oldValue = composer.find('.js-card-title').val();
|
||||
// // InputsCache.set(inputCacheKey, oldValue);
|
||||
|
||||
// // // add composer hide class
|
||||
// // composer.addClass('hide');
|
||||
// // composer.find('.js-card-title').val('');
|
||||
|
||||
// // // remove hide open link class
|
||||
// // $('.js-open-card-composer').removeClass('hide');
|
||||
// // },
|
||||
// 'submit': function(evt, tpl) {
|
||||
// evt.preventDefault();
|
||||
// var textarea = $(evt.currentTarget).find('textarea');
|
||||
// var title = textarea.val();
|
||||
// var lastCard = tpl.find('.js-minicard:last-child');
|
||||
// var sort;
|
||||
// if (lastCard === null) {
|
||||
// sort = 0;
|
||||
// } else {
|
||||
// sort = Blaze.getData(lastCard).sort + 1;
|
||||
// }
|
||||
// // debugger
|
||||
|
||||
// // Clear the form in-memory cache
|
||||
// // var inputCacheKey = "addCard-" + this.listId;
|
||||
// // InputsCache.set(inputCacheKey, '');
|
||||
|
||||
// // title trim if not empty then
|
||||
// if ($.trim(title)) {
|
||||
// Cards.insert({
|
||||
// title: title,
|
||||
// listId: Template.currentData().listId,
|
||||
// boardId: Template.currentData().board._id,
|
||||
// sort: sort
|
||||
// }, function(err, _id) {
|
||||
// // In case the filter is active we need to add the newly
|
||||
// // inserted card in the list of exceptions -- cards that are
|
||||
// // not filtered. Otherwise the card will disappear instantly.
|
||||
// // See https://github.com/libreboard/libreboard/issues/80
|
||||
// Filter.addException(_id);
|
||||
// });
|
||||
|
||||
// // empty and focus.
|
||||
// textarea.val('').focus();
|
||||
|
||||
// // focus complete then scroll top
|
||||
// Utils.Scroll(tpl.find('.js-minicards')).top(1000, true);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// Template.cards.events({
|
||||
// 'click .member': Popup.open('cardMember')
|
||||
// });
|
||||
|
||||
Template.cardMemberPopup.events({
|
||||
'click .js-remove-member': function() {
|
||||
Cards.update(this.cardId, {$pull: {members: this.userId}});
|
||||
Popup.close();
|
||||
}
|
||||
});
|
||||
|
||||
Template.WindowActivityModule.events({
|
||||
'click .js-new-comment:not(.focus)': function(evt) {
|
||||
var $this = $(evt.currentTarget);
|
||||
$this.addClass('focus');
|
||||
},
|
||||
'submit #CommentForm': function(evt, t) {
|
||||
var text = t.$('.js-new-comment-input');
|
||||
if ($.trim(text.val())) {
|
||||
CardComments.insert({
|
||||
boardId: this.card.boardId,
|
||||
cardId: this.card._id,
|
||||
text: text.val()
|
||||
});
|
||||
text.val('');
|
||||
$('.focus').removeClass('focus');
|
||||
}
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
Template.WindowSidebarModule.events({
|
||||
'click .js-change-card-members': Popup.open('cardMembers'),
|
||||
'click .js-edit-labels': Popup.open('cardLabels'),
|
||||
'click .js-archive-card': function(evt) {
|
||||
// Update
|
||||
Cards.update(this.card._id, {
|
||||
$set: {
|
||||
archived: true
|
||||
}
|
||||
});
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-unarchive-card': function(evt) {
|
||||
Cards.update(this.card._id, {
|
||||
$set: {
|
||||
archived: false
|
||||
}
|
||||
});
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
|
||||
Cards.remove(this.card._id);
|
||||
|
||||
// redirect board
|
||||
Utils.goBoardId(this.card.board()._id);
|
||||
Popup.close();
|
||||
}),
|
||||
'click .js-more-menu': Popup.open('cardMore'),
|
||||
'click .js-attach': Popup.open('cardAttachments')
|
||||
});
|
||||
|
||||
Template.WindowAttachmentsModule.events({
|
||||
'click .js-attach': Popup.open('cardAttachments'),
|
||||
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete',
|
||||
function() {
|
||||
Attachments.remove(this._id);
|
||||
Popup.close();
|
||||
}
|
||||
),
|
||||
// If we let this event bubble, Iron-Router will handle it and empty the
|
||||
// page content, see #101.
|
||||
'click .js-open-viewer, click .js-download': function(event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
'click .js-add-cover': function() {
|
||||
Cards.update(this.cardId, { $set: { coverId: this._id } });
|
||||
},
|
||||
'click .js-remove-cover': function() {
|
||||
Cards.update(this.cardId, { $unset: { coverId: '' } });
|
||||
}
|
||||
});
|
||||
|
||||
Template.cardMembersPopup.events({
|
||||
'click .js-select-member': function(evt) {
|
||||
var cardId = Template.parentData(2).data._id;
|
||||
var memberId = this.userId;
|
||||
var operation;
|
||||
if (Cards.find({ _id: cardId, members: memberId}).count() === 0)
|
||||
operation = '$addToSet';
|
||||
else
|
||||
operation = '$pull';
|
||||
|
||||
var query = {};
|
||||
query[operation] = {
|
||||
members: memberId
|
||||
};
|
||||
Cards.update(cardId, query);
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
Template.cardLabelsPopup.events({
|
||||
'click .js-select-label': function(evt) {
|
||||
var cardId = Template.parentData(2).data._id;
|
||||
var labelId = this._id;
|
||||
var operation;
|
||||
if (Cards.find({ _id: cardId, labelIds: labelId}).count() === 0)
|
||||
operation = '$addToSet';
|
||||
else
|
||||
operation = '$pull';
|
||||
|
||||
var query = {};
|
||||
query[operation] = {
|
||||
labelIds: labelId
|
||||
};
|
||||
Cards.update(cardId, query);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-edit-label': Popup.open('editLabel'),
|
||||
'click .js-add-label': Popup.open('createLabel')
|
||||
});
|
||||
|
||||
Template.formLabel.events({
|
||||
'click .js-palette-color': function(evt) {
|
||||
var $this = $(evt.currentTarget);
|
||||
|
||||
// hide selected ll colors
|
||||
$('.js-palette-select').addClass('hide');
|
||||
|
||||
// show select color
|
||||
$this.find('.js-palette-select').removeClass('hide');
|
||||
}
|
||||
});
|
||||
|
||||
Template.createLabelPopup.events({
|
||||
// Create the new label
|
||||
'submit .create-label': function(evt, tpl) {
|
||||
var name = tpl.$('#labelName').val().trim();
|
||||
var boardId = Session.get('currentBoard');
|
||||
var selectLabelDom = tpl.$('.js-palette-select:not(.hide)').get(0);
|
||||
var selectLabel = Blaze.getData(selectLabelDom);
|
||||
Boards.update(boardId, {
|
||||
$push: {
|
||||
labels: {
|
||||
_id: Random.id(6),
|
||||
name: name,
|
||||
color: selectLabel.color
|
||||
}
|
||||
}
|
||||
});
|
||||
Popup.back();
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
Template.editLabelPopup.events({
|
||||
'click .js-delete-label': Popup.afterConfirm('deleteLabel', function() {
|
||||
var boardId = Session.get('currentBoard');
|
||||
Boards.update(boardId, {
|
||||
$pull: {
|
||||
labels: {
|
||||
_id: this._id
|
||||
}
|
||||
}
|
||||
});
|
||||
Popup.back(2);
|
||||
}),
|
||||
'submit .edit-label': function(evt, tpl) {
|
||||
var name = tpl.$('#labelName').val().trim();
|
||||
var boardId = Session.get('currentBoard');
|
||||
var getLabel = Utils.getLabelIndex(boardId, this._id);
|
||||
var selectLabelDom = tpl.$('.js-palette-select:not(.hide)').get(0);
|
||||
var selectLabel = Blaze.getData(selectLabelDom);
|
||||
var $set = {};
|
||||
|
||||
// set label index
|
||||
$set[getLabel.key('name')] = name;
|
||||
|
||||
// set color
|
||||
$set[getLabel.key('color')] = selectLabel.color;
|
||||
|
||||
// update
|
||||
Boards.update(boardId, { $set: $set });
|
||||
|
||||
// return to the previous popup view trigger
|
||||
Popup.back();
|
||||
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-select-label': function() {
|
||||
Cards.remove(this.cardId);
|
||||
|
||||
// redirect board
|
||||
Utils.goBoardId(this.boardId);
|
||||
}
|
||||
});
|
||||
|
||||
Template.cardMorePopup.events({
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function() {
|
||||
Cards.remove(this.card._id);
|
||||
|
||||
// redirect board
|
||||
Utils.goBoardId(this.card.board()._id);
|
||||
})
|
||||
});
|
||||
|
||||
Template.cardAttachmentsPopup.events({
|
||||
'change .js-attach-file': function(evt) {
|
||||
var card = this.card;
|
||||
FS.Utility.eachFile(evt, function(f) {
|
||||
var file = new FS.File(f);
|
||||
|
||||
// set Ids
|
||||
file.boardId = card.boardId;
|
||||
file.cardId = card._id;
|
||||
|
||||
// upload file
|
||||
Attachments.insert(file);
|
||||
|
||||
Popup.close();
|
||||
});
|
||||
},
|
||||
'click .js-computer-upload': function(evt, t) {
|
||||
t.find('.js-attach-file').click();
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
48
client/components/cards/helpers.js
Normal file
48
client/components/cards/helpers.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
Template.cardMembersPopup.helpers({
|
||||
isCardMember: function() {
|
||||
var cardId = Template.parentData()._id;
|
||||
var cardMembers = Cards.findOne(cardId).members || [];
|
||||
return _.contains(cardMembers, this.userId);
|
||||
},
|
||||
user: function() {
|
||||
return Users.findOne(this.userId);
|
||||
}
|
||||
});
|
||||
|
||||
Template.cardLabelsPopup.helpers({
|
||||
isLabelSelected: function(cardId) {
|
||||
return _.contains(Cards.findOne(cardId).labelIds, this._id);
|
||||
}
|
||||
});
|
||||
|
||||
var labelColors;
|
||||
Meteor.startup(function() {
|
||||
labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
|
||||
});
|
||||
|
||||
Template.createLabelPopup.helpers({
|
||||
// This is the default color for a new label. We search the first color that
|
||||
// is not already used in the board (although it's not a problem if two
|
||||
// labels have the same color).
|
||||
defaultColor: function() {
|
||||
var labels = this.labels || this.card.board().labels;
|
||||
var usedColors = _.pluck(labels, 'color');
|
||||
var availableColors = _.difference(labelColors, usedColors);
|
||||
return availableColors.length > 1 ? availableColors[0] : 'green';
|
||||
}
|
||||
});
|
||||
|
||||
Template.formLabel.helpers({
|
||||
labels: function() {
|
||||
return _.map(labelColors, function(color) {
|
||||
return { color: color, name: '' };
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentCard', function() {
|
||||
var cardId = Session.get('currentCard');
|
||||
if (cardId) {
|
||||
return Cards.findOne(cardId);
|
||||
}
|
||||
});
|
||||
183
client/components/cards/labels.styl
Normal file
183
client/components/cards/labels.styl
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
@import 'nib'
|
||||
|
||||
// XXX Use .board-widget-labels as a flexbox container
|
||||
.card-label
|
||||
background-color: #b3b3b3
|
||||
border-radius: 4px
|
||||
color: white
|
||||
display: inline-block
|
||||
font-weight: 700
|
||||
font-size: 13px
|
||||
margin-right: 4px
|
||||
padding: 3px 8px
|
||||
position:relative
|
||||
max-width: 100%
|
||||
min-width: 8px
|
||||
overflow: ellipsis
|
||||
height: 18px
|
||||
|
||||
&:hover
|
||||
color: white
|
||||
|
||||
.card-label-green
|
||||
background-color: #3cb500
|
||||
|
||||
.card-label-yellow
|
||||
background-color: #fad900
|
||||
|
||||
.card-label-orange
|
||||
background-color: #ff9f19
|
||||
|
||||
.card-label-red
|
||||
background-color: #eb4646
|
||||
|
||||
.card-label-purple
|
||||
background-color: #a632db
|
||||
|
||||
.card-label-blue
|
||||
background-color: #0079bf
|
||||
|
||||
.card-label-pink
|
||||
background-color: #ff78cb
|
||||
|
||||
.card-label-sky
|
||||
background-color: #00c2e0
|
||||
|
||||
.card-label-black
|
||||
background-color: #4d4d4d
|
||||
|
||||
.card-label-lime
|
||||
background-color: #51e898
|
||||
|
||||
.edit-label,
|
||||
.create-label
|
||||
.card-label
|
||||
float: left
|
||||
height: 25px
|
||||
margin: 0px 3% 7px 0px
|
||||
width: 10.5%
|
||||
cursor: pointer
|
||||
|
||||
.edit-labels
|
||||
input[type="text"]
|
||||
margin: 4px 0 6px 38px
|
||||
width: 243px
|
||||
|
||||
.card-label
|
||||
height: 30px
|
||||
left: 0
|
||||
padding: 1px 5px
|
||||
position: absolute
|
||||
top: 0
|
||||
width: 24px
|
||||
|
||||
.labels-static .card-label
|
||||
line-height: 30px
|
||||
margin-bottom: 4px
|
||||
position: relative
|
||||
top: auto
|
||||
left: 0
|
||||
width: 260px
|
||||
|
||||
.minicard-labels
|
||||
position: relative
|
||||
z-index: 30
|
||||
top: -6px
|
||||
|
||||
.card-label
|
||||
border-radius: 0
|
||||
float: left
|
||||
height: 4px
|
||||
margin-bottom: 1px
|
||||
padding: 0
|
||||
width: 40px
|
||||
line-height: 100px
|
||||
|
||||
.card-detail-item-labels .card-label
|
||||
border-radius: 3px
|
||||
display: block
|
||||
float: left
|
||||
height: 20px
|
||||
line-height: 20px
|
||||
margin: 0 4px 4px 0
|
||||
min-width: 30px
|
||||
padding: 5px 10px
|
||||
width: auto
|
||||
|
||||
.editable-labels .card-label:hover
|
||||
cursor: pointer
|
||||
opacity: .75
|
||||
|
||||
.edit-labels-pop-over
|
||||
margin-bottom: 8px
|
||||
|
||||
.edit-labels-pop-over .shortcut
|
||||
display: inline-block
|
||||
|
||||
.card-label-selectable
|
||||
border-radius: 3px
|
||||
cursor: pointer
|
||||
margin: 0 50px 4px 0
|
||||
min-height: 18px
|
||||
padding: 8px
|
||||
position: relative
|
||||
transition: margin-right .1s
|
||||
|
||||
.card-label-selectable-icon
|
||||
position: absolute
|
||||
top: 8px
|
||||
right: -20px
|
||||
|
||||
&.active:hover,
|
||||
&.active,
|
||||
&.active.selected:hover,
|
||||
&.active.selected
|
||||
margin-right: 38px
|
||||
padding-right: 32px
|
||||
|
||||
.card-label-selectable-icon
|
||||
right: 6px
|
||||
|
||||
&.active:hover:hover,
|
||||
&.active:hover,
|
||||
&.active.selected:hover:hover,
|
||||
&.active.selected:hover
|
||||
margin-right: 38px
|
||||
|
||||
&.selected,
|
||||
&:hover
|
||||
margin-right: 38px
|
||||
opacity: .8
|
||||
|
||||
.active .card-label-selectable
|
||||
&,
|
||||
&:hover
|
||||
margin-right: 0
|
||||
|
||||
.card-label-selectable-icon
|
||||
right: 8px
|
||||
|
||||
.card-label-edit-button
|
||||
border-radius: 3px
|
||||
float: right
|
||||
padding: 8px
|
||||
|
||||
&:hover
|
||||
background: #dbdbdb
|
||||
|
||||
.card-label-color-select-icon
|
||||
left: 14px
|
||||
position: absolute
|
||||
top: 9px
|
||||
|
||||
.phenom .card-label
|
||||
display: inline-block
|
||||
font-size: 12px
|
||||
height: 14px
|
||||
line-height: 13px
|
||||
padding: 0 4px
|
||||
min-width: 16px
|
||||
overflow: ellipsis
|
||||
|
||||
.board-widget .phenom .card-label
|
||||
max-width: 130px
|
||||
136
client/components/cards/minicard.styl
Normal file
136
client/components/cards/minicard.styl
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
.minicard
|
||||
background-color: #fff
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2)
|
||||
border-radius: 2px
|
||||
cursor: pointer
|
||||
margin-bottom: 9px
|
||||
max-width: 300px
|
||||
min-height: 20px
|
||||
position: relative
|
||||
z-index: 0
|
||||
overflow: hidden
|
||||
|
||||
a
|
||||
color: #4d4d4d
|
||||
|
||||
&.active-card
|
||||
background-color: #f0f0f0
|
||||
border-bottom-color: #c2c2c2
|
||||
|
||||
.minicard-operation
|
||||
display: block
|
||||
|
||||
&.draggable-hover-card
|
||||
background-color: #f0f0f0
|
||||
border-bottom-color: #c2c2c2
|
||||
|
||||
.minicard-cover
|
||||
background-position: center
|
||||
background-repeat: no-repeat
|
||||
background-size: cover
|
||||
height: 145px
|
||||
user-select: none
|
||||
margin: -6px -8px 6px -8px
|
||||
border-radius: top 2px
|
||||
|
||||
&.no-preview-size
|
||||
background-size: auto
|
||||
background-position: center
|
||||
|
||||
.minicard-details
|
||||
padding: 6px 8px 2px
|
||||
position: relative
|
||||
z-index: 10
|
||||
|
||||
|
||||
&.is-selected
|
||||
.minicard-details
|
||||
padding-bottom: 0
|
||||
|
||||
a.minicard-details
|
||||
text-decoration:none
|
||||
|
||||
.minicard-details-overlay
|
||||
background: transparent
|
||||
bottom: 0
|
||||
left: 0
|
||||
position: absolute
|
||||
right: 0
|
||||
top: 0
|
||||
|
||||
.minicard-dropzone
|
||||
display: none
|
||||
|
||||
.minicard.drophover .minicard-dropzone
|
||||
background: rgba(255, 255, 255, .8)
|
||||
// border-radius: 3px
|
||||
// bottom: 0
|
||||
// display: block
|
||||
// font-weight: 700
|
||||
// line-height: 100%
|
||||
// left: 0
|
||||
// margin: 0
|
||||
// opacity: 1
|
||||
// padding: 0
|
||||
// position: absolute
|
||||
// right: 0
|
||||
// text-align: center
|
||||
// top: 0
|
||||
// z-index: 40
|
||||
|
||||
.minicard-title
|
||||
display: block
|
||||
font-weight: 400
|
||||
margin: 0 0 4px
|
||||
overflow: hidden
|
||||
text-decoration: none
|
||||
word-wrap: break-word
|
||||
|
||||
&::selection
|
||||
background: transparent
|
||||
|
||||
.minicard-labels
|
||||
padding-top: 3px
|
||||
margin-top: 4px
|
||||
float: right
|
||||
|
||||
.minicard-label
|
||||
float: right
|
||||
width: 8px
|
||||
height: @width
|
||||
border-radius: 2px
|
||||
margin-left: 4px
|
||||
|
||||
.minicard-members
|
||||
float: right
|
||||
margin: 2px -8px -2px 0
|
||||
|
||||
.member
|
||||
float: right
|
||||
border-radius: 50%
|
||||
height: 28px
|
||||
width: @height
|
||||
|
||||
+ .badges
|
||||
margin-top: 10px
|
||||
|
||||
.minicard-members:empty
|
||||
display: none
|
||||
|
||||
.badges
|
||||
float: left
|
||||
|
||||
&:empty
|
||||
display: none
|
||||
|
||||
textarea.minicard-composer-textarea,
|
||||
textarea.minicard-composer-textarea:focus
|
||||
background: none
|
||||
border: none
|
||||
box-shadow: none
|
||||
height: auto
|
||||
margin-bottom: 4px
|
||||
padding: 0
|
||||
max-height: 162px
|
||||
min-height: 54px
|
||||
overflow-y: auto
|
||||
12
client/components/cards/popups.jade
Normal file
12
client/components/cards/popups.jade
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
template(name="cardMembersPopup")
|
||||
//- input.js-search-mem(autofocus placeholder="Search members…" type="text")
|
||||
ul.pop-over-member-list.checkable.js-mem-list
|
||||
each board.members
|
||||
li.item.js-member-item(class="{{#if isCardMember}}active{{/if}}")
|
||||
a.name.js-select-member(href="#")
|
||||
+userAvatar(user=user size="small")
|
||||
span.full-name
|
||||
= user.profile.name
|
||||
| (<span class="username">{{ user.username }}</span>)
|
||||
if isCardMember
|
||||
i.fa.fa-check
|
||||
15
client/components/cards/router.js
Normal file
15
client/components/cards/router.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Router.route('/boards/:boardId/:slug/:cardId', {
|
||||
name: 'Card',
|
||||
template: 'board',
|
||||
waitOn: function() {
|
||||
var params = this.params;
|
||||
// XXX We probably shouldn't rely on Session
|
||||
Session.set('currentBoard', params.boardId);
|
||||
Session.set('currentCard', params.cardId);
|
||||
|
||||
return BoardSubsManager.subscribe('board', params.boardId, params.slug);
|
||||
},
|
||||
data: function() {
|
||||
return Boards.findOne(this.params.boardId);
|
||||
}
|
||||
});
|
||||
336
client/components/cards/templates.html
Normal file
336
client/components/cards/templates.html
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
<template name="cardModal">
|
||||
{{ > modal template='cardDetailWindow' card=this board=this.board }}
|
||||
</template>
|
||||
|
||||
<template name="cardMemberPopup">
|
||||
<div class="board-member-menu">
|
||||
<div class="mini-profile-info">
|
||||
{{> userAvatar user=user }}
|
||||
<div class="info">
|
||||
<h3 class="bottom" style="margin-right: 40px;">
|
||||
<a class="js-profile" href="{{ pathFor route='Profile' username=user.username }}">{{ user.profile.name }}</a>
|
||||
</h3>
|
||||
<p class="quiet bottom">@{{ user.username }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{# if currentUser.isBoardMember }}
|
||||
<ul class="pop-over-list">
|
||||
<li><a class="js-remove-member">{{_ 'remove-member-from-card'}}</a></li>
|
||||
</ul>
|
||||
{{/ if }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="cardMorePopup">
|
||||
<p class="quiet bottom">
|
||||
<span class="clearfix">
|
||||
<span>{{_ 'link-card'}}</span>
|
||||
<span class="icon-sm fa {{#if card.board.isPublic}}fa-globe{{else}}fa-lock{{/if}}"></span>
|
||||
<input class="js-url js-autoselect inline-input" type="text" readonly="readonly" value="{{ card.rootUrl }}">
|
||||
</span>
|
||||
{{_ 'added'}} <span class="date" title="{{ card.createdAt }}">{{ moment card.createdAt 'LLL' }}</span> -
|
||||
<a class="js-delete" href="#" title="{{_ 'card-delete-notice'}}">{{_ 'delete'}}</a>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template name="cardLabelsPopup">
|
||||
<div>
|
||||
{{! <input id="labelSearch" name="search" class="js-autofocus js-label-search" placeholder="Search labels…" value="" type="text"> }}
|
||||
<ul class="edit-labels-pop-over js-labels-list">
|
||||
{{# each card.board.labels }}
|
||||
<li>
|
||||
<a href="#" class="card-label-edit-button icon-sm fa fa-pencil js-edit-label"></a>
|
||||
<span class="card-label card-label-selectable card-label-{{color}} js-select-label {{# if isLabelSelected ../card._id }}active{{/ if }}">
|
||||
{{name}}
|
||||
{{# if currentUser.isBoardAdmin }}
|
||||
<span class="card-label-selectable-icon icon-sm fa fa-check light"></span>
|
||||
{{/ if }}
|
||||
</span>
|
||||
</li>
|
||||
{{/ each}}
|
||||
</ul>
|
||||
<a class="quiet-button full js-add-label">{{_ 'label-create'}}</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="cardAttachmentsPopup">
|
||||
<div>
|
||||
<ul class="pop-over-list">
|
||||
<li>
|
||||
<input type="file" name="file" class="js-attach-file hide" multiple>
|
||||
<a class="js-computer-upload" href="#">
|
||||
{{_ 'computer'}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="formLabel">
|
||||
<div class="colors clearfix">
|
||||
<label for="labelName">{{_ 'name'}}</label>
|
||||
<input id="labelName" type="text" name="name" class="js-label-name" value='{{ name }}' autofocus>
|
||||
<label>{{_ "select-color"}}</label>
|
||||
{{# each labels }}
|
||||
<span class="card-label card-label--selectable card-label-{{ color }} palette-color js-palette-color">
|
||||
<span class="card-label-color-select-icon icon-sm fa fa-check light js-palette-select {{#if $neq color ../color}}hide{{/if}}"></span>
|
||||
</span>
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="createLabelPopup">
|
||||
<form class="create-label">
|
||||
{{#with color=defaultColor}}
|
||||
{{> formLabel}}
|
||||
{{/with}}
|
||||
<input type="submit" class="primary wide left" value="{{_ 'create'}}">
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<template name="editLabelPopup">
|
||||
<form class="edit-label">
|
||||
{{> formLabel}}
|
||||
<input type="submit" class="primary wide left" value="{{_ 'save'}}">
|
||||
<span class="right">
|
||||
<input type="submit" value="{{_ 'delete'}}" class="negate js-delete-label">
|
||||
</span>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<template name="deleteLabelPopup">
|
||||
<p>{{_ "label-delete-pop"}}</p>
|
||||
<input type="submit" class="js-confirm negate full" value="{{_ 'delete'}}">
|
||||
</template>
|
||||
|
||||
<template name="cardDeletePopup">
|
||||
<p>{{_ "card-delete-pop"}}</p>
|
||||
<input type="submit" class="js-confirm negate full" value="{{_ 'delete'}}">
|
||||
</template>
|
||||
|
||||
<template name="attachmentDeletePopup">
|
||||
<p>{{_ "attachment-delete-pop"}}</p>
|
||||
<input type="submit" class="js-confirm negate full" value="{{_ 'delete'}}">
|
||||
</template>
|
||||
|
||||
<template name="cardDetailSidebarOld">
|
||||
<div class="card-detail-window clearfix">
|
||||
{{# if card.cover }}
|
||||
<div class="window-cover js-card-cover-box js-open-card-cover-in-viewer has-cover" style="background-image: url({{ card.cover.url }}); background-color: rgb(119, 119, 119); background-size: contain;">
|
||||
</div>
|
||||
{{ /if }}
|
||||
{{ #if card.archived }}
|
||||
<div class="window-archive-banner js-archive-banner">
|
||||
<span class="icon-lg fa fa-archive window-archive-banner-icon"></span>
|
||||
<p class="window-archive-banner-text">{{_ "card-archived"}}</p>
|
||||
</div>
|
||||
{{ /if }}
|
||||
<div class="window-header clearfix">
|
||||
<span class="window-header-icon icon-lg fa fa-calendar-o"></span>
|
||||
<div class="window-title card-detail-title non-empty inline {{# if currentUser.isBoardMember }}editable{{/ if }}">
|
||||
<h2 class="window-title-text current hide-on-edit js-card-title">{{ card.title }}</h2>
|
||||
<div class="edit edit-heavy">
|
||||
<form id="WindowTitleEdit">
|
||||
<textarea type="text" class="field single-line" id="title">{{ card.title }}</textarea>
|
||||
<div class="edit-controls clearfix">
|
||||
<input type="submit" class="primary confirm js-title-save-edit" value="{{_ 'save'}}">
|
||||
<a href="#" class="icon-lg fa fa-times dark-hover cancel js-cancel-edit"></a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="quiet hide-on-edit window-header-inline-content js-current-list">
|
||||
<p class="inline-block bottom">
|
||||
{{_ 'in-list'}}
|
||||
<a href="#" class="{{# if currentUser.isBoardMember }}js-open-move-from-header{{else}}disabled{{/ if }}"><strong>{{ card.list.title }}</strong></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="window-main-col clearfix">
|
||||
<div class="card-detail-data gutter clearfix">
|
||||
<div class="card-detail-item card-detail-item-block clear clearfix editable">
|
||||
{{# if card.members }}
|
||||
<div class="card-detail-item card-detail-item-members clearfix js-card-detail-members">
|
||||
<h3 class="card-detail-item-header">{{_ 'members'}}</h3>
|
||||
<div class="js-card-detail-members-list clearfix">
|
||||
{{# each card.members }}
|
||||
{{> userAvatar userId=this size="small" cardId=../card._id }}
|
||||
{{/ each }}
|
||||
<a class="card-detail-item-add-button dark-hover js-details-edit-members">
|
||||
<span class="icon-sm fa fa-plus"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/ if }}
|
||||
{{# if card.labels }}
|
||||
<div class="card-detail-item card-detail-item-labels clearfix js-card-detail-labels">
|
||||
<h3 class="card-detail-item-header">{{_ 'labels'}}</h3>
|
||||
<div class="js-card-detail-labels-list clearfix editable-labels js-edit-label">
|
||||
{{# each card.labels }}
|
||||
<span class="card-label card-label-{{color}}" title="{{name}}">{{ name }}</span>
|
||||
{{/ each }}
|
||||
<a class="card-detail-item-add-button dark-hover js-details-edit-labels">
|
||||
<span class="icon-sm fa fa-plus"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{{/ if }}
|
||||
<div class="card-detail-item card-detail-item-block clear clearfix editable" attr="desc">
|
||||
{{# if card.description }}
|
||||
<h3 class="card-detail-item-header js-show-with-desc">{{_ 'description'}}</h3>
|
||||
{{# if currentUser.isBoardMember }}
|
||||
<a href="#" class="card-detail-item-header-edit hide-on-edit js-show-with-desc js-edit-desc">{{_ 'edit'}}</a>
|
||||
{{/ if }}
|
||||
<div class="current markeddown hide-on-edit js-card-desc js-show-with-desc">
|
||||
{{#viewer}}{{ card.description }}{{/viewer}}
|
||||
</div>
|
||||
{{ else }}
|
||||
{{# if currentUser.isBoardMember }}
|
||||
<p class="bottom">
|
||||
<a href="#" class="hide-on-edit quiet-button w-img js-edit-desc js-hide-with-desc">
|
||||
<span class="icon-sm fa fa-align-left"></span>
|
||||
{{_ 'edit-description'}}
|
||||
</a>
|
||||
</p>
|
||||
{{/ if }}
|
||||
{{/ if }}
|
||||
<div class="card-detail-edit edit">
|
||||
<form id="WindowDescEdit">
|
||||
{{#editor class="field single-line2" id="desc"}}{{ card.description }}{{/editor}}
|
||||
<div class="edit-controls clearfix">
|
||||
<input type="submit" class="primary confirm js-title-save-edit" value="{{_ 'save'}}">
|
||||
<a href="#" class="icon-lg fa fa-times dark-hover cancel js-cancel-edit"></a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{# if card.attachments.count }}
|
||||
{{ > WindowAttachmentsModule card=card }}
|
||||
{{/ if}}
|
||||
{{ > WindowActivityModule card=card }}
|
||||
</div>
|
||||
{{# if currentUser.isBoardMember }}
|
||||
{{ > WindowSidebarModule card=card }}
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="WindowActivityModule">
|
||||
<div class="card-detailwindow-module">
|
||||
<div class="window-module-title window-module-title-no-divider">
|
||||
<span class="window-module-title-icon icon-lg fa fa-comments-o"></span>
|
||||
<h3>{{ _ 'activity'}}</h3>
|
||||
</div>
|
||||
{{# if currentUser.isBoardMember }}
|
||||
<div class="new-comment js-new-comment">
|
||||
{{> userAvatar user=currentUser size="small" class="member-no-menu" }}
|
||||
<form id="CommentForm">
|
||||
{{#editor class="new-comment-input js-new-comment-input"}}{{/editor}}
|
||||
<div class="add-controls clearfix">
|
||||
<input type="submit" class="primary confirm clear js-add-comment" value="{{_ 'comment'}}" tabindex="2">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{/ if }}
|
||||
{{ > activities mode="card" }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="WindowAttachmentsModule">
|
||||
<div class="window-module js-attachments-section clearfix">
|
||||
<div class="window-module-title window-module-title-no-divider">
|
||||
<span class="window-module-title-icon icon-lg fa fa-paperclip"></span>
|
||||
<h3 class="inline-block">{{_ 'attachments'}}</h3>
|
||||
</div>
|
||||
<div class="gutter">
|
||||
<div class="clearfix js-attachment-list">
|
||||
{{# each card.attachments }}
|
||||
<div class="attachment-thumbnail">
|
||||
{{# if isUploaded }}
|
||||
<a href="{{ url download=true }}" class="attachment-thumbnail-preview js-open-viewer attachment-thumbnail-preview-is-cover">
|
||||
{{# if isImage }}
|
||||
<img src="{{ url }}">
|
||||
{{ else }}
|
||||
<span class="attachment-thumbnail-preview-ext">{{ extension }}</span>
|
||||
{{ /if }}
|
||||
</a>
|
||||
<p class="attachment-thumbnail-details js-open-viewer">
|
||||
<a href="" class="attachment-thumbnail-details-title js-attachment-thumbnail-details">
|
||||
{{ name }}
|
||||
<span class="block quiet">
|
||||
{{_ 'added'}} <span class="date">{{ moment uploadedAt }}</span>
|
||||
</span>
|
||||
</a>
|
||||
<span class="quiet attachment-thumbnail-details-options">
|
||||
<a href="{{ url download=true }}" class="attachment-thumbnail-details-options-item dark-hover js-download">
|
||||
<span class="icon-sm fa fa-download"></span>
|
||||
<span class="attachment-thumbnail-details-options-item-text">{{_ 'download'}}</span>
|
||||
</a>
|
||||
{{# if isImage }}
|
||||
<a class="attachment-thumbnail-details-options-item dark-hover {{#if $eq ../card.coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}">
|
||||
<span class="icon-sm fa fa-thumb-tack"></span>
|
||||
<span class="attachment-thumbnail-details-options-item-text">{{#if $eq ../card.coverId _id}}{{_ 'remove-cover'}}{{else}}{{_ 'add-cover'}}{{/if}}</span>
|
||||
</a>
|
||||
{{/if}}
|
||||
<a href="#" class="attachment-thumbnail-details-options-item attachment-thumbnail-details-options-item-delete dark-hover js-confirm-delete">
|
||||
<span class="icon-sm fa fa-close"></span>
|
||||
<span class="attachment-thumbnail-details-options-item-text">{{_ 'delete'}}</span>
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
{{ else }}
|
||||
+spinner
|
||||
{{/ if }}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<p>
|
||||
<a href="#" class="quiet-button js-attach">{{_ 'add-attachment' }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="WindowSidebarModule">
|
||||
<div class="window-sidebar" style="position: relative;">
|
||||
<div class="window-module clearfix">
|
||||
<h3>{{_ 'add'}}</h3>
|
||||
<div class="clearfix">
|
||||
<a href="#" class="button-link js-change-card-members" title="{{_ 'members-title'}}">
|
||||
<span class="icon-sm fa fa-user"></span> {{_ 'members'}}
|
||||
</a>
|
||||
<a href="#" class="button-link js-edit-labels" title="{{_ 'labels-title'}}">
|
||||
<span class="icon-sm fa fa-tags"></span> {{_ 'labels'}}
|
||||
</a>
|
||||
<a href="#" class="button-link js-attach" title="{{_ 'attachment-title'}}">
|
||||
<span class="icon-sm fa fa-paperclip"></span> {{_ 'attachment'}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="window-module other-actions clearfix">
|
||||
<h3>{{_ 'actions'}}</h3>
|
||||
<div class="clearfix">
|
||||
<hr>
|
||||
{{ #if card.archived }}
|
||||
<a href="#" class="button-link js-unarchive-card" title="{{_ 'send-to-board-title'}}">
|
||||
<span class="icon-sm fa fa-recycle"></span> {{_ 'send-to-board'}}
|
||||
</a>
|
||||
<a href="#" class="button-link negate js-delete-card" title="{{_ 'delete-title'}}">
|
||||
<span class="icon-sm fa fa-trash-o"></span> {{_ 'delete'}}
|
||||
</a>
|
||||
{{ else }}
|
||||
<a href="#" class="button-link js-archive-card" title="{{_ 'archive-title'}}">
|
||||
<span class="icon-sm fa fa-archive"></span> {{_ 'archive'}}
|
||||
</a>
|
||||
{{ /if }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="window-module clearfix">
|
||||
<p class="quiet bottom">
|
||||
<a href="#" class="quiet-button js-more-menu" title="{{_ 'share-and-more-title'}}">{{_ 'share-and-more'}}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Loading…
Add table
Add a link
Reference in a new issue