From 088986626db1a2d272b1b780fc4c5e6fca7030bf Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Thu, 25 Feb 2016 16:24:19 +0100 Subject: [PATCH] Blocked projects Add blocked project page Fix styles in plugins Add blocked warning in dashboard Add blocked warning to dropdown Add blocked warning to projects list Add blocked project in project profile Minor style code fixes in project like/watch Bloc project listing Profile Favs in blocked projects Blocked projects Fix jade syntax error Fixing tests Updating changelog --- CHANGELOG.md | 1 + app/coffee/app.coffee | 46 +++++++++++++++++++ app/coffee/modules/base.coffee | 1 + app/locales/taiga/locale-en.json | 5 ++ app/modules/home/duties/duty.jade | 6 ++- app/modules/home/home.service.coffee | 1 + app/modules/home/home.service.spec.coffee | 6 +++ .../home/projects/home-project-list.jade | 12 ++++- .../home/projects/home-project-list.scss | 14 ++++++ app/modules/home/working-on/working-on.jade | 6 ++- .../dropdown-project-list.jade | 12 ++++- .../navigation-bar/navigation-bar.scss | 8 ++++ .../profile/profile-favs/items/project.jade | 24 +++++----- .../profile/profile-favs/items/ticket.jade | 14 +++--- .../profile-favs.controller.coffee | 1 - .../profile/profile-favs/profile-favs.jade | 24 ++++++++-- .../profile-projects/profile-projects.jade | 20 ++++---- app/modules/profile/profile.scss | 1 - ...ocked-project-explanation.directive.coffee | 25 ++++++++++ .../projects/listing/projects-listing.jade | 8 +++- .../listing/styles/profile-projects.scss | 15 +++++- .../projects/listing/styles/project-list.scss | 13 +++++- .../project/blocked-project-explanation.jade | 5 ++ .../projects/project/blocked-project.jade | 15 ++++++ .../projects/project/blocked-project.scss | 42 +++++++++++++++++ app/styles/components/list-items.scss | 27 ++++++++++- app/svg/sprite.svg | 7 +++ e2e/suites/project-home.e2e.js | 7 +++ 28 files changed, 319 insertions(+), 47 deletions(-) create mode 100644 app/modules/projects/components/blocked-project-explanation.directive.coffee create mode 100644 app/modules/projects/project/blocked-project-explanation.jade create mode 100644 app/modules/projects/project/blocked-project.jade create mode 100644 app/modules/projects/project/blocked-project.scss diff --git a/CHANGELOG.md b/CHANGELOG.md index 4246e874..dfe2d59b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Ability to create url custom fields. (thanks to [@astagi](https://github.com/astagi)). +- Blocked projects support - Moved from iconfont to SVG sprite icon system and redesign. - Redesign 'Admin > Project > Modules' panel. - Add badge to project owners diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 83976ab3..d0a750f5 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -111,6 +111,16 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven } ) + + $routeProvider.when("/blocked-project/:pslug/", + { + templateUrl: "projects/project/blocked-project.html", + loader: true, + controller: "Project", + controllerAs: "vm" + } + ) + $routeProvider.when("/project/:pslug/", { templateUrl: "projects/project/project.html", @@ -515,6 +525,42 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven $httpProvider.interceptors.push("versionCheckHttpIntercept") + + blockingIntercept = ($q, $routeParams, $location, $navUrls) -> + # API calls can return blocked elements and in that situation the user will be redirected + # to the blocked project page + # This can happens in two scenarios + # - An ok response containing a blocked_code in the data + # - An error reponse when updating/creating/deleting including a 451 error code + redirectToBlockedPage = -> + pslug = $routeParams.pslug + blockedUrl = $navUrls.resolve("blocked-project", {project: pslug}) + currentUrl = $location.url() + if currentUrl.indexOf(blockedUrl) == -1 + $location.replace().path(blockedUrl) + + responseOk = (response) -> + if response.data.blocked_code + redirectToBlockedPage() + + return response + + responseError = (response) -> + if response.status == 451 + redirectToBlockedPage() + + return $q.reject(response) + + return { + response: responseOk + responseError: responseError + } + + $provide.factory("blockingIntercept", ["$q", "$routeParams", "$location", "$tgNavUrls", blockingIntercept]) + + $httpProvider.interceptors.push("blockingIntercept") + + $compileProvider.debugInfoEnabled(window.taigaConfig.debugInfo || false) if localStorage.userInfo diff --git a/app/coffee/modules/base.coffee b/app/coffee/modules/base.coffee index e0b8c33b..2806d182 100644 --- a/app/coffee/modules/base.coffee +++ b/app/coffee/modules/base.coffee @@ -67,6 +67,7 @@ urls = { "profile": "/profile" "user-profile": "/profile/:username" + "blocked-project": "/blocked-project/:project" "project": "/project/:project" "project-backlog": "/project/:project/backlog" "project-taskboard": "/project/:project/taskboard/:sprint" diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json index c53fc45b..368d9784 100644 --- a/app/locales/taiga/locale-en.json +++ b/app/locales/taiga/locale-en.json @@ -740,6 +740,11 @@ "FANS_COUNTER_TITLE": "{total, plural, one{one fan} other{# fans}}", "WATCHERS_COUNTER_TITLE": "{total, plural, one{one watcher} other{# watchers}}", "MEMBERS_COUNTER_TITLE": "{total, plural, one{one member} other{# members}}", + "BLOCKED_PROJECT": { + "BLOCKED": "Blocked project", + "THIS_PROJECT_IS_BLOCKED": "This project is temporarily blocked", + "TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF": "To unblock your projects you must contact with the admin staff" + }, "STATS": { "PROJECT": "project
points", "DEFINED": "defined
points", diff --git a/app/modules/home/duties/duty.jade b/app/modules/home/duties/duty.jade index ee04e0b8..c0678e0a 100644 --- a/app/modules/home/duties/duty.jade +++ b/app/modules/home/duties/duty.jade @@ -1,7 +1,7 @@ a.list-itemtype-ticket( href="{{ ::vm.duty.get('url') }}" title="{{ ::duty.get('subject') }}" - ng-class="{'blocked': vm.duty.get('is_blocked')}" + ng-class="{'blocked': vm.duty.get('is_blocked'), 'blocked-project': vm.duty.get('blockedProject')}" ) div.list-itemtype-avatar(ng-if="::vm.duty.get('assigned_to_extra_info')") img( @@ -16,8 +16,12 @@ a.list-itemtype-ticket( div.list-itemtype-ticket-data p span.ticket-project {{ ::vm.duty.get('projectName')}} + span.ticket-type {{ ::vm.getDutyType() }} span.ticket-status(ng-style="{'color': vm.duty.get('status_extra_info').get('color')}") {{ ::vm.duty.get('status_extra_info').get('name') }} + svg.icon.icon-blocked-project(ng-if="vm.duty.get('blockedProject')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") h2 span.ticket-id(tg-bo-ref="duty.get('ref')") diff --git a/app/modules/home/home.service.coffee b/app/modules/home/home.service.coffee index 625b31a2..47aa069f 100644 --- a/app/modules/home/home.service.coffee +++ b/app/modules/home/home.service.coffee @@ -41,6 +41,7 @@ class HomeService extends taiga.Service duty = duty.set('url', url) duty = duty.set('projectName', project.get('name')) + duty = duty.set('blockedProject', project.get('blocked_code')) duty = duty.set("_name", objType) return duty diff --git a/app/modules/home/home.service.spec.coffee b/app/modules/home/home.service.spec.coffee index 24b1f01f..41b162ff 100644 --- a/app/modules/home/home.service.spec.coffee +++ b/app/modules/home/home.service.spec.coffee @@ -128,6 +128,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/us/1', projectName: 'fake1', + blockedProject: undefined, _name: 'userstories' }] tasks: [{ @@ -136,6 +137,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/tasks/1', projectName: 'fake1', + blockedProject: undefined, _name: 'tasks' }] issues: [{ @@ -144,6 +146,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/issues/1', projectName: 'fake1', + blockedProject: undefined, _name: 'issues' }] } @@ -154,6 +157,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/us/1', projectName: 'fake1', + blockedProject: undefined, _name: 'userstories' }] tasks: [{ @@ -162,6 +166,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/tasks/1', projectName: 'fake1', + blockedProject: undefined, _name: 'tasks' }] issues: [{ @@ -170,6 +175,7 @@ describe "tgHome", -> project: '1', url: '/testing-project/issues/1', projectName: 'fake1', + blockedProject: undefined, _name: 'issues' }] } diff --git a/app/modules/home/projects/home-project-list.jade b/app/modules/home/projects/home-project-list.jade index a5d4c52a..7bb4820a 100644 --- a/app/modules/home/projects/home-project-list.jade +++ b/app/modules/home/projects/home-project-list.jade @@ -1,6 +1,10 @@ section.home-project-list(ng-if="vm.projects.size") - .home-project(tg-bind-scope, tg-repeat="project in vm.projects") + .home-project( + tg-bind-scope + tg-repeat="project in vm.projects" + ng-class="{'blocked-project': project.get('blocked_code')}" + ) .tags-container .project-tag( style="background: {{tag.get('color')}}" @@ -19,7 +23,7 @@ section.home-project-list(ng-if="vm.projects.size") alt="{{::project.get('name')}}" ) h2.project-card-name - a( + a.project-title( href="#" tg-nav="project:project=project.get('slug')" title="{{::project.get('name')}}" @@ -27,6 +31,10 @@ section.home-project-list(ng-if="vm.projects.size") svg.look-for-people.icon.icon-recruit(ng-if="project.get('is_looking_for_people')") use(xlink:href="#icon-recruit") title="{{ ::project.get('looking_for_people_note') }}" + svg.icon.icon-blocked-project(ng-if="project.get('blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") + p.project-card-description {{::project.get('description')| limitTo:100 }} span(ng-if="::project.get('description').length > 100") ... .project-card-statistics diff --git a/app/modules/home/projects/home-project-list.scss b/app/modules/home/projects/home-project-list.scss index 503b1155..d87810e0 100644 --- a/app/modules/home/projects/home-project-list.scss +++ b/app/modules/home/projects/home-project-list.scss @@ -9,6 +9,20 @@ &:hover { border: 1px solid $primary-light; } + &.blocked-project { + border: $whitish; + &:hover { + border: $whitish; + } + .tags-container, + .project-card-logo, + .project-card-name a, + .icon-recruit, + .project-card-description, + .project-card-statistics { + opacity: .3; + } + } } .projects-empty { diff --git a/app/modules/home/working-on/working-on.jade b/app/modules/home/working-on/working-on.jade index 62e3d755..6b301ba8 100644 --- a/app/modules/home/working-on/working-on.jade +++ b/app/modules/home/working-on/working-on.jade @@ -20,7 +20,11 @@ section.watching-container .title-bar.watching-title(translate="HOME.WATCHING_SECTION") .watching(ng-if="vm.watching.size") - .duty-single(tg-duty="duty", tg-repeat="duty in vm.watching", ng-class="{'blocked': duty.is_blocked}") + .duty-single( + tg-duty="duty" + tg-repeat="duty in vm.watching" + ng-class="{'blocked': duty.is_blocked}" + ) .watching-empty(ng-if="vm.watching != undefined && vm.watching.size === 0") p(translate="HOME.EMPTY_WATCHING") 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 47a2a7c0..c52a9961 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 @@ -4,8 +4,16 @@ a(href="", title="Projects", tg-nav="projects") div.navbar-dropdown.dropdown-project-list ul - li(tg-repeat="project in vm.projects track by project.get('id')") - a(href="#", tg-nav="project:project=project.get('slug')") {{::project.get("name")}} + li(tg-repeat="project in vm.projects track by project.get('id')") + a( + href="#" + tg-nav="project:project=project.get('slug')" + ng-class="{'blocked-project': project.get('blocked_code')}" + ) + span {{::project.get("name")}} + svg.icon.icon-blocked-project(ng-if="project.get('blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") a.see-more-projects-btn.button-gray( href="#", diff --git a/app/modules/navigation-bar/navigation-bar.scss b/app/modules/navigation-bar/navigation-bar.scss index 4a6f78a0..26f0fadf 100644 --- a/app/modules/navigation-bar/navigation-bar.scss +++ b/app/modules/navigation-bar/navigation-bar.scss @@ -173,6 +173,14 @@ $dropdown-width: 350px; &.create-project-btn { flex: 1; } + &.blocked-project { + color: $gray; + svg { + margin-left: .5rem; + position: relative; + top: .25rem; + } + } } .import-project-button { &:hover { diff --git a/app/modules/profile/profile-favs/items/project.jade b/app/modules/profile/profile-favs/items/project.jade index c298b272..99f58d66 100644 --- a/app/modules/profile/profile-favs/items/project.jade +++ b/app/modules/profile/profile-favs/items/project.jade @@ -1,7 +1,6 @@ -.list-itemtype-project +.list-itemtype-project(ng-class="{'blocked-project': vm.item.get('project_blocked_code')}") .list-itemtype-project-left .list-itemtype-project-data-wrapper - a.list-itemtype-project-image( href="#" tg-nav="project:project=vm.item.get('slug')" @@ -14,20 +13,21 @@ .list-itemtype-project-data h2 - a( + a.list-itemtype-project-name( href="#" tg-nav="project:project=vm.item.get('slug')" title="{{ ::vm.item.get('name') }}" ) {{ ::vm.item.get('name') }} - span.private(ng-if="::project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}") - p {{ ::vm.item.get('description') }} - - .list-itemtype-project-tags.tags-container(ng-if="::vm.item.get('tags_colors').size") - span.tag( - tg-repeat="tag in ::vm.item.get('tags_colors')" - style='border-left: 5px solid {{ ::tag.get("color") }};' - ) - span.tag-name {{ ::tag.get('name') }} + span.private( + ng-if="::vm.item.get('project_is_private')" + title="{{'PROJECT.PRIVATE' | translate}}" + ) + svg.icon.icon-lock + use(xlink:href="#icon-lock") + svg.icon.icon-blocked-project(ng-if="vm.item.get('project_blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") + p.list-itemtype-project-description {{ ::vm.item.get('description') }} .list-itemtype-track span.list-itemtype-track-likers( diff --git a/app/modules/profile/profile-favs/items/ticket.jade b/app/modules/profile/profile-favs/items/ticket.jade index d938466a..599fd041 100644 --- a/app/modules/profile/profile-favs/items/ticket.jade +++ b/app/modules/profile/profile-favs/items/ticket.jade @@ -1,4 +1,4 @@ -div.list-itemtype-ticket +div.list-itemtype-ticket(ng-class="{'blocked-project': vm.item.get('project_blocked_code')}") a.list-itemtype-avatar( href="" ng-if="::vm.item.get('assigned_to')" @@ -38,6 +38,9 @@ div.list-itemtype-ticket ) span.ticket-status(ng-style="::{'color': vm.item.get('status_color')}") | {{:: vm.item.get('status') }} + svg.icon.icon-blocked-project(ng-if="vm.item.get('project_blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") h2 span.ticket-id(tg-bo-ref="vm.item.get('ref')") a.ticket-title( @@ -45,22 +48,19 @@ div.list-itemtype-ticket ng-if="::vm.item.get('type') === 'userstory'" tg-nav="project-userstories-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" - ) - | {{ ::vm.item.get('subject') }} + ) {{ ::vm.item.get('subject') }} a.ticket-title( href="#" ng-if="::vm.item.get('type') === 'task'" tg-nav="project-tasks-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" - ) - | {{ ::vm.item.get('subject') }} + ) {{ ::vm.item.get('subject') }} a.ticket-title( href="#" ng-if="::vm.item.get('type') === 'issue'" tg-nav="project-issues-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')" title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}" - ) - | {{ ::vm.item.get('subject') }} + ) {{ ::vm.item.get('subject') }} div.list-itemtype-track span.list-itemtype-track-likers( diff --git a/app/modules/profile/profile-favs/profile-favs.controller.coffee b/app/modules/profile/profile-favs/profile-favs.controller.coffee index 2022ee4a..5bd5917d 100644 --- a/app/modules/profile/profile-favs/profile-favs.controller.coffee +++ b/app/modules/profile/profile-favs/profile-favs.controller.coffee @@ -184,4 +184,3 @@ class ProfileWatchedController extends FavsBaseController angular.module("taigaProfile") .controller("ProfileWatched", ProfileWatchedController) - diff --git a/app/modules/profile/profile-favs/profile-favs.jade b/app/modules/profile/profile-favs/profile-favs.jade index 24120ccb..9ec621c7 100644 --- a/app/modules/profile/profile-favs/profile-favs.jade +++ b/app/modules/profile/profile-favs/profile-favs.jade @@ -60,10 +60,26 @@ section.profile-favs tg-repeat="item in vm.items track by $index" ng-switch="item.get('type')" ) - div(ng-switch-when="project", tg-fav-item="item", item-type="project") - div(ng-switch-when="userstory", tg-fav-item="item", item-type="userstory") - div(ng-switch-when="task", tg-fav-item="item", item-type="task") - div(ng-switch-when="issue", tg-fav-item="item", item-type="issue") + div( + ng-switch-when="project" + tg-fav-item="item" + item-type="project" + ) + div( + ng-switch-when="userstory" + tg-fav-item="item" + item-type="userstory" + ) + div( + ng-switch-when="task" + tg-fav-item="item" + item-type="task" + ) + div( + ng-switch-when="issue" + tg-fav-item="item" + item-type="issue" + ) div(ng-if="vm.isLoading") div.spin diff --git a/app/modules/profile/profile-projects/profile-projects.jade b/app/modules/profile/profile-projects/profile-projects.jade index 19e943c8..5e3ff52d 100644 --- a/app/modules/profile/profile-projects/profile-projects.jade +++ b/app/modules/profile/profile-projects/profile-projects.jade @@ -11,8 +11,10 @@ section.profile-projects translate="USER.PROFILE.PROJECTS_EMPTY" translate-values="{username: vm.user.get('full_name_display')}" ) - - .list-itemtype-project(tg-repeat="project in vm.projects") + .list-itemtype-project( + tg-repeat="project in vm.projects" + ng-class="{'blocked-project': project.get('blocked_code')}" + ) .list-itemtype-project-left .project-list-single-title-wrapper a.list-itemtype-project-image( @@ -26,19 +28,15 @@ section.profile-projects ) .project-list-single-title h2 - a( + a.project-title( href="#" tg-nav="project:project=project.get('slug')" title="{{ ::project.get('name') }}" ) {{::project.get('name')}} - p {{ ::project.get('description') | limitTo:300 }} - - .list-itemtype-project-tags.tags-container(ng-if="::project.get('tags').size") - span.tag( - style='border-left: 5px solid {{::tag.get("color")}};' - tg-repeat="tag in ::project.get('colorized_tags')" - ) - span.tag-name {{::tag.get('name')}} + svg.icon.icon-blocked-project(ng-if="project.get('blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") + p.project-description {{ ::project.get('description') | limitTo:300 }} .list-itemtype-project-right diff --git a/app/modules/profile/profile.scss b/app/modules/profile/profile.scss index d11826f6..a2b22bb7 100644 --- a/app/modules/profile/profile.scss +++ b/app/modules/profile/profile.scss @@ -11,7 +11,6 @@ padding: 0; } .timeline-wrapper { - background: lighten($whitish, 10%); margin-right: 3.5rem; width: 768px; > div { diff --git a/app/modules/projects/components/blocked-project-explanation.directive.coffee b/app/modules/projects/components/blocked-project-explanation.directive.coffee new file mode 100644 index 00000000..fac3ed91 --- /dev/null +++ b/app/modules/projects/components/blocked-project-explanation.directive.coffee @@ -0,0 +1,25 @@ +### +# Copyright (C) 2014-2016 Taiga Agile LLC +# +# 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 . +# +# File: blocked-project-explanation.directive.coffee +### + +BlockedProjectExplanationDirective = () -> + return { + templateUrl: "projects/project/blocked-project-explanation.html" + } + +angular.module("taigaProjects").directive("tgBlockedProjectExplanation", BlockedProjectExplanationDirective) diff --git a/app/modules/projects/listing/projects-listing.jade b/app/modules/projects/listing/projects-listing.jade index 237e1061..65414a43 100644 --- a/app/modules/projects/listing/projects-listing.jade +++ b/app/modules/projects/listing/projects-listing.jade @@ -23,6 +23,7 @@ li.list-itemtype-project( tg-bind-scope tg-repeat="project in vm.projects track by project.get('id')" + ng-class="{'blocked-project': project.get('blocked_code')}" ) .list-itemtype-project-left @@ -38,7 +39,7 @@ ) .list-itemtype-project-data h2 - a( + a.project-title( href="#" tg-nav="project:project=project.get('slug')" title="{{ ::project.get('name') }}" @@ -53,9 +54,12 @@ svg.icon.icon-badge(ng-if="project.get('i_am_owner')") use(xlink:href="#icon-badge") title(translate="COMMON.OWNER") + svg.icon.icon-blocked-project(ng-if="project.get('blocked_code')") + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") - p {{ ::project.get('description') | limitTo:300 }} + p.project-description {{ ::project.get('description') | limitTo:300 }} span(ng-if="::project.get('description').length > 300") ... svg.drag.icon.icon-drag diff --git a/app/modules/projects/listing/styles/profile-projects.scss b/app/modules/projects/listing/styles/profile-projects.scss index e068e7c7..2a2a6041 100644 --- a/app/modules/projects/listing/styles/profile-projects.scss +++ b/app/modules/projects/listing/styles/profile-projects.scss @@ -3,7 +3,16 @@ .list-itemtype-project { display: flex; justify-content: space-between; - min-height: 10rem; + min-height: 9rem; + padding: .75rem; + &.blocked-project { + .list-itemtype-project-image, + .project-title, + .project-description, + .list-itemtype-project-right { + opacity: .4; + } + } .project-list-single-title-wrapper { display: flex; } @@ -14,7 +23,11 @@ display: flex; flex-direction: column; flex-shrink: 0; + justify-content: space-between; width: 200px; } + .icon-blocked-project { + @include svg-size(); + } } } diff --git a/app/modules/projects/listing/styles/project-list.scss b/app/modules/projects/listing/styles/project-list.scss index f2599a51..fe26d12c 100644 --- a/app/modules/projects/listing/styles/project-list.scss +++ b/app/modules/projects/listing/styles/project-list.scss @@ -14,7 +14,8 @@ } } .icon-lock, - .icon-badge { + .icon-badge, + .icon-blocked-project { @include svg-size(); } .icon-badge { @@ -62,6 +63,16 @@ opacity: 1; } } + &.blocked-project { + .list-itemtype-project-image, + .project-title, + .private, + .project-description, + .icon-badge, + .icon-drag { + opacity: .25; + } + } .list-itemtype-project-data-wrapper { display: flex; } diff --git a/app/modules/projects/project/blocked-project-explanation.jade b/app/modules/projects/project/blocked-project-explanation.jade new file mode 100644 index 00000000..0ce3441b --- /dev/null +++ b/app/modules/projects/project/blocked-project-explanation.jade @@ -0,0 +1,5 @@ +div(ng-if="!vm.project.get('i_am_owner')") + div {{'PROJECT.BLOCKED_PROJECT.THIS_PROJECT_IS_BLOCKED' | translate}} + +div(ng-if="vm.project.get('i_am_owner')") + div {{'PROJECT.BLOCKED_PROJECT.TO_UNBLOCK_CONTACT_THE_ADMIN_STAFF' | translate}} diff --git a/app/modules/projects/project/blocked-project.jade b/app/modules/projects/project/blocked-project.jade new file mode 100644 index 00000000..be6b75b8 --- /dev/null +++ b/app/modules/projects/project/blocked-project.jade @@ -0,0 +1,15 @@ +.blocked-project-detail + .blocked-project-inner + .blocked-project-title + .project-image + img( + tg-project-logo-small-src="vm.project" + alt="{{::vm.project.get('name')}}" + ) + svg.icon.icon-blocked-project + use(xlink:href="#icon-blocked-project") + title(translate="PROJECT.BLOCKED_PROJECT.BLOCKED") + span.project-title {{::vm.project.get("name")}} + .blocked-project-message + h1.project-block-title {{'PROJECT.BLOCKED_PROJECT.BLOCKED' | translate}} + tg-blocked-project-explanation.project-block-message diff --git a/app/modules/projects/project/blocked-project.scss b/app/modules/projects/project/blocked-project.scss new file mode 100644 index 00000000..40bbc218 --- /dev/null +++ b/app/modules/projects/project/blocked-project.scss @@ -0,0 +1,42 @@ +.blocked-project-detail { + align-items: center; + background: url('../images/discover.png') bottom center repeat-x; + display: flex; + justify-content: center; + min-height: calc(100vh - 40px); +} + +.blocked-project-inner { + width: 330px; +} + +.blocked-project-title { + align-items: center; + display: flex; + .project-image { + flex-basis: 6rem; + margin-right: 1rem; + max-width: 6rem; + position: relative; + } + img { + width: 100%; + } + .icon-blocked-project { + @include svg-size(1.5rem); + position: absolute; + right: -.5rem; + top: -.5rem; + } + .project-title { + @extend %larger; + } +} + +.blocked-project-message { + margin-top: 4rem; + text-align: center; + .project-block-title { + @extend %xlarge; + } +} diff --git a/app/styles/components/list-items.scss b/app/styles/components/list-items.scss index 0b715bac..547c4294 100644 --- a/app/styles/components/list-items.scss +++ b/app/styles/components/list-items.scss @@ -32,9 +32,21 @@ .list-itemtype-project { @include list-itemtype-common; justify-content: space-between; + &.blocked-project { + .list-itemtype-track, + .list-itemtype-project-image, + .list-itemtype-project-name, + .list-itemtype-project-description, + .list-itemtype-project-private { + opacity: .4; + } + } h2 { @extend %large; } + .icon-blocked-project { + @include svg-size(); + } .list-itemtype-project-data-wrapper { display: flex; } @@ -75,6 +87,20 @@ .list-itemtype-ticket { @include list-itemtype-common; + position: relative; + &.blocked-project { + .ticket-project, + .ticket-type, + .ticket-status, + .list-itemtype-avatar, + .list-itemtype-track, + .ticket-title { + opacity: .4; + } + .icon-blocked-project { + @include svg-size(); + } + } h2 { @extend %medium; } @@ -97,7 +123,6 @@ color: $red; margin-left: .3rem; } - } diff --git a/app/svg/sprite.svg b/app/svg/sprite.svg index 68d91a7e..2a25e0c5 100644 --- a/app/svg/sprite.svg +++ b/app/svg/sprite.svg @@ -418,5 +418,12 @@ + + Blocked Project + + + diff --git a/e2e/suites/project-home.e2e.js b/e2e/suites/project-home.e2e.js index 5afb2343..dfaf8295 100644 --- a/e2e/suites/project-home.e2e.js +++ b/e2e/suites/project-home.e2e.js @@ -138,4 +138,11 @@ describe('project home', function() { expect(watchCounter).to.be.equal(watchCounterOld + 1); }); + it('blocked project', async function() { + browser.get(browser.params.glob.host + 'project/project-6/'); + await utils.common.waitLoader(); + await utils.common.takeScreenshot("project", "blocked-project"); + expect(browser.getCurrentUrl()).to.be.eventually.equal(browser.params.glob.host + 'blocked-project/project-6/'); + }); + });