commit
2a46431b3f
|
@ -21,9 +21,6 @@
|
|||
|
||||
taiga = @.taiga
|
||||
|
||||
trim = @.taiga.trim
|
||||
typeIsArray = @.taiga.typeIsArray
|
||||
|
||||
module = angular.module("taigaCommon", [])
|
||||
|
||||
#############################################################################
|
||||
|
@ -31,19 +28,15 @@ module = angular.module("taigaCommon", [])
|
|||
#############################################################################
|
||||
|
||||
CheckPermissionDirective = ->
|
||||
showElementIfPermission = (element, permission, project) ->
|
||||
element.show() if project.my_permissions.indexOf(permission) > -1
|
||||
render = ($el, project, permission) ->
|
||||
$el.show() if project.my_permissions.indexOf(permission) > -1
|
||||
|
||||
link = ($scope, $el, $attrs) ->
|
||||
$el.hide()
|
||||
permission = $attrs.tgCheckPermission
|
||||
|
||||
#Sometimes this directive from a self included html template
|
||||
if $scope.project?
|
||||
showElementIfPermission($el, permission, $scope.project)
|
||||
|
||||
$scope.$on "project:loaded", (ctx, project) ->
|
||||
showElementIfPermission($el, permission, project)
|
||||
$scope.$watch "project", (project) ->
|
||||
render($el, project, permission) if project?
|
||||
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
|
|
@ -21,22 +21,189 @@
|
|||
|
||||
taiga = @.taiga
|
||||
sizeFormat = @.taiga.sizeFormat
|
||||
bindOnce = @.taiga.bindOnce
|
||||
|
||||
module = angular.module("taigaCommon")
|
||||
|
||||
|
||||
#############################################################################
|
||||
## Attachments Directive
|
||||
#############################################################################
|
||||
class AttachmentsController extends taiga.Controller
|
||||
@.$inject = ["$scope", "$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", "$q"]
|
||||
|
||||
AttachmentsDirective = ($repo, $rs, $confirm) ->
|
||||
link = ($scope, $el, $attrs, $model) ->
|
||||
$ctrl = $el.controller()
|
||||
$scope.uploadingFiles = []
|
||||
constructor: (@scope, @rootscope, @repo, @rs, @confirm, @q) ->
|
||||
_.bindAll(@)
|
||||
@.type = null
|
||||
@.objectId = null
|
||||
|
||||
@.uploadingAttachments = []
|
||||
@.attachments = []
|
||||
@.attachmentsCount = 0
|
||||
@.deprecatedAttachmentsCount = 0
|
||||
@.showDeprecated = false
|
||||
|
||||
initialize: (type, objectId) ->
|
||||
@.type = type
|
||||
@.objectId = objectId
|
||||
|
||||
loadAttachments: ->
|
||||
urlname = "attachments/#{@.type}"
|
||||
id = @.objectId
|
||||
|
||||
return @rs.attachments.list(urlname, id).then (attachments) =>
|
||||
@.attachments = _.sortBy(attachments, "order")
|
||||
@.updateCounters()
|
||||
return attachments
|
||||
|
||||
updateCounters: ->
|
||||
@.attachmentsCount = @.attachments.length
|
||||
@.deprecatedAttachmentsCount = _.filter(@.attachments, {is_deprecated: true}).length
|
||||
|
||||
_createAttachment: (attachment) ->
|
||||
projectId = @scope.projectId
|
||||
urlName = "attachments/#{@.type}"
|
||||
|
||||
promise = @rs.attachments.create(urlName, projectId, @.objectId, attachment)
|
||||
promise = promise.then (data) =>
|
||||
data.isCreatedRightNow = true
|
||||
|
||||
index = @.uploadingAttachments.indexOf(attachment)
|
||||
@.uploadingAttachments.splice(index, 1)
|
||||
@.attachments.push(data)
|
||||
@rootscope.$broadcast("attachment:create")
|
||||
|
||||
promise = promise.then null, (data) ->
|
||||
index = @.uploadingAttachments.indexOf(attachment)
|
||||
@.uploadingAttachments.splice(index, 1)
|
||||
@confirm.notify("error", null, "We have not been able to upload '#{attachment.name}'.")
|
||||
return @q.reject(data)
|
||||
|
||||
return promise
|
||||
|
||||
# Create attachments in bulk
|
||||
createAttachments: (attachments) ->
|
||||
promises = _.map(attachments, (x) => @._createAttachment(x))
|
||||
return @q.all.apply(null, promises).then =>
|
||||
@.updateCounters()
|
||||
|
||||
# Add uploading attachment tracking.
|
||||
addUploadingAttachments: (attachments) ->
|
||||
@.uploadingAttachments = _.union(@.uploadingAttachments, attachments)
|
||||
|
||||
# Change order of attachment in a ordered list.
|
||||
# This function is mainly executed after sortable ends.
|
||||
reorderAttachment: (attachment, newIndex) ->
|
||||
oldIndex = @.attachments.indexOf(attachment)
|
||||
return if oldIndex == newIndex
|
||||
|
||||
@.attachments.splice(oldIndex, 1)
|
||||
@.attachments.splice(newIndex, 0, attachment)
|
||||
|
||||
_.each(@.attachments, (x,i) -> x.order = i+1)
|
||||
|
||||
# Persist one concrete attachment.
|
||||
# This function is mainly used when user clicks
|
||||
# to save button for save one unique attachment.
|
||||
updateAttachment: (attachment) ->
|
||||
onSuccess = =>
|
||||
@.updateCounters()
|
||||
@rootscope.$broadcast("attachment:edit")
|
||||
|
||||
onError = =>
|
||||
@confirm.notify("error")
|
||||
return @q.reject()
|
||||
|
||||
return @repo.save(attachment).then(onSuccess, onError)
|
||||
|
||||
# Persist all pending modifications on attachments.
|
||||
# This function is used mainly for persist the order
|
||||
# after sorting.
|
||||
saveAttachments: ->
|
||||
return @repo.saveAll(@.attachments).then null, =>
|
||||
for item in @.attachments
|
||||
item.revert()
|
||||
@.attachments = _.sorBy(@.attachments, "order")
|
||||
|
||||
# Remove one concrete attachment.
|
||||
removeAttachment: (attachment) ->
|
||||
title = "Delete attachment" #TODO: i18in
|
||||
subtitle = "the attachment '#{attachment.name}'" #TODO: i18in
|
||||
|
||||
onSuccess = =>
|
||||
index = @.attachments.indexOf(attachment)
|
||||
@.attachments.splice(index, 1)
|
||||
@.updateCounters()
|
||||
@rootscope.$broadcast("attachment:delete")
|
||||
|
||||
onError = =>
|
||||
@confirm.notify("error", null, "We have not been able to delete #{subtitle}.")
|
||||
return @q.reject()
|
||||
|
||||
return @confirm.ask(title, subtitle).then =>
|
||||
return @repo.remove(attachment).then(onSuccess, onError)
|
||||
|
||||
# Function used in template for filter visible attachments
|
||||
filterAttachments: (item) ->
|
||||
if @.showDeprecated
|
||||
return true
|
||||
return not item.is_deprecated
|
||||
|
||||
|
||||
AttachmentsDirective = ($confirm) ->
|
||||
template = _.template("""
|
||||
<section class="attachments">
|
||||
<div class="attachments-header">
|
||||
<h3 class="attachments-title">
|
||||
<span class="icon icon-attachments"></span>
|
||||
<span class="attachments-num" tg-bind-html="ctrl.attachmentsCount"></span>
|
||||
<span class="attachments-text">attachments</span>
|
||||
|
||||
<div tg-check-permission="modify_<%- type %>"
|
||||
title="Add new attachment" class="button button-gray add-attach">
|
||||
<span>+new file</span>
|
||||
<input type="file" multiple="multiple"/>
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="attachment-body sortable">
|
||||
<div ng-repeat="attach in ctrl.attachments|filter:ctrl.filterAttachments track by attach.id"
|
||||
tg-attachment="attach"
|
||||
class="single-attachment">
|
||||
</div>
|
||||
|
||||
<div ng-repeat="file in ctrl.uploadingAttachments" class="single-attachment">
|
||||
<div class="attachment-name">
|
||||
<a href="" tg-bo-title="file.name" tg-bo-bind="file.name"></a>
|
||||
</div>
|
||||
<div class="attachment-size">
|
||||
<span tg-bo-bind="file.size" class="attachment-size"></span>
|
||||
</div>
|
||||
<div class="attachment-comments">
|
||||
<span ng-bind="file.progressMessage"></span>
|
||||
<div ng-style="{'width': file.progressPercent}" class="percentage"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="" title="show deprecated atachments" class="more-attachments"
|
||||
ng-if="ctrl.deprecatedAttachmentsCount > 0">
|
||||
<span class="text" data-type="show">+ show deprecated atachments</span>
|
||||
<span class="text hidden" data-type="hide">- hide deprecated atachments</span>
|
||||
<span class="more-attachments-num">
|
||||
({{ctrl.deprecatedAttachmentsCount }} deprecated)
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>""")
|
||||
|
||||
|
||||
link = ($scope, $el, $attrs, $ctrls) ->
|
||||
$ctrl = $ctrls[0]
|
||||
$model = $ctrls[1]
|
||||
|
||||
bindOnce $scope, $attrs.ngModel, (value) ->
|
||||
$ctrl.initialize($attrs.type, value.id)
|
||||
$ctrl.loadAttachments()
|
||||
|
||||
## Drag & drop
|
||||
tdom = $el.find("div.attachment-body.sortable")
|
||||
|
||||
tdom.sortable({
|
||||
items: "div.single-attachment"
|
||||
handle: "a.settings.icon.icon-drag-v"
|
||||
|
@ -49,101 +216,58 @@ AttachmentsDirective = ($repo, $rs, $confirm) ->
|
|||
tdom.on "sortstop", (event, ui) ->
|
||||
attachment = ui.item.scope().attach
|
||||
newIndex = ui.item.index()
|
||||
index = $scope.attachments.indexOf(attachment)
|
||||
|
||||
return if index == newIndex
|
||||
$ctrl.reorderAttachment(attachment, newIndex)
|
||||
$ctrl.saveAttachments()
|
||||
|
||||
# Move attachment to newIndex and recalculate order
|
||||
$scope.attachments.splice(index, 1)
|
||||
$scope.attachments.splice(newIndex, 0, attachment)
|
||||
_.forEach $scope.attachments, (attach, idx) ->
|
||||
attach.order = idx+1
|
||||
$el.on "click", "a.add-attach", (event) ->
|
||||
event.preventDefault()
|
||||
$el.find("input.add-attach").trigger("click")
|
||||
|
||||
# Save or revert changes
|
||||
$repo.saveAll($scope.attachments).then null, ->
|
||||
_.forEach $scope.attachments, attach ->
|
||||
attach.revert()
|
||||
_.sorBy($scope.attachments, 'order')
|
||||
$el.on "change", "input.add-attach", (event) ->
|
||||
files = _.toArray(event.target.files)
|
||||
return if files.length < 1
|
||||
|
||||
## Total attachments counter
|
||||
$scope.$watch "attachmentsCount", (count) ->
|
||||
$el.find("span.attachments-num").html(count)
|
||||
$scope.$apply ->
|
||||
$ctrl.addUploadingAttachments(files)
|
||||
$ctrl.createAttachments(files)
|
||||
|
||||
## Show/Hide deprecated attachments
|
||||
$scope.showDeprecatedAttachments = false
|
||||
|
||||
$scope.$watch "deprecatedAttachmentsCount", (deprecatedAttachmentsCount) ->
|
||||
$el.find("span.more-attachments-num").html("(#{deprecatedAttachmentsCount} deprecated)") # TODO: i18n
|
||||
|
||||
if deprecatedAttachmentsCount
|
||||
$el.find("a.more-attachments").removeClass("hidden")
|
||||
else
|
||||
$el.find("a.more-attachments").addClass("hidden")
|
||||
|
||||
$el.on "click", "a.more-attachments", ->
|
||||
$el.on "click", ".more-attachments", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
$scope.showDeprecatedAttachments = not $scope.showDeprecatedAttachments
|
||||
$scope.$apply ->
|
||||
$ctrl.showDeprecated = not $ctrl.showDeprecated
|
||||
|
||||
if $scope.showDeprecatedAttachments
|
||||
target.find("span.text").html("- hide deprecated attachments") # TODO: i18n
|
||||
.prop("title", "hide deprecated attachments") # TODO: i18n
|
||||
$el.find("div.single-attachment.deprecated").removeClass("hidden")
|
||||
target.find("span.text").addClass("hidden")
|
||||
if $ctrl.showDeprecated
|
||||
target.find("span[data-type=hide]").removeClass("hidden")
|
||||
target.find("more-attachments-num").addClass("hidden")
|
||||
else
|
||||
target.find("span.text").html("+ show deprecated attachments") # TODO: i18n
|
||||
.prop("title", "show deprecated attachments") # TODO: i18n
|
||||
$el.find("div.single-attachment.deprecated").addClass("hidden")
|
||||
target.find("span[data-type=show]").removeClass("hidden")
|
||||
target.find("more-attachments-num").removeClass("hidden")
|
||||
|
||||
$el.on "change", "input.add-attach", ->
|
||||
files = _.map(event.target.files, (x) -> x)
|
||||
return if files.length < 1
|
||||
|
||||
# Add files to uploadingFiles array
|
||||
$scope.$apply =>
|
||||
if not $scope.uploadingFiles or $scope.uploadingFiles.length == 0
|
||||
$scope.uploadingFiles = files
|
||||
else
|
||||
$scope.uploadingFiles = scope.uploadingFiles.concat(files)
|
||||
|
||||
# Upload new files
|
||||
urlName = $ctrl.attachmentsUrlName
|
||||
projectId = $scope.projectId
|
||||
objectId = $model.$modelValue.id
|
||||
|
||||
_.forEach files, (file) ->
|
||||
promise = $rs.attachments.create(urlName, projectId, objectId, file)
|
||||
|
||||
promise.then (data) ->
|
||||
data.isCreatedRightNow = true
|
||||
|
||||
index = $scope.uploadingFiles.indexOf(file)
|
||||
$scope.uploadingFiles.splice(index, 1)
|
||||
$ctrl.onCreateAttachment(data)
|
||||
|
||||
promise.then null, (data) ->
|
||||
index = $scope.uploadingFiles.indexOf(file)
|
||||
$scope.uploadingFiles.splice(index, 1)
|
||||
$confirm.notify("error", null, "We have not been able to upload '#{file.name}'.") #TODO: i18in
|
||||
|
||||
## On destroy
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
||||
templateFn = ($el, $attrs) ->
|
||||
return template({type: $attrs.type})
|
||||
|
||||
return {
|
||||
link: link,
|
||||
require: "ngModel"
|
||||
require: ["tgAttachments", "ngModel"]
|
||||
controller: AttachmentsController
|
||||
controllerAs: "ctrl"
|
||||
restrict: "AE"
|
||||
scope: true
|
||||
link: link
|
||||
template: templateFn
|
||||
}
|
||||
|
||||
module.directive("tgAttachments", ["$tgRepo", "$tgResources", "$tgConfirm", AttachmentsDirective])
|
||||
module.directive("tgAttachments", ["$tgConfirm", AttachmentsDirective])
|
||||
|
||||
|
||||
#############################################################################
|
||||
## Attachment Directive
|
||||
#############################################################################
|
||||
|
||||
AttachmentDirective = ($log, $repo, $confirm) ->
|
||||
singleAttachment = _.template("""
|
||||
AttachmentDirective = ->
|
||||
template = _.template("""
|
||||
<div class="attachment-name">
|
||||
<a href="<%- url %>" title="<%- name %>" target="_blank">
|
||||
<span class="icon icon-documents"></span>
|
||||
|
@ -164,9 +288,9 @@ AttachmentDirective = ($log, $repo, $confirm) ->
|
|||
<a class="settings icon icon-drag-v" href="" title=""Drag"></a>
|
||||
</div>
|
||||
<% } %>
|
||||
""") #TODO: i18n
|
||||
""")
|
||||
|
||||
singleAttachmentEditable = _.template("""
|
||||
templateEdit = _.template("""
|
||||
<div class="attachment-name">
|
||||
<span class="icon.icon-document"></span>
|
||||
<a href="<%- url %>" title="<%- name %>" target="_blank"><%- name %></a>
|
||||
|
@ -188,13 +312,13 @@ AttachmentDirective = ($log, $repo, $confirm) ->
|
|||
<a class="editable-settings icon icon-floppy" href="" title="Save"></a>
|
||||
<a class="editable-settings icon icon-delete" href="" title="Cancel"></a>
|
||||
</div>
|
||||
""") # TODO: i18n
|
||||
""")
|
||||
|
||||
link = ($scope, $el, $attrs) ->
|
||||
$ctrl = $el.controller()
|
||||
link = ($scope, $el, $attrs, $ctrl) ->
|
||||
render = (attachment, edit=false) ->
|
||||
permissions = $scope.project.my_permissions
|
||||
modifyPermission = permissions.indexOf("modify_#{$ctrl.type}") > -1
|
||||
|
||||
render = (attachment, isEditable=false) ->
|
||||
modifyPermission = $scope.project.my_permissions.indexOf("modify_#{$attrs.permissionSuffix}") > -1
|
||||
ctx = {
|
||||
id: attachment.id
|
||||
name: attachment.name
|
||||
|
@ -205,30 +329,29 @@ AttachmentDirective = ($log, $repo, $confirm) ->
|
|||
modifyPermission: modifyPermission
|
||||
}
|
||||
|
||||
if isEditable
|
||||
html = singleAttachmentEditable(ctx)
|
||||
if edit
|
||||
html = templateEdit(ctx)
|
||||
else
|
||||
html = singleAttachment(ctx)
|
||||
html = template(ctx)
|
||||
|
||||
$el.html(html)
|
||||
|
||||
if attachment.is_deprecated
|
||||
$el.addClass("deprecated")
|
||||
if $scope.showDeprecatedAttachments
|
||||
$el.removeClass("hidden")
|
||||
else
|
||||
$el.addClass("hidden")
|
||||
else
|
||||
$el.removeClass("deprecated")
|
||||
$el.removeClass("hidden")
|
||||
|
||||
## Initialize
|
||||
if not $attrs.tgAttachment?
|
||||
return $log.error "AttachmentDirective the directive need an attachment"
|
||||
## Actions (on edit mode)
|
||||
$el.on "click", "a.editable-settings.icon-floppy", (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
attachment = $scope.$eval($attrs.tgAttachment)
|
||||
render(attachment, attachment.isCreatedRightNow)
|
||||
delete attachment.isCreatedRightNow
|
||||
attachment.description = $el.find("input[name='description']").val()
|
||||
attachment.is_deprecated = $el.find("input[name='is-deprecated']").prop("checked")
|
||||
|
||||
$scope.$apply ->
|
||||
$ctrl.updateAttachment(attachment).then ->
|
||||
render(attachment)
|
||||
|
||||
$el.on "click", "a.editable-settings.icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
render(attachment, false)
|
||||
|
||||
## Actions (on view mode)
|
||||
$el.on "click", "a.settings.icon-edit", (event) ->
|
||||
|
@ -237,49 +360,20 @@ AttachmentDirective = ($log, $repo, $confirm) ->
|
|||
|
||||
$el.on "click", "a.settings.icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
$scope.$apply ->
|
||||
$ctrl.removeAttachment(attachment)
|
||||
|
||||
title = "Delete attachment" #TODO: i18in
|
||||
subtitle = "the attachment '#{attachment.name}'" #TODO: i18in
|
||||
|
||||
onSuccess = ->
|
||||
$ctrl.onDeleteAttachment(attachment)
|
||||
|
||||
onError = ->
|
||||
$confirm.notify("error", null, "We have not been able to delete #{subtitle}.") #TODO: i18in
|
||||
|
||||
$confirm.ask(title, subtitle).then ->
|
||||
$repo.remove(attachment).then(onSuccess, onError)
|
||||
|
||||
## Actions (on edit mode)
|
||||
$el.on "click", "a.editable-settings.icon-floppy", (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
newDescription = $el.find("input[name='description']").val()
|
||||
newIsDeprecated = $el.find("input[name='is-deprecated']").prop("checked")
|
||||
|
||||
if newDescription != attachment.description
|
||||
attachment.description = newDescription
|
||||
if newIsDeprecated != attachment.is_deprecated
|
||||
attachment.is_deprecated = newIsDeprecated
|
||||
|
||||
onSuccess = ->
|
||||
$ctrl.onEditAttachment(attachment)
|
||||
render(attachment)
|
||||
|
||||
onError = ->
|
||||
$confirm.notify("error")
|
||||
|
||||
$repo.save(attachment).then(onSuccess, onError)
|
||||
|
||||
$el.on "click", "a.editable-settings.icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
render(attachment)
|
||||
|
||||
## On destroy
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
||||
return {link: link}
|
||||
# Bootstrap
|
||||
attachment = $scope.$eval($attrs.tgAttachment)
|
||||
render(attachment, attachment.isCreatedRightNow)
|
||||
|
||||
module.directive("tgAttachment", ["$log", "$tgRepo", "$tgConfirm",
|
||||
AttachmentDirective])
|
||||
return {
|
||||
link: link
|
||||
require: "^tgAttachments"
|
||||
restrict: "AE"
|
||||
}
|
||||
|
||||
module.directive("tgAttachment", AttachmentDirective)
|
||||
|
|
|
@ -102,44 +102,3 @@ class FiltersMixin
|
|||
location.search(name, value)
|
||||
|
||||
taiga.FiltersMixin = FiltersMixin
|
||||
|
||||
|
||||
#############################################################################
|
||||
## Attachments Mixin
|
||||
#############################################################################
|
||||
# This mixin requires @rs ($tgResources), @scope and @log ($tgLog)
|
||||
# The mixin required @..attachmentsUrlName (p.e. 'issues/attachments',see resources.coffee)
|
||||
|
||||
class AttachmentsMixin
|
||||
loadAttachments: (objectId) ->
|
||||
if not @.attachmentsUrlName
|
||||
return @log.error "AttachmentsMixin: @.attachmentsUrlName is required"
|
||||
|
||||
@scope.attachmentsCount = 0
|
||||
@scope.deprecatedAttachmentsCount = 0
|
||||
|
||||
return @rs.attachments.list(@.attachmentsUrlName, objectId).then (attachments) =>
|
||||
@scope.attachments = _.sortBy(attachments, "order")
|
||||
@.updateAttachmentsCounters()
|
||||
return attachments
|
||||
|
||||
updateAttachmentsCounters: ->
|
||||
@scope.attachmentsCount = @scope.attachments.length
|
||||
@scope.deprecatedAttachmentsCount = _.filter(@scope.attachments, is_deprecated: true).length
|
||||
|
||||
onCreateAttachment: (attachment) ->
|
||||
@scope.attachments[@scope.attachments.length] = attachment
|
||||
@.updateAttachmentsCounters()
|
||||
@scope.$emit("attachment:create")
|
||||
|
||||
onEditAttachment: (attachment) ->
|
||||
@.updateAttachmentsCounters()
|
||||
@scope.$emit("attachment:edit")
|
||||
|
||||
onDeleteAttachment: (attachment) ->
|
||||
index = @scope.attachments.indexOf(attachment)
|
||||
@scope.attachments.splice(index, 1)
|
||||
@.updateAttachmentsCounters()
|
||||
@scope.$emit("attachment:delete")
|
||||
|
||||
taiga.AttachmentsMixin = AttachmentsMixin
|
||||
|
|
|
@ -33,7 +33,7 @@ module = angular.module("taigaIssues")
|
|||
## Issue Detail Controller
|
||||
#############################################################################
|
||||
|
||||
class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.AttachmentsMixin)
|
||||
class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||
@.$inject = [
|
||||
"$scope",
|
||||
"$rootScope",
|
||||
|
@ -49,8 +49,6 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin, tai
|
|||
]
|
||||
|
||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appTitle, @navUrls) ->
|
||||
@.attachmentsUrlName = "issues/attachments"
|
||||
|
||||
@scope.issueRef = @params.issueref
|
||||
@scope.sectionName = "Issue Details"
|
||||
|
||||
|
@ -118,8 +116,7 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin, tai
|
|||
|
||||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadUsersAndRoles())
|
||||
.then(=> @q.all([@.loadIssue(),
|
||||
@.loadAttachments(@scope.issueId)]))
|
||||
.then(=> @.loadIssue())
|
||||
|
||||
block: ->
|
||||
@rootscope.$broadcast("block", @scope.issue)
|
||||
|
|
|
@ -88,10 +88,10 @@ urls = {
|
|||
"history/wiki": "/api/v1/history/wiki"
|
||||
|
||||
# Attachments
|
||||
"userstories/attachments": "/api/v1/userstories/attachments"
|
||||
"issues/attachments": "/api/v1/issues/attachments"
|
||||
"tasks/attachments": "/api/v1/tasks/attachments"
|
||||
"wiki/attachments": "/api/v1/wiki/attachments"
|
||||
"attachments/us": "/api/v1/userstories/attachments"
|
||||
"attachments/issue": "/api/v1/issues/attachments"
|
||||
"attachments/task": "/api/v1/tasks/attachments"
|
||||
"attachments/wiki_page": "/api/v1/wiki/attachments"
|
||||
}
|
||||
|
||||
# Initialize api urls service
|
||||
|
|
|
@ -30,7 +30,7 @@ module = angular.module("taigaTasks")
|
|||
## Task Detail Controller
|
||||
#############################################################################
|
||||
|
||||
class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.AttachmentsMixin)
|
||||
class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||
@.$inject = [
|
||||
"$scope",
|
||||
"$rootScope",
|
||||
|
@ -46,8 +46,6 @@ class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taig
|
|||
]
|
||||
|
||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appTitle, @navUrls) ->
|
||||
@.attachmentsUrlName = "tasks/attachments"
|
||||
|
||||
@scope.taskRef = @params.taskref
|
||||
@scope.sectionName = "Task Details"
|
||||
|
||||
|
@ -110,7 +108,6 @@ class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taig
|
|||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadUsersAndRoles())
|
||||
.then(=> @.loadTask())
|
||||
.then(=> @.loadAttachments(@scope.taskId))
|
||||
|
||||
block: ->
|
||||
@rootscope.$broadcast("block", @scope.task)
|
||||
|
|
|
@ -31,7 +31,7 @@ module = angular.module("taigaUserStories")
|
|||
## User story Detail Controller
|
||||
#############################################################################
|
||||
|
||||
class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.AttachmentsMixin)
|
||||
class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||
@.$inject = [
|
||||
"$scope",
|
||||
"$rootScope",
|
||||
|
@ -47,7 +47,6 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin,
|
|||
]
|
||||
|
||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appTitle, @navUrls) ->
|
||||
@.attachmentsUrlName = "userstories/attachments"
|
||||
@scope.issueRef = @params.issueref
|
||||
@scope.sectionName = "User Story Details"
|
||||
|
||||
|
@ -114,8 +113,7 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin,
|
|||
|
||||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadUsersAndRoles())
|
||||
.then(=> @q.all([@.loadUs(),
|
||||
@.loadAttachments(@scope.usId)]))
|
||||
.then(=> @.loadUs())
|
||||
|
||||
block: ->
|
||||
@rootscope.$broadcast("block", @scope.us)
|
||||
|
|
|
@ -32,7 +32,7 @@ module = angular.module("taigaWiki")
|
|||
## Wiki Detail Controller
|
||||
#############################################################################
|
||||
|
||||
class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.AttachmentsMixin)
|
||||
class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||
@.$inject = [
|
||||
"$scope",
|
||||
"$rootScope",
|
||||
|
@ -50,7 +50,6 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taig
|
|||
|
||||
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @filter, @log, @appTitle,
|
||||
@navUrls) ->
|
||||
@.attachmentsUrlName = "wiki/attachments"
|
||||
@scope.projectSlug = @params.pslug
|
||||
@scope.wikiSlug = @params.slug
|
||||
@scope.sectionName = "Wiki"
|
||||
|
@ -116,8 +115,7 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin, taig
|
|||
return promise.then(=> @.loadProject())
|
||||
.then(=> @.loadUsersAndRoles())
|
||||
.then(=> @q.all([@.loadWikiLinks(),
|
||||
@.loadWiki(),
|
||||
@.loadAttachments(@scope.wikiId)]))
|
||||
@.loadWiki()]))
|
||||
|
||||
edit: ->
|
||||
ctx = {
|
||||
|
|
|
@ -28,10 +28,7 @@ block content
|
|||
section.us-content
|
||||
textarea(placeholder="Write a description of your issue", ng-model="issue.description", tg-markitup)
|
||||
|
||||
- var attachModel = "issue"
|
||||
- var permissionSuffix = "issue"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="issue", type="issue")
|
||||
tg-history(ng-model="issue", type="issue", mode="edit")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -28,10 +28,7 @@ block content
|
|||
|
||||
section.us-content.wysiwyg(tg-bind-html="issue.description_html")
|
||||
|
||||
- var attachModel = "issue"
|
||||
- var permissionSuffix = "issue"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="issue", type="issue")
|
||||
tg-history(ng-model="issue", type="issue")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -28,10 +28,7 @@ block content
|
|||
section.us-content
|
||||
textarea(placeholder="Write a description of your task", ng-model="task.description", tg-markitup)
|
||||
|
||||
- var attachModel = "task"
|
||||
- var permissionSuffix = "task"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="task", type="task")
|
||||
tg-history(ng-model="task", type="task", mode="edit")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -28,10 +28,7 @@ block content
|
|||
|
||||
section.us-content.wysiwyg(tg-bind-html="task.description_html")
|
||||
|
||||
- var attachModel = "task"
|
||||
- var permissionSuffix = "task"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="task", type="task")
|
||||
tg-history(ng-model="task", type="task")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -28,10 +28,7 @@ block content
|
|||
section.us-content
|
||||
textarea(placeholder="Write a description of your user story", ng-model="us.description", tg-markitup)
|
||||
|
||||
- var attachModel = "us"
|
||||
- var permissionSuffix = "us"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="us", type="us")
|
||||
tg-history(ng-model="us", type="us", mode="edit")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -32,10 +32,7 @@ block content
|
|||
|
||||
include views/modules/related-tasks
|
||||
|
||||
- var attachModel = "us"
|
||||
- var permissionSuffix = "us"
|
||||
include views/modules/attachments
|
||||
|
||||
tg-attachments(ng-model="us", type="us")
|
||||
tg-history(ng-model="us", type="us")
|
||||
|
||||
sidebar.menu-secondary.sidebar
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
//- NOTE: You must to define 'var attachModel' 'var permissionSuffix' with the object model
|
||||
//- that have attachments
|
||||
|
||||
section.attachments(tg-attachments, ng-model=attachModel, ng-if="#{attachModel}.id")
|
||||
div.attachments-header
|
||||
h3.attachments-title
|
||||
span.icon.icon-attachments
|
||||
span.attachments-num 0
|
||||
span.attachments-text attachments
|
||||
div.button.button-gray.add-attach(tg-check-permission="modify_"+permissionSuffix, title="Add new attachment")
|
||||
span +new file
|
||||
input.add-attach(type="file", multiple="multiple")
|
||||
|
||||
div.attachment-body.sortable
|
||||
div.hidden.single-attachment(ng-repeat="attach in attachments",
|
||||
tg-attachment="attach", permission-suffix=permissionSuffix)
|
||||
|
||||
//- See modules/common/attachments.coffee - AttachmentDirective
|
||||
|
||||
div.single-attachment(ng-repeat="file in uploadingFiles")
|
||||
div.attachment-name
|
||||
a(href="", tg-bo-title="file.name", tg-bo-bind="file.name")
|
||||
div.attachment-size
|
||||
span.attachment-size(tg-bo-bind="file.size")
|
||||
div.attachment-comments
|
||||
span(ng-bind="file.progressMessage")
|
||||
div.percentage(ng-style="{'width': file.progressPercent}")
|
||||
|
||||
a.hidden.more-attachments(href="", title="show deprecated atachments")
|
||||
span.text + show deprecated atachments
|
||||
span.more-attachments-num (0 deprecated)
|
|
@ -21,6 +21,4 @@ block content
|
|||
section.wysiwyg
|
||||
textarea(placeholder="Write a your wiki page", ng-model="wiki.content", tg-markitup)
|
||||
|
||||
- var attachModel = "wiki"
|
||||
- var permissionSuffix = "wiki_page"
|
||||
include views/modules/attachments
|
||||
tg-attachments(ng-model="wiki", type="wiki_page")
|
||||
|
|
|
@ -25,6 +25,4 @@ block content
|
|||
|
||||
section.wiki-content.wysiwyg(tg-bind-html="wiki.html")
|
||||
|
||||
- var attachModel = "wiki"
|
||||
- var permissionSuffix = "wiki_page"
|
||||
include views/modules/attachments
|
||||
tg-attachments(ng-model="wiki", type="wiki_page")
|
||||
|
|
|
@ -159,16 +159,19 @@
|
|||
}
|
||||
|
||||
.add-attach {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
input {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
font-size: 99px;
|
||||
height: 120%;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: -5px;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue