attachments image slider
parent
a3345de76d
commit
389582bd1f
|
@ -7,6 +7,7 @@
|
||||||
- Show a confirmation notice when you exit edit mode by pressing ESC in the markdown inputs.
|
- Show a confirmation notice when you exit edit mode by pressing ESC in the markdown inputs.
|
||||||
- Add the tribe button to link stories from tree.taiga.io with gigs in tribe.taiga.io.
|
- Add the tribe button to link stories from tree.taiga.io with gigs in tribe.taiga.io.
|
||||||
- Errors (not found, server error, permissions and blocked project) don't change the current url.
|
- Errors (not found, server error, permissions and blocked project) don't change the current url.
|
||||||
|
- Attachments image slider
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Lots of small and not so small bugfixes.
|
- Lots of small and not so small bugfixes.
|
||||||
|
|
|
@ -395,3 +395,50 @@ Autofocus = ($timeout) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive('tgAutofocus', ['$timeout', Autofocus])
|
module.directive('tgAutofocus', ['$timeout', Autofocus])
|
||||||
|
|
||||||
|
module.directive 'tgPreloadImage', () ->
|
||||||
|
spinner = "<img class='loading-spinner' src='/" + window._version + "/svg/spinner-circle.svg' alt='loading...' />"
|
||||||
|
|
||||||
|
template = """
|
||||||
|
<div>
|
||||||
|
<ng-transclude></ng-transclude>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
preload = (src, onLoad) ->
|
||||||
|
image = new Image()
|
||||||
|
image.onload = onLoad
|
||||||
|
image.src = src
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
return {
|
||||||
|
template: template,
|
||||||
|
transclude: true,
|
||||||
|
replace: true,
|
||||||
|
link: (scope, el, attrs) ->
|
||||||
|
image = el.find('img:last')
|
||||||
|
timeout = null
|
||||||
|
|
||||||
|
onLoad = () ->
|
||||||
|
el.find('.loading-spinner').remove()
|
||||||
|
image.show()
|
||||||
|
|
||||||
|
if timeout
|
||||||
|
clearTimeout(timeout)
|
||||||
|
timeout = null
|
||||||
|
|
||||||
|
attrs.$observe 'preloadSrc', (src) ->
|
||||||
|
if timeout
|
||||||
|
clearTimeout(timeout)
|
||||||
|
|
||||||
|
el.find('.loading-spinner').remove()
|
||||||
|
|
||||||
|
timeout = setTimeout () ->
|
||||||
|
el.prepend(spinner)
|
||||||
|
, 200
|
||||||
|
|
||||||
|
image.hide()
|
||||||
|
|
||||||
|
preload(src, onLoad)
|
||||||
|
}
|
||||||
|
|
|
@ -686,22 +686,6 @@ WatchersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNavigationS
|
||||||
module.directive("tgLbWatchers", ["$tgRepo", "lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", WatchersLightboxDirective])
|
module.directive("tgLbWatchers", ["$tgRepo", "lightboxService", "lightboxKeyboardNavigationService", "$tgTemplate", "$compile", WatchersLightboxDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
## Attachment Preview Lighbox
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
AttachmentPreviewLightboxDirective = (lightboxService, $template, $compile) ->
|
|
||||||
link = ($scope, $el, attrs) ->
|
|
||||||
lightboxService.open($el)
|
|
||||||
|
|
||||||
return {
|
|
||||||
templateUrl: 'common/lightbox/lightbox-attachment-preview.html',
|
|
||||||
link: link,
|
|
||||||
scope: true
|
|
||||||
}
|
|
||||||
|
|
||||||
module.directive("tgLbAttachmentPreview", ["lightboxService", "$tgTemplate", "$compile", AttachmentPreviewLightboxDirective])
|
|
||||||
|
|
||||||
LightboxLeaveProjectWarningDirective = (lightboxService, $template, $compile) ->
|
LightboxLeaveProjectWarningDirective = (lightboxService, $template, $compile) ->
|
||||||
link = ($scope, $el, attrs) ->
|
link = ($scope, $el, attrs) ->
|
||||||
lightboxService.open($el)
|
lightboxService.open($el)
|
||||||
|
|
|
@ -127,6 +127,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachment-preview {
|
.attachment-preview {
|
||||||
|
.attachment-preview-container {
|
||||||
|
svg {
|
||||||
|
@include svg-size(3rem);
|
||||||
|
fill: $gray-light;
|
||||||
|
&:hover {
|
||||||
|
fill: $primary-light;
|
||||||
|
transition: fill .3s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.previous {
|
||||||
|
left: 3rem;
|
||||||
|
position: absolute;
|
||||||
|
top: calc(50% - 3rem);
|
||||||
|
}
|
||||||
|
.next {
|
||||||
|
position: absolute;
|
||||||
|
right: 3rem;
|
||||||
|
top: calc(50% - 3rem);
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
max-width: 80vw;
|
max-width: 80vw;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
# File: attachment-link.directive.coffee
|
# File: attachment-link.directive.coffee
|
||||||
###
|
###
|
||||||
|
|
||||||
AttachmentLinkDirective = ($parse, lightboxFactory) ->
|
AttachmentLinkDirective = ($parse, attachmentsPreviewService, lightboxService) ->
|
||||||
link = (scope, el, attrs) ->
|
link = (scope, el, attrs) ->
|
||||||
attachment = $parse(attrs.tgAttachmentLink)(scope)
|
attachment = $parse(attrs.tgAttachmentLink)(scope)
|
||||||
|
|
||||||
|
@ -26,11 +26,8 @@ AttachmentLinkDirective = ($parse, lightboxFactory) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
scope.$apply ->
|
scope.$apply ->
|
||||||
lightboxFactory.create('tg-lb-attachment-preview', {
|
lightboxService.open($('tg-attachments-preview'))
|
||||||
class: 'lightbox lightbox-block'
|
attachmentsPreviewService.fileId = attachment.getIn(['file', 'id'])
|
||||||
}, {
|
|
||||||
file: attachment.get('file')
|
|
||||||
})
|
|
||||||
|
|
||||||
scope.$on "$destroy", -> el.off()
|
scope.$on "$destroy", -> el.off()
|
||||||
return {
|
return {
|
||||||
|
@ -39,7 +36,8 @@ AttachmentLinkDirective = ($parse, lightboxFactory) ->
|
||||||
|
|
||||||
AttachmentLinkDirective.$inject = [
|
AttachmentLinkDirective.$inject = [
|
||||||
"$parse",
|
"$parse",
|
||||||
"tgLightboxFactory"
|
"tgAttachmentsPreviewService",
|
||||||
|
"lightboxService"
|
||||||
]
|
]
|
||||||
|
|
||||||
angular.module("taigaComponents").directive("tgAttachmentLink", AttachmentLinkDirective)
|
angular.module("taigaComponents").directive("tgAttachmentLink", AttachmentLinkDirective)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
ng-class="{deprecated: vm.attachment.getIn(['file', 'is_deprecated'])}",
|
ng-class="{deprecated: vm.attachment.getIn(['file', 'is_deprecated'])}",
|
||||||
ng-if="vm.attachment.getIn(['file', 'id'])",
|
ng-if="vm.attachment.getIn(['file', 'id'])",
|
||||||
)
|
)
|
||||||
a.attachment-image(
|
a.attachment-image.e2e-attachment-link(
|
||||||
tg-attachment-link="vm.attachment"
|
tg-attachment-link="vm.attachment"
|
||||||
href="{{::vm.attachment.getIn(['file', 'url'])}}"
|
href="{{::vm.attachment.getIn(['file', 'url'])}}"
|
||||||
title="{{::vm.attachment.getIn(['file', 'name'])}}"
|
title="{{::vm.attachment.getIn(['file', 'name'])}}"
|
||||||
|
|
|
@ -5,7 +5,7 @@ form.single-attachment(
|
||||||
)
|
)
|
||||||
|
|
||||||
.attachment-name
|
.attachment-name
|
||||||
a(
|
a.e2e-attachment-link(
|
||||||
tg-attachment-link="vm.attachment"
|
tg-attachment-link="vm.attachment"
|
||||||
href="{{::vm.attachment.getIn(['file', 'url'])}}"
|
href="{{::vm.attachment.getIn(['file', 'url'])}}"
|
||||||
title="{{::vm.attachment.get(['file', 'name'])}}"
|
title="{{::vm.attachment.get(['file', 'name'])}}"
|
||||||
|
|
|
@ -26,10 +26,11 @@ class AttachmentsFullController
|
||||||
"$tgConfig",
|
"$tgConfig",
|
||||||
"$tgStorage",
|
"$tgStorage",
|
||||||
"tgAttachmentsFullService",
|
"tgAttachmentsFullService",
|
||||||
"tgProjectService"
|
"tgProjectService",
|
||||||
|
"tgAttachmentsPreviewService"
|
||||||
]
|
]
|
||||||
|
|
||||||
constructor: (@translate, @confirm, @config, @storage, @attachmentsFullService, @projectService) ->
|
constructor: (@translate, @confirm, @config, @storage, @attachmentsFullService, @projectService, @attachmentsPreviewService) ->
|
||||||
@.mode = @storage.get('attachment-mode', 'list')
|
@.mode = @storage.get('attachment-mode', 'list')
|
||||||
|
|
||||||
@.maxFileSize = @config.get("maxUploadFileSize", null)
|
@.maxFileSize = @config.get("maxUploadFileSize", null)
|
||||||
|
@ -64,6 +65,8 @@ class AttachmentsFullController
|
||||||
@attachmentsFullService.loadAttachments(@.type, @.objId, @.projectId)
|
@attachmentsFullService.loadAttachments(@.type, @.objId, @.projectId)
|
||||||
|
|
||||||
deleteAttachment: (toDeleteAttachment) ->
|
deleteAttachment: (toDeleteAttachment) ->
|
||||||
|
@attachmentsPreviewService.fileId = null
|
||||||
|
|
||||||
title = @translate.instant("ATTACHMENT.TITLE_LIGHTBOX_DELETE_ATTACHMENT")
|
title = @translate.instant("ATTACHMENT.TITLE_LIGHTBOX_DELETE_ATTACHMENT")
|
||||||
message = @translate.instant("ATTACHMENT.MSG_LIGHTBOX_DELETE_ATTACHMENT", {
|
message = @translate.instant("ATTACHMENT.MSG_LIGHTBOX_DELETE_ATTACHMENT", {
|
||||||
fileName: toDeleteAttachment.getIn(['file', 'name'])
|
fileName: toDeleteAttachment.getIn(['file', 'name'])
|
||||||
|
|
|
@ -94,3 +94,8 @@ section.attachments(
|
||||||
alt="{{'COMMON.LOADING' | translate}}"
|
alt="{{'COMMON.LOADING' | translate}}"
|
||||||
)
|
)
|
||||||
.attachment-data {{file.progressMessage}}
|
.attachment-data {{file.progressMessage}}
|
||||||
|
|
||||||
|
tg-attachments-preview.lightbox.lightbox-block(
|
||||||
|
ng-show="vm.showAttachments()",
|
||||||
|
attachments="vm.attachments"
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
###
|
||||||
|
# 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-preview.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class AttachmentsPreviewController
|
||||||
|
@.$inject = [
|
||||||
|
"tgAttachmentsPreviewService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@attachmentsPreviewService) ->
|
||||||
|
taiga.defineImmutableProperty @, "current", () =>
|
||||||
|
if !@attachmentsPreviewService.fileId
|
||||||
|
return null
|
||||||
|
|
||||||
|
return @.getCurrent()
|
||||||
|
|
||||||
|
hasPagination: () ->
|
||||||
|
images = @.attachments.filter (attachment) =>
|
||||||
|
return taiga.isImage(attachment.getIn(['file', 'name']))
|
||||||
|
|
||||||
|
return images.size > 1
|
||||||
|
|
||||||
|
getCurrent: () ->
|
||||||
|
attachment = @.attachments.find (attachment) =>
|
||||||
|
@attachmentsPreviewService.fileId == attachment.getIn(['file', 'id'])
|
||||||
|
|
||||||
|
file = attachment.get('file')
|
||||||
|
|
||||||
|
return file
|
||||||
|
|
||||||
|
getIndex: () ->
|
||||||
|
return @.attachments.findIndex (attachment) =>
|
||||||
|
@attachmentsPreviewService.fileId == attachment.getIn(['file', 'id'])
|
||||||
|
|
||||||
|
next: () ->
|
||||||
|
attachmentIndex = @.getIndex()
|
||||||
|
|
||||||
|
image = @.attachments.slice(attachmentIndex + 1).find (attachment) ->
|
||||||
|
return taiga.isImage(attachment.getIn(['file', 'name']))
|
||||||
|
|
||||||
|
if !image
|
||||||
|
image = @.attachments.find (attachment) ->
|
||||||
|
return taiga.isImage(attachment.getIn(['file', 'name']))
|
||||||
|
|
||||||
|
|
||||||
|
@attachmentsPreviewService.fileId = image.getIn(['file', 'id'])
|
||||||
|
|
||||||
|
previous: () ->
|
||||||
|
attachmentIndex = @.getIndex()
|
||||||
|
|
||||||
|
image = @.attachments.slice(0, attachmentIndex).findLast (attachment) ->
|
||||||
|
return taiga.isImage(attachment.getIn(['file', 'name']))
|
||||||
|
|
||||||
|
if !image
|
||||||
|
image = @.attachments.findLast (attachment) ->
|
||||||
|
return taiga.isImage(attachment.getIn(['file', 'name']))
|
||||||
|
|
||||||
|
@attachmentsPreviewService.fileId = image.getIn(['file', 'id'])
|
||||||
|
|
||||||
|
angular.module('taigaComponents').controller('AttachmentsPreview', AttachmentsPreviewController)
|
|
@ -0,0 +1,346 @@
|
||||||
|
###
|
||||||
|
# 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: attachments-preview.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "AttachmentsPreviewController", ->
|
||||||
|
$provide = null
|
||||||
|
$controller = null
|
||||||
|
scope = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockAttachmentsPreviewService = ->
|
||||||
|
mocks.attachmentsPreviewService = {}
|
||||||
|
|
||||||
|
$provide.value("tgAttachmentsPreviewService", mocks.attachmentsPreviewService)
|
||||||
|
|
||||||
|
_mocks = ->
|
||||||
|
module (_$provide_) ->
|
||||||
|
$provide = _$provide_
|
||||||
|
|
||||||
|
_mockAttachmentsPreviewService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = ->
|
||||||
|
inject (_$controller_, $rootScope) ->
|
||||||
|
$controller = _$controller_
|
||||||
|
scope = $rootScope.$new()
|
||||||
|
|
||||||
|
_setup = ->
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaComponents"
|
||||||
|
|
||||||
|
_setup()
|
||||||
|
|
||||||
|
it "get current file", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 2;
|
||||||
|
|
||||||
|
current = ctrl.getCurrent()
|
||||||
|
|
||||||
|
expect(current.get('id')).to.be.equal(2)
|
||||||
|
expect(ctrl.current.get('id')).to.be.equal(2)
|
||||||
|
|
||||||
|
|
||||||
|
it "has pagination", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.getIndex = sinon.stub().returns(0)
|
||||||
|
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 1;
|
||||||
|
|
||||||
|
pagination = ctrl.hasPagination()
|
||||||
|
|
||||||
|
expect(pagination).to.be.false
|
||||||
|
|
||||||
|
ctrl.attachments = ctrl.attachments.push(Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
id: 4,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
pagination = ctrl.hasPagination()
|
||||||
|
|
||||||
|
expect(pagination).to.be.true
|
||||||
|
|
||||||
|
it "get index", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 2;
|
||||||
|
|
||||||
|
currentIndex = ctrl.getIndex()
|
||||||
|
|
||||||
|
expect(currentIndex).to.be.equal(1)
|
||||||
|
|
||||||
|
it "next", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.getIndex = sinon.stub().returns(0)
|
||||||
|
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 1;
|
||||||
|
|
||||||
|
currentIndex = ctrl.next()
|
||||||
|
|
||||||
|
expect(mocks.attachmentsPreviewService.fileId).to.be.equal(3)
|
||||||
|
|
||||||
|
it "next infinite", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.getIndex = sinon.stub().returns(2)
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 3;
|
||||||
|
|
||||||
|
currentIndex = ctrl.next()
|
||||||
|
|
||||||
|
expect(mocks.attachmentsPreviewService.fileId).to.be.equal(1)
|
||||||
|
|
||||||
|
it "previous", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.getIndex = sinon.stub().returns(2)
|
||||||
|
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 3;
|
||||||
|
|
||||||
|
currentIndex = ctrl.previous()
|
||||||
|
|
||||||
|
expect(mocks.attachmentsPreviewService.fileId).to.be.equal(1)
|
||||||
|
|
||||||
|
it "previous infinite", () ->
|
||||||
|
attachment = Immutable.fromJS({
|
||||||
|
file: {
|
||||||
|
description: 'desc',
|
||||||
|
is_deprecated: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl = $controller("AttachmentsPreview", {
|
||||||
|
$scope: scope
|
||||||
|
})
|
||||||
|
|
||||||
|
ctrl.getIndex = sinon.stub().returns(0)
|
||||||
|
|
||||||
|
ctrl.attachments = Immutable.fromJS([
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 1,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 2,
|
||||||
|
name: "xx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: {
|
||||||
|
id: 3,
|
||||||
|
name: "xx.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
mocks.attachmentsPreviewService.fileId = 1;
|
||||||
|
|
||||||
|
currentIndex = ctrl.previous()
|
||||||
|
|
||||||
|
expect(mocks.attachmentsPreviewService.fileId).to.be.equal(3)
|
|
@ -0,0 +1,48 @@
|
||||||
|
###
|
||||||
|
# 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-preview.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
AttachmentPreviewLightboxDirective = (lightboxService, attachmentsPreviewService) ->
|
||||||
|
link = ($scope, el, attrs, ctrl) ->
|
||||||
|
$(document.body).on "keydown.image-preview", (e) ->
|
||||||
|
if attachmentsPreviewService.fileId
|
||||||
|
if e.keyCode == 39
|
||||||
|
ctrl.next()
|
||||||
|
else if e.keyCode == 37
|
||||||
|
ctrl.previous()
|
||||||
|
|
||||||
|
$scope.$digest()
|
||||||
|
|
||||||
|
$scope.$on '$destroy', () ->
|
||||||
|
$(document.body).off('.image-preview')
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: {},
|
||||||
|
controller: 'AttachmentsPreview',
|
||||||
|
templateUrl: 'components/attachments-preview/attachments-preview.html',
|
||||||
|
link: link,
|
||||||
|
controllerAs: "vm",
|
||||||
|
bindToController: {
|
||||||
|
attachments: "="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.module('taigaComponents').directive("tgAttachmentsPreview", [
|
||||||
|
"lightboxService",
|
||||||
|
"tgAttachmentsPreviewService",
|
||||||
|
AttachmentPreviewLightboxDirective])
|
|
@ -0,0 +1,21 @@
|
||||||
|
.attachment-preview(ng-if="vm.attachments.size && vm.current")
|
||||||
|
tg-lightbox-close
|
||||||
|
|
||||||
|
.attachment-preview-container
|
||||||
|
a.previous(
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.previous()",
|
||||||
|
ng-if="vm.hasPagination()"
|
||||||
|
)
|
||||||
|
tg-svg(svg-icon="icon-arrow-left")
|
||||||
|
|
||||||
|
a(href="{{vm.current.get('url')}}", title="{{vm.current.get('description')}}", target="_blank", download="{{vm.current.get('name')}}")
|
||||||
|
tg-preload-image(preload-src="{{vm.getCurrent().get('url')}}")
|
||||||
|
img(ng-src="{{vm.getCurrent().get('url')}}")
|
||||||
|
|
||||||
|
a.next(
|
||||||
|
href="#",
|
||||||
|
ng-click="vm.next()",
|
||||||
|
ng-if="vm.hasPagination()"
|
||||||
|
)
|
||||||
|
tg-svg(svg-icon="icon-arrow-right")
|
|
@ -0,0 +1,25 @@
|
||||||
|
###
|
||||||
|
# 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-preview.service.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
class AttachmentsPreviewService extends taiga.Service
|
||||||
|
@.$inject = []
|
||||||
|
|
||||||
|
constructor: () ->
|
||||||
|
|
||||||
|
angular.module("taigaComponents").service("tgAttachmentsPreviewService", AttachmentsPreviewService)
|
|
@ -1,5 +0,0 @@
|
||||||
.attachment-preview
|
|
||||||
tg-lightbox-close
|
|
||||||
|
|
||||||
a(href="{{::file.get('url')}}", title="{{::file.get('description')}}", target="_blank", download="{{::file.get('name')}}")
|
|
||||||
img(src="{{::file.get('url')}}")
|
|
|
@ -417,6 +417,18 @@ helper.attachment = function() {
|
||||||
list: function() {
|
list: function() {
|
||||||
$('.view-list').click();
|
$('.view-list').click();
|
||||||
},
|
},
|
||||||
|
previewLightbox: function() {
|
||||||
|
return utils.lightbox.open($('tg-attachments-preview'));
|
||||||
|
},
|
||||||
|
getPreviewSrc: function() {
|
||||||
|
return $('tg-attachments-preview img').getAttribute('src');
|
||||||
|
},
|
||||||
|
nextPreview: function() {
|
||||||
|
return $('tg-attachments-preview .next').click();
|
||||||
|
},
|
||||||
|
attachmentLinks: function() {
|
||||||
|
return $$('.e2e-attachment-link');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -315,6 +315,28 @@ shared.attachmentTesting = async function() {
|
||||||
|
|
||||||
attachmentHelper.list();
|
attachmentHelper.list();
|
||||||
|
|
||||||
|
// Gallery images
|
||||||
|
var fileToUploadImage = commonUtil.uploadImagePath();
|
||||||
|
|
||||||
|
await attachmentHelper.upload(fileToUploadImage, 'testing image ' + date);
|
||||||
|
|
||||||
|
await attachmentHelper.upload(fileToUpload, 'testing image ' + date);
|
||||||
|
|
||||||
|
await attachmentHelper.upload(fileToUploadImage, 'testing image ' + date);
|
||||||
|
await browser.sleep(5000);
|
||||||
|
|
||||||
|
attachmentHelper.attachmentLinks().last().click();
|
||||||
|
|
||||||
|
await attachmentHelper.previewLightbox();
|
||||||
|
let previewSrc = await attachmentHelper.getPreviewSrc();
|
||||||
|
|
||||||
|
await attachmentHelper.nextPreview();
|
||||||
|
|
||||||
|
let previewSrc2 = await attachmentHelper.getPreviewSrc();
|
||||||
|
|
||||||
|
expect(previewSrc).not.to.be.equal(previewSrc2);
|
||||||
|
await lightbox.exit();
|
||||||
|
|
||||||
// Deleting
|
// Deleting
|
||||||
attachmentsLength = await attachmentHelper.countAttachments();
|
attachmentsLength = await attachmentHelper.countAttachments();
|
||||||
await attachmentHelper.deleteLastAttachment();
|
await attachmentHelper.deleteLastAttachment();
|
||||||
|
|
|
@ -4,6 +4,10 @@ var lightbox = module.exports;
|
||||||
var transition = 300;
|
var transition = 300;
|
||||||
|
|
||||||
lightbox.exit = function(el) {
|
lightbox.exit = function(el) {
|
||||||
|
if (!el) {
|
||||||
|
el = $('.lightbox.open');
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof el === 'string' || el instanceof String) {
|
if (typeof el === 'string' || el instanceof String) {
|
||||||
el = $(el);
|
el = $(el);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue