diff --git a/app/coffee/modules/common/importer.coffee b/app/coffee/modules/common/importer.coffee index de61ce3f..46b84007 100644 --- a/app/coffee/modules/common/importer.coffee +++ b/app/coffee/modules/common/importer.coffee @@ -25,8 +25,60 @@ module = angular.module("taigaCommon") -ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls, $translate) -> +ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls, $translate, $lightboxFactory, currentUserService, $tgAuth) -> link = ($scope, $el, $attrs) -> + getRestrictionError = (result) -> + if result.headers + errorKey = '' + + user = currentUserService.getUser() + maxMembers = 0 + + if result.headers.isPrivate + privateError = !currentUserService.canCreatePrivateProjects().valid + maxMembers = null + + if user.get('max_members_private_projects') != null && result.headers.members > user.get('max_members_private_projects') + membersError = true + else + membersError = false + + if privateError && membersError + errorKey = 'private-space-members' + maxMembers = user.get('max_members_private_projects') + else if privateError + errorKey = 'private-space' + else if membersError + errorKey = 'private-members' + maxMembers = user.get('max_members_private_projects') + + else + publicError = !currentUserService.canCreatePublicProjects().valid + + if user.get('max_members_public_projects') != null && result.headers.members > user.get('max_members_public_projects') + membersError = true + else + membersError = false + + if publicError && membersError + errorKey = 'public-space-members' + maxMembers = user.get('max_members_public_projects') + else if publicError + errorKey = 'public-space' + else if membersError + errorKey = 'public-members' + maxMembers = user.get('max_members_public_projects') + + return { + key: errorKey, + values: { + max_members: maxMembers, + members: result.headers.members + } + } + else + return false + $el.on "click", ".import-project-button", (event) -> event.preventDefault() $el.find("input.import-file").val("") @@ -53,19 +105,47 @@ ImportProjectButtonDirective = ($rs, $confirm, $location, $navUrls, $translate) $confirm.notify("success", msg) onError = (result) -> - loader.stop() - errorMsg = $translate.instant("PROJECT.IMPORT.ERROR") + $tgAuth.refresh().then () -> + restrictionError = getRestrictionError(result) - if result.status == 429 # TOO MANY REQUESTS - errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_TOO_MANY_REQUEST") - else if result.data?._error_message - errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_MESSAGE", {error_message: result.data._error_message}) - $confirm.notify("error", errorMsg) + loader.stop() + + if restrictionError + $lightboxFactory.create('tg-lb-import-error', { + class: 'lightbox lightbox-import-error' + }, restrictionError) + + else + errorMsg = $translate.instant("PROJECT.IMPORT.ERROR") + + if result.status == 429 # TOO MANY REQUESTS + errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_TOO_MANY_REQUEST") + else if result.data?._error_message + errorMsg = $translate.instant("PROJECT.IMPORT.ERROR_MESSAGE", {error_message: result.data._error_message}) + $confirm.notify("error", errorMsg) loader.start() $rs.projects.import(file, loader.update).then(onSuccess, onError) return {link: link} -module.directive("tgImportProjectButton", ["$tgResources", "$tgConfirm", "$location", "$tgNavUrls", "$translate", +module.directive("tgImportProjectButton", +["$tgResources", "$tgConfirm", "$location", "$tgNavUrls", "$translate", "tgLightboxFactory", "tgCurrentUserService", "$tgAuth", ImportProjectButtonDirective]) + +LbImportErrorDirective = (lightboxService) -> + link = (scope, el, attrs) -> + lightboxService.open(el) + + scope.close = () -> + lightboxService.close(el) + return + + return { + templateUrl: "common/lightbox/lightbox-import-error.html", + link: link + } + +LbImportErrorDirective.$inject = ["lightboxService"] + +module.directive("tgLbImportError", LbImportErrorDirective) diff --git a/app/coffee/modules/common/lightboxes.coffee b/app/coffee/modules/common/lightboxes.coffee index fe3dd88d..5db4e843 100644 --- a/app/coffee/modules/common/lightboxes.coffee +++ b/app/coffee/modules/common/lightboxes.coffee @@ -74,7 +74,8 @@ class LightboxService extends taiga.Service $el.removeAttr('style') $el.removeClass("open").removeClass('close') - $el.addClass('close') + @animationFrame.add -> + $el.addClass('close') if $el.hasClass("remove-on-close") scope = $el.data("scope") diff --git a/app/coffee/modules/resources/projects.coffee b/app/coffee/modules/resources/projects.coffee index a1745420..7c1a372f 100644 --- a/app/coffee/modules/resources/projects.coffee +++ b/app/coffee/modules/resources/projects.coffee @@ -128,7 +128,11 @@ resourceProvider = ($config, $repo, $http, $urls, $auth, $q, $translate) -> catch response.data = {} response.status = evt.target.status - + if evt.target.getResponseHeader('Taiga-Info-Project-Is-Private') + response.headers = { + isPrivate: evt.target.getResponseHeader('Taiga-Info-Project-Is-Private') == 'True', + members: parseInt(evt.target.getResponseHeader('Taiga-Info-Project-Memberships')) + } defered.resolve(response) if response.status in [201, 202] defered.reject(response) diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json index 608e67fa..c9b100e2 100644 --- a/app/locales/taiga/locale-en.json +++ b/app/locales/taiga/locale-en.json @@ -806,7 +806,32 @@ "ERROR_TOO_MANY_REQUEST": "Sorry, our Oompa Loompas are very busy right now. Please try again in a few minutes.", "ERROR_MESSAGE": "Our Oompa Loompas have some problems importing your dump data: {{error_message}}", "ERROR_MAX_SIZE_EXCEEDED": "'{{fileName}}' ({{fileSize}}) is too heavy for our Oompa Loompas, try it with a smaller than ({{maxFileSize}})", - "SYNC_SUCCESS": "Your project has been imported successfuly" + "SYNC_SUCCESS": "Your project has been imported successfuly", + "PROJECT_RESTRICTIONS": { + "PROJECT_MEMBERS_DESC": "The project you want to import has {{members}} users, but you are only allowed to have {{max_members}} users per project. If you want have more users contact with the administrators.", + "PRIVATE_PROJECTS_SPACE": { + "TITLE": "You don't have space for another private project", + "DESC": "The project you want to import is private, but you don't have space to create more." + }, + "PUBLIC_PROJECTS_SPACE": { + "TITLE": "You don't' have space for another public project", + "DESC": "The project you want to import is public, but you don't have space to create more." + }, + "PRIVATE_PROJECTS_MEMBERS": { + "TITLE": "Your account only allows {{max_members}} users per private project" + }, + "PUBLIC_PROJECTS_MEMBERS": { + "TITLE": "Your account only allows {{max_members}} users per public project" + }, + "PRIVATE_PROJECTS_SPACE_MEMBERS": { + "TITLE": "You don't have space for another private project and neither for more than {{max_members}} users per private projects", + "DESC": "The project that you want to import is private and has {{members}} users." + }, + "PUBLIC_PROJECTS_SPACE_MEMBERS": { + "TITLE": "You don't have space for another public project and neither for more than {{max_members}} users per public projects", + "DESC": "The public that you want to import is public and has more than {{members}} users." + } + } }, "LIKE_BUTTON": { "LIKE": "Like", diff --git a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.jade b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.jade index c52a9961..10374374 100644 --- a/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.jade +++ b/app/modules/navigation-bar/dropdown-project-list/dropdown-project-list.jade @@ -28,11 +28,11 @@ div.navbar-dropdown.dropdown-project-list title="{{'PROJECT.NAVIGATION.ACTION_CREATE_PROJECT' | translate}}", translate="PROJECT.NAVIGATION.ACTION_CREATE_PROJECT") - a.button-blackish.import-project-button( - href="" - title="{{'PROJECT.NAVIGATION.TITLE_IMPORT_PROJECT' | translate}}" - tg-import-project-button - ) - svg.icon.icon-upload - use(xlink:href="#icon-upload") - input.import-file.hidden(type="file") + span(tg-import-project-button) + a.button-blackish.import-project-button( + href="" + title="{{'PROJECT.NAVIGATION.TITLE_IMPORT_PROJECT' | translate}}" + ) + svg.icon.icon-upload + use(xlink:href="#icon-upload") + input.import-file.hidden(type="file") \ No newline at end of file diff --git a/app/partials/common/lightbox/lightbox-import-error.jade b/app/partials/common/lightbox/lightbox-import-error.jade new file mode 100644 index 00000000..a715445d --- /dev/null +++ b/app/partials/common/lightbox/lightbox-import-error.jade @@ -0,0 +1,44 @@ +a.close(href="", title="{{'COMMON.CLOSE' | translate}}") + svg.icon.icon-close + use(xlink:href="#icon-close") + +.content + div(ng-switch="key") + div(ng-switch-when="private-space") + img(width="80", src="/#{v}/svg/icons/project-limit.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PRIVATE_PROJECTS_SPACE.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PRIVATE_PROJECTS_SPACE.DESC", translate-values="{{values}}") + + div(ng-switch-when="private-members") + img(width="80", src="/#{v}/svg/icons/block-user.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PRIVATE_PROJECTS_MEMBERS.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PROJECT_MEMBERS_DESC", translate-values="{{values}}") + + div(ng-switch-when="private-space-members") + img(width="180", src="/#{v}/svg/icons/multi-block-project.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PRIVATE_PROJECTS_SPACE_MEMBERS.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PRIVATE_PROJECTS_SPACE_MEMBERS.DESC", translate-values="{{values}}") + + div(ng-switch-when="public-space") + img(width="80", src="/#{v}/svg/icons/project-limit.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PUBLIC_PROJECTS_SPACE.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PUBLIC_PROJECTS_SPACE.DESC", translate-values="{{values}}") + + div(ng-switch-when="public-members") + img(width="80", src="/#{v}/svg/icons/block-user.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PUBLIC_PROJECTS_MEMBERS.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PROJECT_MEMBERS_DESC", translate-values="{{values}}") + + div(ng-switch-when="public-space-members") + img(width="180", src="/#{v}/svg/icons/multi-block-project.svg") + + h2.title(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PUBLIC_PROJECTS_SPACE_MEMBERS.TITLE", translate-values="{{values}}") + p(translate="PROJECT.IMPORT.PROJECT_RESTRICTIONS.PUBLIC_PROJECTS_SPACE_MEMBERS.DESC", translate-values="{{values}}") + + div.options + a.button-green(translate="COMMON.ACCEPT", ng-click="close()") \ No newline at end of file diff --git a/app/styles/modules/common/lightbox.scss b/app/styles/modules/common/lightbox.scss index 1a9b3379..265a5236 100644 --- a/app/styles/modules/common/lightbox.scss +++ b/app/styles/modules/common/lightbox.scss @@ -538,3 +538,18 @@ } } } + +.lightbox-import-error { + text-align: center; + p { + a { + color: $primary; + } + } + .content { + width: 500px; + } + h2 { + margin-top: 1rem; + } +} diff --git a/app/svg/icons/block-user.svg b/app/svg/icons/block-user.svg new file mode 100644 index 00000000..3c43c532 --- /dev/null +++ b/app/svg/icons/block-user.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/app/svg/icons/multi-block-project.svg b/app/svg/icons/multi-block-project.svg new file mode 100644 index 00000000..bc13957a --- /dev/null +++ b/app/svg/icons/multi-block-project.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/svg/icons/project-limit.svg b/app/svg/icons/project-limit.svg new file mode 100644 index 00000000..6f0ac0d5 --- /dev/null +++ b/app/svg/icons/project-limit.svg @@ -0,0 +1,8 @@ + + + + + + + +