refresh attachments when the user drags in a wysiwyg

stable
Juanfran 2016-01-20 10:44:51 +01:00
parent 1393139cf9
commit 7456e84c7e
8 changed files with 459 additions and 279 deletions

View File

@ -627,7 +627,7 @@ module.directive("tgEditableDescription", [
EditableWysiwyg = (attachmentsService) ->
EditableWysiwyg = (attachmentsService, attachmentsFullService) ->
link = ($scope, $el, $attrs, $model) ->
isInEditMode = ->
@ -637,19 +637,11 @@ EditableWysiwyg = (attachmentsService) ->
uploadFile = (file, type) ->
return if !attachmentsService.validate(file)
attachmentsService.upload(
file,
$model.$modelValue.id,
$model.$modelValue.project,
type
).then (result) ->
if taiga.isImage(result.get('name'))
url = '![' + result.get('name') + '](' + result.get('url') + ')'
return attachmentsFullService.addAttachment($model.$modelValue.project, $model.$modelValue.id, type, file).then (result) ->
if taiga.isImage(result.getIn(['file', 'name']))
return '![' + result.getIn(['file', 'name']) + '](' + result.getIn(['file', 'url']) + ')'
else
url = '[' + result.get('name') + '](' + result.get('url') + ')'
return url
return '[' + result.getIn(['file', 'name']) + '](' + result.getIn(['file', 'url']) + ')'
$el.on 'dragover', (e) ->
textarea = $el.find('textarea').focus()
@ -694,7 +686,7 @@ EditableWysiwyg = (attachmentsService) ->
require: "ngModel"
}
module.directive("tgEditableWysiwyg", ["tgAttachmentsService", EditableWysiwyg])
module.directive("tgEditableWysiwyg", ["tgAttachmentsService", "tgAttachmentsFullService", EditableWysiwyg])
#############################################################################

View File

@ -28,21 +28,22 @@ class AttachmentController
@.form.description = @.attachment.getIn(['file', 'description'])
@.form.is_deprecated = @.attachment.get(['file', 'is_deprecated'])
@.loading = false
@.title = @translate.instant("ATTACHMENT.TITLE", {
fileName: @.attachment.get('name'),
date: moment(@.attachment.get('created_date')).format(@translate.instant("ATTACHMENT.DATE"))
})
editMode: (mode) ->
@.attachment = @.attachment.set('editable', mode)
attachment = @.attachment.set('editable', mode)
@.onUpdate({attachment: attachment})
delete: () ->
@.onDelete({attachment: @.attachment})
save: () ->
@.attachment = @.attachment.set('loading', true)
attachment = @.attachment.set('loading', true)
@.onUpdate({attachment: attachment})
attachment = @.attachment.merge({
editable: false,

View File

@ -72,10 +72,18 @@ describe "AttachmentController", ->
attachment : attachment
})
ctrl.editable = false
ctrl.onUpdate = sinon.spy()
onUpdate = sinon.match (value) ->
value = value.attachment.toJS()
return value.editable
, "onUpdate"
ctrl.editMode(true)
expect(ctrl.attachment.get('editable')).to.be.true
expect(ctrl.onUpdate).to.be.calledWith(onUpdate)
it "delete", () ->
attachment = Immutable.fromJS({
@ -119,6 +127,12 @@ describe "AttachmentController", ->
ctrl.onUpdate = sinon.spy()
onUpdateLoading = sinon.match (value) ->
value = value.attachment.toJS()
return value.loading
, "onUpdateLoading"
onUpdate = sinon.match (value) ->
value = value.attachment.toJS()
@ -137,4 +151,5 @@ describe "AttachmentController", ->
attachment = ctrl.attachment.toJS()
expect(ctrl.onUpdate).to.be.calledWith(onUpdateLoading)
expect(ctrl.onUpdate).to.be.calledWith(onUpdate)

View File

@ -21,82 +21,46 @@ sizeFormat = @.taiga.sizeFormat
class AttachmentsFullController
@.$inject = [
"tgAttachmentsService",
"$rootScope",
"$translate",
"$tgConfirm",
"$tgConfig",
"$tgStorage"
"$tgStorage",
"tgAttachmentsFullService"
]
constructor: (@attachmentsService, @rootScope, @translate, @confirm, @config, @storage) ->
@.deprecatedsVisible = false
@.uploadingAttachments = []
constructor: (@translate, @confirm, @config, @storage, @attachmentsFullService) ->
@.mode = @storage.get('attachment-mode', 'list')
@.maxFileSize = @config.get("maxUploadFileSize", null)
@.maxFileSize = sizeFormat(@.maxFileSize) if @.maxFileSize
@.maxFileSizeMsg = if @.maxFileSize then @translate.instant("ATTACHMENT.MAX_UPLOAD_SIZE", {maxFileSize: @.maxFileSize}) else ""
loadAttachments: ->
@attachmentsService.list(@.type, @.objId, @.projectId).then (files) =>
@.attachments = files.map (file) ->
attachment = Immutable.Map()
taiga.defineImmutableProperty @, 'attachments', () => return @attachmentsFullService.attachments
taiga.defineImmutableProperty @, 'deprecatedsCount', () => return @attachmentsFullService.deprecatedsCount
taiga.defineImmutableProperty @, 'attachmentsVisible', () => return @attachmentsFullService.attachmentsVisible
taiga.defineImmutableProperty @, 'deprecatedsVisible', () => return @attachmentsFullService.deprecatedsVisible
return attachment.merge({
loading: false,
editable: false,
file: file
})
uploadingAttachments: () ->
return @attachmentsFullService.uploadingAttachments
@.generate()
addAttachment: (file) ->
editable = (@.mode == 'list')
@attachmentsFullService.addAttachment(@.projectId, @.objId, @.type, file, editable)
setMode: (mode) ->
@.mode = mode
@storage.set('attachment-mode', mode)
generate: () ->
@.deprecatedsCount = @.attachments.count (it) -> it.getIn(['file', 'is_deprecated'])
if @.deprecatedsVisible
@.attachmentsVisible = @.attachments
else
@.attachmentsVisible = @.attachments.filter (it) -> !it.getIn(['file', 'is_deprecated'])
toggleDeprecatedsVisible: () ->
@.deprecatedsVisible = !@.deprecatedsVisible
@.generate()
@attachmentsFullService.toggleDeprecatedsVisible()
addAttachment: (file, editable = true) ->
return new Promise (resolve, reject) =>
if @attachmentsService.validate(file)
@.uploadingAttachments.push(file)
addAttachments: (files) ->
_.forEach files, (file) => @.addAttachment(file)
promise = @attachmentsService.upload(file, @.objId, @.projectId, @.type)
promise.then (file) =>
@.uploadingAttachments = @.uploadingAttachments.filter (uploading) ->
return uploading.name != file.get('name')
attachment = Immutable.Map()
attachment = attachment.merge({
file: file,
editable: editable,
loading: false
})
@.attachments = @.attachments.push(attachment)
@.generate()
@rootScope.$broadcast("attachment:create")
resolve(@.attachments)
else
reject(file)
addAttachments: (files, editable) ->
_.forEach files, (file) => @.addAttachment(file, editable)
loadAttachments: ->
@attachmentsFullService.loadAttachments(@.type, @.objId, @.projectId)
deleteAttachment: (toDeleteAttachment) ->
title = @translate.instant("ATTACHMENT.TITLE_LIGHTBOX_DELETE_ATTACHMENT")
@ -111,40 +75,14 @@ class AttachmentsFullController
@confirm.notify("error", null, message)
askResponse.finish(false)
onSuccess = () =>
@.attachments = @.attachments.filter (attachment) -> attachment != toDeleteAttachment
@.generate()
onSuccess = () => askResponse.finish()
askResponse.finish()
return @attachmentsService.delete(@.type, toDeleteAttachment.getIn(['file', 'id'])).then(onSuccess, onError)
@attachmentsFullService.deleteAttachment(toDeleteAttachment, @.type).then(onSuccess, onError)
reorderAttachment: (attachment, newIndex) ->
oldIndex = @.attachments.findIndex (it) -> it == attachment
return if oldIndex == newIndex
attachments = @.attachments.remove(oldIndex)
attachments = attachments.splice(newIndex, 0, attachment)
attachments = attachments.map (x, i) -> x.setIn(['file', 'order'], i + 1)
promises = attachments.map (attachment) =>
patch = {order: attachment.getIn(['file', 'order'])}
return @attachmentsService.patch(attachment.getIn(['file', 'id']), @.type, patch)
return Promise.all(promises.toJS()).then () =>
@.attachments = attachments
@.generate()
@attachmentsFullService.reorderAttachment(@.type, attachment, newIndex)
updateAttachment: (toUpdateAttachment) ->
index = @.attachments.findIndex (attachment) ->
return attachment.getIn(['file', 'id']) == toUpdateAttachment.getIn(['file', 'id'])
oldAttachment = @.attachments.get(index)
patch = taiga.patch(oldAttachment.get('file'), toUpdateAttachment.get('file'))
return @attachmentsService.patch(toUpdateAttachment.getIn(['file', 'id']), @.type, patch).then () =>
@.attachments = @.attachments.set(index, toUpdateAttachment)
@.generate()
@attachmentsFullService.updateAttachment(toUpdateAttachment, @.type)
angular.module("taigaComponents").controller("AttachmentsFull", AttachmentsFullController)

View File

@ -22,13 +22,6 @@ describe "AttachmentsController", ->
$controller = null
mocks = {}
_mockAttachmentsService = ->
mocks.attachmentsService = {
upload: sinon.stub()
}
$provide.value("tgAttachmentsService", mocks.attachmentsService)
_mockConfirm = ->
mocks.confirm = {}
@ -55,21 +48,20 @@ describe "AttachmentsController", ->
$provide.value("$tgStorage", mocks.storage)
_mockRootScope = ->
mocks.rootScope = {}
_mockAttachmetsFullService = ->
mocks.attachmentsFullService = {}
$provide.value("$rootScope", mocks.rootScope)
$provide.value("tgAttachmentsFullService", mocks.attachmentsFullService)
_mocks = ->
module (_$provide_) ->
$provide = _$provide_
_mockAttachmentsService()
_mockConfirm()
_mockTranslate()
_mockConfig()
_mockStorage()
_mockRootScope()
_mockAttachmetsFullService()
return null
@ -86,100 +78,31 @@ describe "AttachmentsController", ->
_setup()
it "generate, refresh deprecated counter", () ->
attachments = Immutable.fromJS([
{
file: {
is_deprecated: false
}
},
{
file: {
is_deprecated: true
}
},
{
file: {
is_deprecated: true
}
},
{
file: {
is_deprecated: false
}
},
{
file: {
is_deprecated: true
}
}
])
ctrl = $controller("AttachmentsFull")
ctrl.attachments = attachments
ctrl.generate()
expect(ctrl.deprecatedsCount).to.be.equal(3)
it "toggle deprecated visibility", () ->
mocks.attachmentsFullService.toggleDeprecatedsVisible = sinon.spy()
ctrl = $controller("AttachmentsFull")
ctrl.deprecatedsVisible = false
ctrl.generate = sinon.spy()
ctrl.toggleDeprecatedsVisible()
expect(ctrl.deprecatedsVisible).to.be.true
expect(ctrl.generate).to.be.calledOnce
expect(mocks.attachmentsFullService.toggleDeprecatedsVisible).to.be.calledOnce
describe "add attachments", () ->
it "valid attachment", (done) ->
file = Immutable.fromJS({
file: {},
name: 'test',
size: 3000
})
it "add attachment", () ->
mocks.attachmentsFullService.addAttachment = sinon.spy()
mocks.attachmentsService.validate = sinon.stub()
mocks.attachmentsService.validate.withArgs(file).returns(true)
ctrl = $controller("AttachmentsFull")
mocks.attachmentsService.upload = sinon.stub()
mocks.attachmentsService.upload.promise().resolve(file)
file = Immutable.Map()
mocks.rootScope.$broadcast = sinon.spy()
ctrl.projectId = 3
ctrl.objId = 30
ctrl.type = 'us'
ctrl.mode = 'list'
ctrl = $controller("AttachmentsFull")
ctrl.attachments = Immutable.List()
ctrl.addAttachment(file)
ctrl.addAttachment(file).then () ->
expect(mocks.rootScope.$broadcast).have.been.calledWith('attachment:create')
expect(ctrl.attachments.count()).to.be.equal(1)
done()
it "invalid attachment", () ->
file = Immutable.fromJS({
file: {},
name: 'test',
size: 3000
})
mocks.attachmentsService.validate = sinon.stub()
mocks.attachmentsService.validate.withArgs(file).returns(false)
mocks.attachmentsService.upload = sinon.stub()
mocks.attachmentsService.upload.promise().resolve(file)
mocks.rootScope.$broadcast = sinon.spy()
ctrl = $controller("AttachmentsFull")
ctrl.attachments = Immutable.List()
ctrl.addAttachment(file).then null, () ->
expect(ctrl.attachments.count()).to.be.equal(0)
expect(mocks.attachmentsFullService.addAttachment).to.have.been.calledWith(3, 30, 'us', file, true)
it "add attachments", () ->
ctrl = $controller("AttachmentsFull")
@ -199,6 +122,11 @@ describe "AttachmentsController", ->
describe "deleteattachments", () ->
it "success attachment", (done) ->
deleteFile = Immutable.Map()
mocks.attachmentsFullService.deleteAttachment = sinon.stub()
mocks.attachmentsFullService.deleteAttachment.withArgs(deleteFile, 'us').promise().resolve()
askResponse = {
finish: sinon.spy()
}
@ -209,37 +137,20 @@ describe "AttachmentsController", ->
mocks.confirm.askOnDelete = sinon.stub()
mocks.confirm.askOnDelete.withArgs('title', 'message').promise().resolve(askResponse)
mocks.attachmentsService.delete = sinon.stub()
mocks.attachmentsService.delete.withArgs('us', 2).promise().resolve()
ctrl = $controller("AttachmentsFull")
ctrl.type = 'us'
ctrl.generate = sinon.spy()
ctrl.attachments = Immutable.fromJS([
{
file: {id: 1}
},
{
file: {id: 2}
},
{
file: {id: 3}
},
{
file: {id: 4}
}
])
deleteFile = ctrl.attachments.get(1)
ctrl.deleteAttachment(deleteFile).then () ->
expect(ctrl.generate).have.been.calledOnce
expect(ctrl.attachments.size).to.be.equal(3)
expect(askResponse.finish).have.been.calledOnce
done()
it "error attachment", (done) ->
deleteFile = Immutable.Map()
mocks.attachmentsFullService.deleteAttachment = sinon.stub()
mocks.attachmentsFullService.deleteAttachment.withArgs(deleteFile, 'us').promise().reject()
askResponse = {
finish: sinon.spy()
}
@ -253,76 +164,52 @@ describe "AttachmentsController", ->
mocks.confirm.notify = sinon.spy()
mocks.attachmentsService.delete = sinon.stub()
mocks.attachmentsService.delete.promise().reject()
ctrl = $controller("AttachmentsFull")
ctrl.type = 'us'
ctrl.generate = sinon.spy()
ctrl.attachments = Immutable.fromJS([
{
file: {id: 1}
},
{
file: {id: 2}
},
{
file: {id: 3}
},
{
file: {id: 4}
}
])
deleteFile = ctrl.attachments.get(1)
ctrl.deleteAttachment(deleteFile).then () ->
expect(ctrl.attachments.size).to.be.equal(4)
expect(askResponse.finish.withArgs(false)).have.been.calledOnce
expect(mocks.confirm.notify.withArgs('error', null, 'error'))
done()
it "reorder attachments", (done) ->
attachments = Immutable.fromJS([
{file: {id: 0, is_deprecated: false, order: 0}},
{file: {id: 1, is_deprecated: true, order: 1}},
{file: {id: 2, is_deprecated: true, order: 2}},
{file: {id: 3, is_deprecated: false, order: 3}},
{file: {id: 4, is_deprecated: true, order: 4}}
])
mocks.attachmentsService.patch = sinon.stub()
mocks.attachmentsService.patch.promise().resolve()
it "loadAttachments", () ->
mocks.attachmentsFullService.loadAttachments = sinon.spy()
ctrl = $controller("AttachmentsFull")
ctrl.projectId = 3
ctrl.objId = 30
ctrl.type = 'us'
ctrl.attachments = attachments
ctrl.reorderAttachment(attachments.get(1), 0).then () ->
expect(ctrl.attachments.get(0)).to.be.equal(attachments.get(1))
done()
ctrl.loadAttachments()
expect(mocks.attachmentsFullService.loadAttachments).to.have.been.calledWith('us', 30, 3)
it "reorder attachments", () ->
mocks.attachmentsFullService.reorderAttachment = sinon.spy()
ctrl = $controller("AttachmentsFull")
file = Immutable.Map()
ctrl.projectId = 3
ctrl.objId = 30
ctrl.type = 'us'
ctrl.reorderAttachment(file, 5)
expect(mocks.attachmentsFullService.reorderAttachment).to.have.been.calledWith('us', file, 5)
it "update attachment", () ->
attachments = Immutable.fromJS([
{file: {id: 0, is_deprecated: false, order: 0}},
{file: {id: 1, is_deprecated: true, order: 1}},
{file: {id: 2, is_deprecated: true, order: 2}},
{file: {id: 3, is_deprecated: false, order: 3}},
{file: {id: 4, is_deprecated: true, order: 4}}
])
attachment = attachments.get(1)
attachment = attachment.setIn(['file', 'is_deprecated'], false)
mocks.attachmentsService.patch = sinon.stub()
mocks.attachmentsService.patch.withArgs(1, 'us', {is_deprecated: false}).promise().resolve()
mocks.attachmentsFullService.updateAttachment = sinon.spy()
ctrl = $controller("AttachmentsFull")
ctrl.type = 'us'
ctrl.attachments = attachments
file = Immutable.Map()
ctrl.updateAttachment(attachment).then () ->
expect(ctrl.attachments.get(1).toJS()).to.be.eql(attachment.toJS())
ctrl.type = 'us'
ctrl.updateAttachment(file, 5)
expect(mocks.attachmentsFullService.updateAttachment).to.have.been.calledWith(file, 'us')

View File

@ -34,7 +34,8 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files, false)")
multiple="multiple",
tg-file-change="vm.addAttachments(files, true)"
)
.attachments-empty(ng-if="!vm.attachments.size")
.attachments-empty(ng-if="!vm.attachments.size && !vm.uploadingAttachments().length")
div {{'ATTACHMENT.DROP' | translate}}
.attachment-list.sortable(ng-if="vm.mode == 'list'")
div(tg-attachments-sortable="vm.reorderAttachment(attachment, index)")
@ -49,13 +50,13 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files, false)")
type="vm.type"
)
.single-attachment(ng-repeat="file in vm.uploadingAttachments")
.single-attachment(ng-repeat="file in vm.uploadingAttachments()")
.attachment-name
span.icon
include ../../../svg/attachment.svg
span {{attachment.get('name')}}
span {{file.name}}
.attachment-size
span {{attachment.get('size') | sizeFormat}}
span {{file.size | sizeFormat}}
.attachment-comments
span {{file.progressMessage}}
@ -88,7 +89,7 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files, false)")
on-update="vm.updateAttachment(attachment)",
type="vm.type"
)
.single-attachment(ng-repeat="file in vm.uploadingAttachments")
.single-attachment(ng-repeat="file in vm.uploadingAttachments()")
.loading-container
img.loading-spinner(
src="/#{v}/svg/spinner-circle.svg",

View File

@ -0,0 +1,131 @@
###
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: attachments-full.service.coffee
###
class AttachmentsFullService extends taiga.Service
@.$inject = [
"tgAttachmentsService",
"$rootScope"
]
constructor: (@attachmentsService, @rootScope) ->
@._attachments = Immutable.List()
@._deprecatedsCount = 0
@._attachmentsVisible = Immutable.List()
@._deprecatedsVisible = false
@.uploadingAttachments = []
taiga.defineImmutableProperty @, 'attachments', () => return @._attachments
taiga.defineImmutableProperty @, 'deprecatedsCount', () => return @._deprecatedsCount
taiga.defineImmutableProperty @, 'attachmentsVisible', () => return @._attachmentsVisible
taiga.defineImmutableProperty @, 'deprecatedsVisible', () => return @._deprecatedsVisible
toggleDeprecatedsVisible: () ->
@._deprecatedsVisible = !@._deprecatedsVisible
@.regenerate()
regenerate: () ->
@._deprecatedsCount = @._attachments.count (it) -> it.getIn(['file', 'is_deprecated'])
if @._deprecatedsVisible
@._attachmentsVisible = @._attachments
else
@._attachmentsVisible = @._attachments.filter (it) -> !it.getIn(['file', 'is_deprecated'])
addAttachment: (projectId, objId, type, file, editable = true) ->
return new Promise (resolve, reject) =>
if @attachmentsService.validate(file)
@.uploadingAttachments.push(file)
promise = @attachmentsService.upload(file, objId, projectId, type)
promise.then (file) =>
@.uploadingAttachments = @.uploadingAttachments.filter (uploading) ->
return uploading.name != file.get('name')
attachment = Immutable.Map()
attachment = attachment.merge({
file: file,
editable: editable,
loading: false
})
@._attachments = @._attachments.push(attachment)
@.regenerate()
@rootScope.$broadcast("attachment:create")
resolve(attachment)
else
reject(file)
loadAttachments: (type, objId, projectId)->
@attachmentsService.list(type, objId, projectId).then (files) =>
@._attachments = files.map (file) ->
attachment = Immutable.Map()
return attachment.merge({
loading: false,
editable: false,
file: file
})
@.regenerate()
deleteAttachment: (toDeleteAttachment, type) ->
onSuccess = () =>
@._attachments = @._attachments.filter (attachment) -> attachment != toDeleteAttachment
@.regenerate()
return @attachmentsService.delete(type, toDeleteAttachment.getIn(['file', 'id'])).then(onSuccess)
reorderAttachment: (type, attachment, newIndex) ->
oldIndex = @.attachments.findIndex (it) -> it == attachment
return if oldIndex == newIndex
attachments = @.attachments.remove(oldIndex)
attachments = attachments.splice(newIndex, 0, attachment)
attachments = attachments.map (x, i) -> x.setIn(['file', 'order'], i + 1)
promises = []
attachments.forEach (attachment) =>
patch = {order: attachment.getIn(['file', 'order'])}
promises.push @attachmentsService.patch(attachment.getIn(['file', 'id']), type, patch)
return Promise.all(promises).then () =>
@._attachments = attachments
@.regenerate()
updateAttachment: (toUpdateAttachment, type) ->
index = @._attachments.findIndex (attachment) ->
return attachment.getIn(['file', 'id']) == toUpdateAttachment.getIn(['file', 'id'])
oldAttachment = @._attachments.get(index)
patch = taiga.patch(oldAttachment.get('file'), toUpdateAttachment.get('file'))
return @attachmentsService.patch(toUpdateAttachment.getIn(['file', 'id']), type, patch).then () =>
@._attachments = @._attachments.set(index, toUpdateAttachment)
@.regenerate()
angular.module("taigaComponents").service("tgAttachmentsFullService", AttachmentsFullService)

View File

@ -0,0 +1,215 @@
###
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: attchments-full.service.spec.coffee
###
describe "tgAttachmentsFullService", ->
$provide = null
attachmentsFullService = null
mocks = {}
_mockAttachmentsService = ->
mocks.attachmentsService = {
upload: sinon.stub()
}
$provide.value("tgAttachmentsService", mocks.attachmentsService)
_mockRootScope = ->
mocks.rootScope = {}
$provide.value("$rootScope", mocks.rootScope)
_mocks = ->
module (_$provide_) ->
$provide = _$provide_
_mockAttachmentsService()
_mockRootScope()
return null
_inject = ->
inject (_tgAttachmentsFullService_) ->
attachmentsFullService = _tgAttachmentsFullService_
_setup = ->
_mocks()
_inject()
beforeEach ->
module "taigaComponents"
_setup()
it "generate, refresh deprecated counter", () ->
attachments = Immutable.fromJS([
{
file: {
is_deprecated: false
}
},
{
file: {
is_deprecated: true
}
},
{
file: {
is_deprecated: true
}
},
{
file: {
is_deprecated: false
}
},
{
file: {
is_deprecated: true
}
}
])
attachmentsFullService._attachments = attachments
attachmentsFullService.regenerate()
expect(attachmentsFullService._deprecatedsCount).to.be.equal(3)
it "toggle deprecated visibility", () ->
attachmentsFullService._deprecatedsVisible = false
attachmentsFullService.regenerate = sinon.spy()
attachmentsFullService.toggleDeprecatedsVisible()
expect(attachmentsFullService.deprecatedsVisible).to.be.true
expect(attachmentsFullService.regenerate).to.be.calledOnce
describe "add attachments", () ->
it "valid attachment", (done) ->
projectId = 1
objId = 2
type = "issue"
file = Immutable.fromJS({
file: {},
name: 'test',
size: 3000
})
mocks.attachmentsService.validate = sinon.stub()
mocks.attachmentsService.validate.withArgs(file).returns(true)
mocks.attachmentsService.upload = sinon.stub()
mocks.attachmentsService.upload.promise().resolve(file)
mocks.rootScope.$broadcast = sinon.spy()
attachmentsFullService._attachments = Immutable.List()
attachmentsFullService.addAttachment(projectId, objId, type, file).then () ->
expect(mocks.rootScope.$broadcast).have.been.calledWith('attachment:create')
expect(attachmentsFullService.attachments.count()).to.be.equal(1)
done()
it "invalid attachment", () ->
file = Immutable.fromJS({
file: {},
name: 'test',
size: 3000
})
mocks.attachmentsService.validate = sinon.stub()
mocks.attachmentsService.validate.withArgs(file).returns(false)
mocks.attachmentsService.upload = sinon.stub()
mocks.attachmentsService.upload.promise().resolve(file)
mocks.rootScope.$broadcast = sinon.spy()
attachmentsFullService._attachments = Immutable.List()
attachmentsFullService.addAttachment(file).then null, () ->
expect(attachmentsFullService._attachments.count()).to.be.equal(0)
describe "deleteattachments", () ->
it "success attachment", (done) ->
mocks.attachmentsService.delete = sinon.stub()
mocks.attachmentsService.delete.withArgs('us', 2).promise().resolve()
attachmentsFullService.regenerate = sinon.spy()
attachmentsFullService._attachments = Immutable.fromJS([
{
file: {id: 1}
},
{
file: {id: 2}
},
{
file: {id: 3}
},
{
file: {id: 4}
}
])
deleteFile = attachmentsFullService._attachments.get(1)
attachmentsFullService.deleteAttachment(deleteFile, 'us').then () ->
expect(attachmentsFullService.regenerate).have.been.calledOnce
expect(attachmentsFullService.attachments.size).to.be.equal(3)
done()
it "reorder attachments", (done) ->
attachments = Immutable.fromJS([
{file: {id: 0, is_deprecated: false, order: 0}},
{file: {id: 1, is_deprecated: true, order: 1}},
{file: {id: 2, is_deprecated: true, order: 2}},
{file: {id: 3, is_deprecated: false, order: 3}},
{file: {id: 4, is_deprecated: true, order: 4}}
])
mocks.attachmentsService.patch = sinon.stub()
mocks.attachmentsService.patch.promise().resolve()
attachmentsFullService._attachments = attachments
attachmentsFullService.reorderAttachment('us', attachments.get(1), 0).then () ->
expect(attachmentsFullService.attachments.get(0)).to.be.equal(attachments.get(1))
done()
it "update attachment", () ->
attachments = Immutable.fromJS([
{file: {id: 0, is_deprecated: false, order: 0}},
{file: {id: 1, is_deprecated: true, order: 1}},
{file: {id: 2, is_deprecated: true, order: 2}},
{file: {id: 3, is_deprecated: false, order: 3}},
{file: {id: 4, is_deprecated: true, order: 4}}
])
attachment = attachments.get(1)
attachment = attachment.setIn(['file', 'is_deprecated'], false)
mocks.attachmentsService.patch = sinon.stub()
mocks.attachmentsService.patch.withArgs(1, 'us', {is_deprecated: false}).promise().resolve()
attachmentsFullService._attachments = attachments
attachmentsFullService.updateAttachment(attachment, 'us').then () ->
expect(attachmentsFullService.attachments.get(1).toJS()).to.be.eql(attachment.toJS())