From 60b0ca8b1bf8e6c5a9fc5f73da59a23616b0ec96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 7 Apr 2016 12:24:16 +0200 Subject: [PATCH 01/47] Fix issue #4068: The next (>) and previous (<) buttons don't work in issue detail page --- app/partials/issue/issues-detail.jade | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/partials/issue/issues-detail.jade b/app/partials/issue/issues-detail.jade index 5a2b5a44..056e718f 100644 --- a/app/partials/issue/issues-detail.jade +++ b/app/partials/issue/issues-detail.jade @@ -47,18 +47,21 @@ div.wrapper( span.block-description(ng-bind="issue.blocked_note || ('ISSUES.BLOCKED' | translate)") .issue-nav - svg.icon.icon-arrow-left( + a( ng-show="previousUrl" tg-bo-href="previousUrl" title="{{'ISSUES.TITLE_PREVIOUS_ISSUE' | translate}}" ) - use(xlink:href="#icon-arrow-left") - svg.icon.icon-arrow-right( + svg.icon.icon-arrow-left + use(xlink:href="#icon-arrow-left") + a( ng-show="nextUrl" tg-bo-href="nextUrl" title="{{'ISSUES.TITLE_NEXT_ISSUE' | translate}}" ) - use(xlink:href="#icon-arrow-right") + svg.icon.icon-arrow-right + use(xlink:href="#icon-arrow-right") + .subheader div.tags-block(tg-tag-line, ng-model="issue", required-perm="modify_issue") tg-created-by-display.ticket-created-by(ng-model="issue") From 9847c05ecf1579d974f8d42ebdafa4705704d1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 7 Apr 2016 12:58:19 +0200 Subject: [PATCH 02/47] Fix issue #4054: Total power for current user has disappeared --- app/partials/team/team-member-current-user.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/partials/team/team-member-current-user.jade b/app/partials/team/team-member-current-user.jade index 1c425a44..7275184f 100644 --- a/app/partials/team/team-member-current-user.jade +++ b/app/partials/team/team-member-current-user.jade @@ -17,7 +17,7 @@ .member-stats( tg-team-member-stats stats="stats" - ser="currentUser.user" + user="currentUser.user" issuesEnabled="issuesEnabled" tasksenabled="tasksEnabled" wikienabled="wikiEnabled" From e280a86069369f2fd4fcc21597f2d9bc5eb5d47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 7 Apr 2016 13:21:07 +0200 Subject: [PATCH 03/47] Fix issue #4069: delete icon of wiki links doesn't work --- app/coffee/modules/wiki/nav.coffee | 2 +- app/partials/wiki/wiki-nav.jade | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/coffee/modules/wiki/nav.coffee b/app/coffee/modules/wiki/nav.coffee index 23935cbb..6bf17e14 100644 --- a/app/coffee/modules/wiki/nav.coffee +++ b/app/coffee/modules/wiki/nav.coffee @@ -77,7 +77,7 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l $el.find(".new input").focus() $el.find(".add-button").hide() - $el.on "click", ".wiki-link .icon-delete", (event) -> + $el.on "click", ".js-delete-link", (event) -> event.preventDefault() event.stopPropagation() target = angular.element(event.currentTarget) diff --git a/app/partials/wiki/wiki-nav.jade b/app/partials/wiki/wiki-nav.jade index 4d3fa0da..c26d5590 100644 --- a/app/partials/wiki/wiki-nav.jade +++ b/app/partials/wiki/wiki-nav.jade @@ -8,7 +8,7 @@ nav a(title!="<%- link.title %>") span.link-title <%- link.title %> <% if (deleteWikiLinkPermission) { %> - svg.icon.icon-trash + svg.js-delete-link.icon.icon-trash use(xlink:href="#icon-trash") <% } %> input(type="text" placeholder="{{'COMMON.FIELDS.NAME' | translate}}" class="hidden" value!="<%- link.title %>") From 12867b9ae5a531554b930a1a52a812392f3a826c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Fri, 8 Apr 2016 09:31:53 +0200 Subject: [PATCH 04/47] Remove looking for people badge in home project list --- app/modules/home/projects/home-project-list.jade | 3 --- app/modules/home/projects/home-project-list.scss | 1 - 2 files changed, 4 deletions(-) diff --git a/app/modules/home/projects/home-project-list.jade b/app/modules/home/projects/home-project-list.jade index 7bb4820a..87493385 100644 --- a/app/modules/home/projects/home-project-list.jade +++ b/app/modules/home/projects/home-project-list.jade @@ -28,9 +28,6 @@ section.home-project-list(ng-if="vm.projects.size") tg-nav="project:project=project.get('slug')" title="{{::project.get('name')}}" ) {{::project.get('name')}} - 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") diff --git a/app/modules/home/projects/home-project-list.scss b/app/modules/home/projects/home-project-list.scss index e5dd7028..fefe9aa0 100644 --- a/app/modules/home/projects/home-project-list.scss +++ b/app/modules/home/projects/home-project-list.scss @@ -18,7 +18,6 @@ .tags-container, .project-card-logo, .project-card-name a, - .icon-recruit, .project-card-description, .project-card-statistics { opacity: .3; From 95d147d9b783d39bcea62e32867cfac2ca22642a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Fri, 8 Apr 2016 14:02:16 +0200 Subject: [PATCH 05/47] [i18n] Update locales and fix some typos --- app/locales/taiga/locale-ca.json | 2 +- app/locales/taiga/locale-de.json | 2 +- app/locales/taiga/locale-en.json | 4 ++-- app/locales/taiga/locale-es.json | 2 +- app/locales/taiga/locale-fi.json | 2 +- app/locales/taiga/locale-fr.json | 2 +- app/locales/taiga/locale-it.json | 2 +- app/locales/taiga/locale-nl.json | 2 +- app/locales/taiga/locale-pl.json | 2 +- app/locales/taiga/locale-pt-br.json | 2 +- app/locales/taiga/locale-ru.json | 2 +- app/locales/taiga/locale-sv.json | 2 +- app/locales/taiga/locale-tr.json | 2 +- app/locales/taiga/locale-zh-hant.json | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/locales/taiga/locale-ca.json b/app/locales/taiga/locale-ca.json index 57a3a9b5..7ce8f0cc 100644 --- a/app/locales/taiga/locale-ca.json +++ b/app/locales/taiga/locale-ca.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-de.json b/app/locales/taiga/locale-de.json index 92639637..258a12e8 100644 --- a/app/locales/taiga/locale-de.json +++ b/app/locales/taiga/locale-de.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json index 4a49d61f..d2650ab2 100644 --- a/app/locales/taiga/locale-en.json +++ b/app/locales/taiga/locale-en.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { @@ -1572,4 +1572,4 @@ "RESULTS": "Search results" } } -} \ No newline at end of file +} diff --git a/app/locales/taiga/locale-es.json b/app/locales/taiga/locale-es.json index c8518ba9..3c24f1c6 100644 --- a/app/locales/taiga/locale-es.json +++ b/app/locales/taiga/locale-es.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-fi.json b/app/locales/taiga/locale-fi.json index 1c3f526f..3d1ec11d 100644 --- a/app/locales/taiga/locale-fi.json +++ b/app/locales/taiga/locale-fi.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-fr.json b/app/locales/taiga/locale-fr.json index 5af40473..1cde83e5 100644 --- a/app/locales/taiga/locale-fr.json +++ b/app/locales/taiga/locale-fr.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-it.json b/app/locales/taiga/locale-it.json index ed6e9b2b..9b8d72d6 100644 --- a/app/locales/taiga/locale-it.json +++ b/app/locales/taiga/locale-it.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-nl.json b/app/locales/taiga/locale-nl.json index df0de862..0bacf439 100644 --- a/app/locales/taiga/locale-nl.json +++ b/app/locales/taiga/locale-nl.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-pl.json b/app/locales/taiga/locale-pl.json index fb9db52f..7f403c83 100644 --- a/app/locales/taiga/locale-pl.json +++ b/app/locales/taiga/locale-pl.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-pt-br.json b/app/locales/taiga/locale-pt-br.json index 2e78ad2d..0afc87ba 100644 --- a/app/locales/taiga/locale-pt-br.json +++ b/app/locales/taiga/locale-pt-br.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-ru.json b/app/locales/taiga/locale-ru.json index 50ec8091..8f3b67ca 100644 --- a/app/locales/taiga/locale-ru.json +++ b/app/locales/taiga/locale-ru.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-sv.json b/app/locales/taiga/locale-sv.json index 7caf2895..306d56c7 100644 --- a/app/locales/taiga/locale-sv.json +++ b/app/locales/taiga/locale-sv.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-tr.json b/app/locales/taiga/locale-tr.json index 7969c999..eef1f5c4 100644 --- a/app/locales/taiga/locale-tr.json +++ b/app/locales/taiga/locale-tr.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { diff --git a/app/locales/taiga/locale-zh-hant.json b/app/locales/taiga/locale-zh-hant.json index c1f81f88..f7c2eab5 100644 --- a/app/locales/taiga/locale-zh-hant.json +++ b/app/locales/taiga/locale-zh-hant.json @@ -842,7 +842,7 @@ "DESC": "The project you are trying to import is private. Unfortunately, your current plan does not allow for additional private projects." }, "PUBLIC_PROJECTS_SPACE": { - "TITLE": "Unfortunately, your current plan does not allow for additional private projects", + "TITLE": "Unfortunately, your current plan does not allow for additional public projects", "DESC": "The project you are trying to import is public. Unfortunately, your current plan does not allow additional public projects." }, "PRIVATE_PROJECTS_MEMBERS": { From aa1b6315c7c58733a2336aeb57026aefd40ae100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Fri, 8 Apr 2016 14:05:27 +0200 Subject: [PATCH 06/47] history tabs wrong behavior --- app/coffee/modules/common/history.coffee | 6 +++--- app/partials/common/history/history-base.jade | 13 +++++++++---- app/styles/modules/common/history.scss | 19 +++++++------------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/app/coffee/modules/common/history.coffee b/app/coffee/modules/common/history.coffee index bbc1beb4..f426a66a 100644 --- a/app/coffee/modules/common/history.coffee +++ b/app/coffee/modules/common/history.coffee @@ -421,7 +421,7 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm, $translate, $c # Events - $el.on "click", ".add-comment button.button-green", debounce 2000, (event) -> + $el.on "click", ".add-comment .button-green", debounce 2000, (event) -> event.preventDefault() target = angular.element(event.currentTarget) @@ -467,10 +467,10 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm, $translate, $c $el.on "focus", ".add-comment textarea", (event) -> $(this).addClass('active') - $el.on "click", ".history-tabs li a", (event) -> + $el.on "click", ".history-tabs li", (event) -> target = angular.element(event.currentTarget) - $el.find(".history-tabs li a").removeClass("active") + $el.find(".history-tabs li").removeClass("active") target.addClass("active") $el.find(".history section").addClass("hidden") diff --git a/app/partials/common/history/history-base.jade b/app/partials/common/history/history-base.jade index 3d8f1874..bd5949e7 100644 --- a/app/partials/common/history/history-base.jade +++ b/app/partials/common/history/history-base.jade @@ -4,15 +4,20 @@ section.history <% if (commentsVisible || historyVisible) { %> ul.history-tabs <% if (commentsVisible) { %> - li - a(href="#", class="active", data-section-class="history-comments") + li( + class="active" + data-section-class="history-comments" + ) + a(href="") svg.icon.icon-writer use(xlink:href="#icon-writer") span.tab-title(translate="COMMENTS.TITLE") <% } %> <% if (historyVisible) { %> - li - a(href="#", data-section-class="history-activity") + li( + data-section-class="history-activity" + ) + a(href="") svg.icon.icon-timeline use(xlink:href="#icon-timeline") span.tab-title(translate="ACTIVITY.TITLE") diff --git a/app/styles/modules/common/history.scss b/app/styles/modules/common/history.scss index f39e2247..5efc4295 100644 --- a/app/styles/modules/common/history.scss +++ b/app/styles/modules/common/history.scss @@ -45,21 +45,10 @@ margin-bottom: 0; li { @extend %large; - display: inline-block; - &:first-child { - border-right: 1px solid $whitish; - } - &:last-child { - border-right: 0; - } - } - a { background: $white; - color: $gray-light; + border-right: 1px solid $whitish; display: inline-block; - padding: .5rem 2rem; position: relative; - transition: color .2s ease-in; &.active { color: $primary; top: 1px; @@ -69,6 +58,12 @@ transition: color .2s ease-in; } } + a { + color: $gray-light; + display: block; + padding: .5rem 2rem; + transition: color .2s ease-in; + } .icon { fill: currentColor; height: .75rem; From 7f8922e8c30702d0941ec3d7a8374e40c77b0458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Sun, 10 Apr 2016 20:10:33 +0200 Subject: [PATCH 07/47] Update CHANGELOG --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 930a76fa..2af211e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog # +## 2.1.0 ??? (unreleased) + +### Features +- ... + +### Misc +- Lots of small and not so small bugfixes. + + ## 2.0.0 Pulsatilla Patens (2016-04-04) ### Features From 09cb60e93aca0bced69639145bd6ebe0b370d9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Mon, 11 Apr 2016 08:25:36 +0200 Subject: [PATCH 08/47] Change condensed fonts in history tabs --- app/styles/modules/common/history.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/styles/modules/common/history.scss b/app/styles/modules/common/history.scss index 5efc4295..aa1e114b 100644 --- a/app/styles/modules/common/history.scss +++ b/app/styles/modules/common/history.scss @@ -39,12 +39,11 @@ } } .history-tabs { - @extend %title; + @extend %light; border-bottom: 1px solid $whitish; border-top: 1px solid $whitish; margin-bottom: 0; li { - @extend %large; background: $white; border-right: 1px solid $whitish; display: inline-block; @@ -74,6 +73,7 @@ .add-comment { @include cursor-progress; @include clearfix; + margin-top: 1rem; &.active { .button-green { display: block; From 04efa2eca428b12fa869c92ff1ddbfdd455c673d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Mon, 11 Apr 2016 08:46:13 +0200 Subject: [PATCH 09/47] Related tasks add visual cue --- app/modules/attachments/attachments.scss | 2 +- app/styles/modules/common/history.scss | 3 ++- app/styles/modules/common/related-tasks.scss | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/modules/attachments/attachments.scss b/app/modules/attachments/attachments.scss index 61b9e15f..64bd6660 100644 --- a/app/modules/attachments/attachments.scss +++ b/app/modules/attachments/attachments.scss @@ -1,5 +1,5 @@ .attachments { - margin-bottom: 2rem; + margin-bottom: 4rem; } .attachments-header { diff --git a/app/styles/modules/common/history.scss b/app/styles/modules/common/history.scss index aa1e114b..9cb43032 100644 --- a/app/styles/modules/common/history.scss +++ b/app/styles/modules/common/history.scss @@ -45,10 +45,11 @@ margin-bottom: 0; li { background: $white; - border-right: 1px solid $whitish; display: inline-block; position: relative; &.active { + border-left: 1px solid $whitish; + border-right: 1px solid $whitish; color: $primary; top: 1px; } diff --git a/app/styles/modules/common/related-tasks.scss b/app/styles/modules/common/related-tasks.scss index 241cb037..268fd5e3 100644 --- a/app/styles/modules/common/related-tasks.scss +++ b/app/styles/modules/common/related-tasks.scss @@ -183,6 +183,20 @@ } } } + .closed, + .closed:hover { + border-left: 10px solid $whitish; + color: $whitish; + a, + svg { + fill: $whitish; + } + .task-name a { + color: $whitish; + text-decoration: line-through; + + } + } .icon-iocaine { display: none; } From 43ff31d7e843699440645ed015908c14c7ea4955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Mon, 11 Apr 2016 09:51:54 +0200 Subject: [PATCH 10/47] Add loading in project transfer --- .../transfer-project.controller.coffee | 20 ++++++++++++++----- .../projects/transfer/transfer-project.jade | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/app/modules/projects/transfer/transfer-project.controller.coffee b/app/modules/projects/transfer/transfer-project.controller.coffee index 7e9bb914..39be19ab 100644 --- a/app/modules/projects/transfer/transfer-project.controller.coffee +++ b/app/modules/projects/transfer/transfer-project.controller.coffee @@ -29,9 +29,10 @@ class TransferProject "$tgNavUrls", "$translate", "$tgConfirm" + "$tgLoading" ] - constructor: (@routeParams, @projectService, @location, @authService, @currentUserService, @navUrls, @translate, @confirmService) -> + constructor: (@routeParams, @projectService, @location, @authService, @currentUserService, @navUrls, @translate, @confirmService, @loading) -> initialize: () -> @.projectId = @.project.get("id") @@ -72,22 +73,31 @@ class TransferProject @.validNumberOfMemberships = maxMemberships == null || @.project.get('total_memberships') <= maxMemberships - transferAccept: (token, reason) -> + transferAccept: (token, reason, $event) -> + target = angular.element($event.currentTarget) + currentLoading = @loading() + .target(target) + .start() return @projectService.transferAccept(@.project.get("id"), token, reason).then () => newUrl = @navUrls.resolve("project-admin-project-profile-details", { project: @.project.get("slug") }) + currentLoading.finish() @location.path(newUrl) @confirmService.notify("success", @translate.instant("ADMIN.PROJECT_TRANSFER.ACCEPTED_PROJECT_OWNERNSHIP"), '', 5000) - return - transferReject: (token, reason) -> + transferReject: (token, reason, $event) -> + target = $($event.target) + currentLoading = @loading() + .target(target) + .start() return @projectService.transferReject(@.project.get("id"), token, reason).then () => - newUrl = @navUrls.resolve("project-admin-project-profile-details", { + newUrl = @navUrls.resolve("home", { project: @project.get("slug") }) + currentLoading.finish() @location.path(newUrl) @confirmService.notify("success", @translate.instant("ADMIN.PROJECT_TRANSFER.REJECTED_PROJECT_OWNERNSHIP"), '', 5000) diff --git a/app/modules/projects/transfer/transfer-project.jade b/app/modules/projects/transfer/transfer-project.jade index 87f3ac12..681aa535 100644 --- a/app/modules/projects/transfer/transfer-project.jade +++ b/app/modules/projects/transfer/transfer-project.jade @@ -53,14 +53,14 @@ .transfer-project-options a.button.button-gray( - ng-click="vm.transferReject(vm.token, vm.reason)" + ng-click="vm.transferReject(vm.token, vm.reason, $event)" href="#" title="{{'ADMIN.PROJECT_TRANSFER.REJECT' | translate}}" translate="ADMIN.PROJECT_TRANSFER.REJECT" ) a.button.button-green( - ng-click="vm.transferAccept(vm.token, vm.reason)" + ng-click="vm.transferAccept(vm.token, vm.reason, $event)" href="#" title="{{'ADMIN.PROJECT_TRANSFER.ACCEPT' | translate}}" translate="ADMIN.PROJECT_TRANSFER.ACCEPT" From 384383ed986c70930502af5eb8859476dd837ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Mon, 11 Apr 2016 10:46:15 +0200 Subject: [PATCH 11/47] Improve background contrast for new sprints --- app/styles/modules/backlog/sprints.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/modules/backlog/sprints.scss b/app/styles/modules/backlog/sprints.scss index 7029229d..e2d11194 100644 --- a/app/styles/modules/backlog/sprints.scss +++ b/app/styles/modules/backlog/sprints.scss @@ -145,7 +145,7 @@ .sprint-table { .sprint-empty { @extend %light; - background: lighten($gray-light, 18%); + background: darken($whitish, 5%); border: 2px dashed lighten($gray-light, 10%); color: $gray; padding: 1rem; From 0ed5a1428a6b27cb7caf7288813ced1c99ee6867 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Wed, 30 Mar 2016 08:27:34 +0200 Subject: [PATCH 12/47] refactor svg icons --- app/coffee/modules/admin/memberships.coffee | 14 +- .../modules/admin/project-profile.coffee | 2 +- app/coffee/modules/admin/roles.coffee | 4 +- app/coffee/modules/auth.coffee | 7 + app/coffee/modules/backlog/filters.coffee | 15 +- app/coffee/modules/backlog/sprints.coffee | 2 +- app/coffee/modules/common.coffee | 69 ++++---- app/coffee/modules/common/confirm.coffee | 6 +- .../modules/common/custom-field-values.coffee | 2 +- app/coffee/modules/issues/list.coffee | 10 +- app/coffee/modules/kanban/main.coffee | 2 +- app/coffee/modules/related-tasks.coffee | 3 +- app/coffee/modules/taskboard/main.coffee | 6 +- app/coffee/utils.coffee | 7 + app/locales/taiga/locale-en.json | 1 + app/modules/attachments/attachment-list.scss | 2 + .../attachment/attachment-gallery.jade | 3 +- .../components/attachment/attachment.jade | 18 +- .../attachments-full/attachments-full.jade | 12 +- .../attachments-simple.jade | 9 +- .../live-announcement/live-announcement.jade | 5 +- .../live-announcement/live-announcement.scss | 5 +- .../components/project-menu/project-menu.jade | 55 +++--- .../components/vote-button/vote-button.jade | 6 +- .../watch-button/watch-button-ticket.jade | 15 +- .../components/watch-button/watch-button.jade | 6 +- .../discover-home-order-by.jade | 3 +- .../discover-search-bar.jade | 7 +- .../discover-search-list-header.jade | 9 +- .../featured-projects/featured-projects.jade | 15 +- .../components/highlighted/highlighted.jade | 17 +- .../components/highlighted/highlighted.scss | 5 - .../components/most-active/most-active.jade | 6 +- .../components/most-liked/most-liked.jade | 11 +- .../discover-search/discover-search.jade | 17 +- .../discover-search/discover-search.scss | 4 - app/modules/home/duties/duty.jade | 15 +- .../home/projects/home-project-list.jade | 38 +++-- .../dropdown-project-list.jade | 22 ++- .../navigation-bar/navigation-bar.jade | 16 +- .../profile-contacts/profile-contacts.jade | 3 +- .../profile/profile-favs/items/project.jade | 24 +-- .../profile/profile-favs/items/ticket.jade | 21 ++- .../profile/profile-favs/profile-favs.jade | 3 +- .../profile/profile-hints/profile-hints.jade | 3 +- .../profile-projects/profile-projects.jade | 18 +- .../profile-tab/profile-tab.directive.coffee | 1 - .../profile/profile-tabs/profile-tabs.jade | 3 +- .../like-project-button.jade | 3 +- .../watch-project-button.jade | 12 +- .../projects/listing/projects-listing.jade | 34 ++-- .../projects/listing/styles/project-list.scss | 12 +- .../projects/project/blocked-project.jade | 7 +- app/modules/projects/project/project.jade | 23 +-- .../projects/transfer/transfer-project.jade | 14 +- .../user-timeline-attachment.jade | 3 +- app/partials/admin/admin-project-export.jade | 3 +- app/partials/admin/admin-project-modules.jade | 27 ++- app/partials/admin/admin-project-profile.jade | 15 +- app/partials/admin/admin-project-reports.jade | 3 +- app/partials/admin/admin-roles.jade | 8 +- .../admin/admin-third-parties-bitbucket.jade | 6 +- .../admin/admin-third-parties-github.jade | 6 +- .../admin/admin-third-parties-gitlab.jade | 6 +- .../admin/admin-third-parties-webhooks.jade | 41 +++-- app/partials/admin/lightbox-add-members.jade | 13 +- .../admin/memberships-row-avatar.jade | 7 +- ....jade => memberships-warning-message.jade} | 0 app/partials/admin/project-csv.jade | 9 +- app/partials/backlog/backlog.jade | 9 +- app/partials/backlog/filter-selected.jade | 12 +- app/partials/backlog/sprint-header.jade | 18 +- .../common/components/add-button.jade | 3 +- .../common/components/assigned-to.jade | 11 +- .../common/components/block-button.jade | 6 +- .../common/components/delete-button.jade | 3 +- .../components/editable-description.jade | 12 +- .../common/components/editable-subject.jade | 13 +- app/partials/common/components/watchers.jade | 6 +- app/partials/common/components/wysiwyg.jade | 3 +- .../us-estimation-points-per-role.jade | 7 +- .../estimation/us-estimation-total.jade | 6 +- .../common/history/history-activity.jade | 15 +- app/partials/common/history/history-base.jade | 26 +-- .../history/history-deleted-comment.jade | 3 +- app/partials/common/lightbox-feedback.jade | 3 +- .../lightbox/lightbox-assigned-to-users.jade | 9 +- .../common/lightbox/lightbox-assigned-to.jade | 3 +- .../lightbox/lightbox-attachment-preview.jade | 3 +- .../common/lightbox/lightbox-block.jade | 4 +- .../lightbox/lightbox-change-owner.jade | 9 +- .../lightbox/lightbox-import-error.jade | 7 +- .../lightbox-leave-project-warning.jade | 8 +- .../lightbox/lightbox-request-ownership.jade | 4 +- .../common/lightbox/lightbox-users.jade | 4 +- app/partials/common/tag/lb-tag-line-tags.jade | 4 +- app/partials/common/tag/lb-tag-line.jade | 3 +- app/partials/common/tag/tag-line.jade | 6 +- app/partials/common/tag/tags-line-tags.jade | 4 +- .../wysiwyg/wysiwyg-markitup-preview.jade | 6 +- .../custom-attribute-value-edit.jade | 4 +- .../custom-attribute-value.jade | 4 +- .../custom-attributes-values.jade | 4 +- .../includes/components/addnewtask.jade | 23 ++- .../includes/components/addnewus.jade | 3 +- .../includes/components/backlog-row.jade | 20 +-- .../components/notification-message.jade | 14 +- .../includes/components/sprint-summary.jade | 11 +- app/partials/includes/components/summary.jade | 3 +- .../includes/components/taskboard-task.jade | 14 +- .../admin/admin-custom-attributes.jade | 101 +++++++----- .../modules/admin/project-points.jade | 35 ++-- .../modules/admin/project-status.jade | 41 +++-- .../includes/modules/admin/project-types.jade | 46 ++++-- .../modules/admin/project-us-status.jade | 46 ++++-- .../includes/modules/backlog-filters.jade | 15 +- .../includes/modules/backlog-table.jade | 3 +- .../includes/modules/issues-filters.jade | 78 +++++---- .../includes/modules/issues-options.jade | 3 +- .../includes/modules/issues-table.jade | 15 +- .../includes/modules/kanban-table.jade | 21 +-- .../includes/modules/lightbox-ask-choice.jade | 5 +- .../modules/lightbox-create-issue.jade | 8 +- .../modules/lightbox-delete-project.jade | 4 +- .../modules/lightbox-generic-ask.jade | 5 +- .../modules/lightbox-generic-error.jade | 8 +- .../modules/lightbox-generic-success.jade | 7 +- .../includes/modules/lightbox-issue-bulk.jade | 8 +- .../modules/lightbox-sprint-add-edit.jade | 12 +- .../includes/modules/lightbox-task-bulk.jade | 7 +- .../modules/lightbox-task-create-edit.jade | 10 +- .../includes/modules/lightbox-us-bulk.jade | 7 +- .../modules/lightbox-us-create-edit.jade | 10 +- app/partials/includes/modules/login-form.jade | 8 +- .../includes/modules/search-filter.jade | 12 +- app/partials/includes/modules/search-in.jade | 3 +- app/partials/includes/modules/sprints.jade | 6 +- .../includes/modules/taskboard-table.jade | 38 ++--- .../includes/modules/team/team-filters.jade | 6 +- app/partials/issue/iocaine-button.jade | 3 +- app/partials/issue/issue-priority-button.jade | 3 +- app/partials/issue/issue-severity-button.jade | 20 ++- app/partials/issue/issue-type-button.jade | 21 +-- app/partials/issue/issues-detail.jade | 68 +++++--- .../issue/issues-filters-selected.jade | 6 +- app/partials/issue/issues-filters.jade | 21 ++- app/partials/issue/issues-status-button.jade | 3 +- .../issue/promote-issue-to-us-button.jade | 4 +- app/partials/kanban/kanban-task.jade | 9 +- .../project/wizard-create-project.jade | 16 +- app/partials/project/wizard-restrictions.jade | 8 +- app/partials/search/lightbox-search.jade | 5 +- .../task/related-task-create-form.jade | 19 +-- app/partials/task/related-task-row-edit.jade | 31 ++-- app/partials/task/related-task-row.jade | 54 +++--- app/partials/task/task-detail.jade | 6 +- app/partials/team/leave-project.jade | 3 +- app/partials/team/team-filter.jade | 6 +- .../team/team-member-current-user.jade | 14 +- app/partials/team/team-member-stats.jade | 30 ++-- app/partials/team/team-members.jade | 5 +- .../us/us-client-requirement-button.jade | 3 +- app/partials/us/us-detail.jade | 6 +- app/partials/us/us-status-button.jade | 3 +- .../us/us-team-requirement-button.jade | 4 +- .../lightbox/lightbox-delete-account.jade | 5 +- app/partials/wiki/editable-wiki-content.jade | 27 ++- app/partials/wiki/wiki-nav.jade | 28 +++- app/partials/wiki/wiki.jade | 11 +- app/styles/components/editor-help.scss | 3 + app/styles/components/filter.scss | 23 +-- app/styles/components/kanban-task.scss | 19 ++- app/styles/components/list-items.scss | 2 + app/styles/components/looking-for-people.scss | 5 + app/styles/components/markitup.scss | 2 +- .../components/notification-message.scss | 10 +- app/styles/components/private.scss | 2 +- app/styles/components/summary.scss | 1 + app/styles/components/tag.scss | 11 +- app/styles/components/taskboard-task.scss | 13 +- app/styles/components/user-list.scss | 1 + app/styles/core/animation.scss | 14 -- app/styles/core/forms.scss | 24 ++- app/styles/dependencies/helpers.scss | 3 + app/styles/dependencies/mixins.scss | 1 - .../dependencies/mixins/project-card.scss | 5 - app/styles/layout/ticket-detail.scss | 16 +- app/styles/layout/wiki.scss | 48 +++--- .../admin/admin-custom-attributes.scss | 24 +-- .../modules/admin/admin-functionalities.scss | 12 +- app/styles/modules/admin/admin-roles.scss | 3 + .../admin/admin-third-parties-webhooks.scss | 9 +- app/styles/modules/admin/project-values.scss | 5 +- app/styles/modules/backlog/backlog-table.scss | 5 + app/styles/modules/backlog/sprints.scss | 8 +- .../modules/backlog/taskboard-table.scss | 80 +++++---- app/styles/modules/common/colors-table.scss | 6 +- app/styles/modules/common/custom-fields.scss | 7 +- app/styles/modules/common/history.scss | 14 +- app/styles/modules/common/related-tasks.scss | 156 +++++++----------- app/styles/modules/common/ticket-data.scss | 3 + app/styles/modules/common/wizard.scss | 2 +- app/styles/modules/filters/filters.scss | 9 +- app/styles/modules/issues/issues-table.scss | 3 + app/styles/modules/kanban/kanban-table.scss | 1 - app/styles/modules/wiki/wiki-nav.scss | 86 +++++----- app/styles/shame/shame.scss | 12 ++ conf.e2e.js | 96 ++++++----- e2e/helpers/admin-memberships.js | 4 +- e2e/helpers/issues-helper.js | 6 +- e2e/helpers/taskboard-helper.js | 8 +- e2e/helpers/wiki-helper.js | 2 +- e2e/shared/detail.js | 19 ++- e2e/suites/admin/project/create-delete.e2e.js | 8 +- e2e/suites/admin/project/modules.e2e.js | 23 ++- e2e/suites/issues/issue-detail.e2e.js | 2 +- e2e/suites/issues/issues.e2e.js | 9 +- e2e/suites/project-home.e2e.js | 1 + e2e/suites/wiki.e2e.js | 2 +- e2e/utils/common.js | 21 +-- e2e/utils/nav.js | 18 +- 221 files changed, 1560 insertions(+), 1446 deletions(-) rename app/partials/admin/{lightbox-add-members-no-more=memberships-warning-message.jade => memberships-warning-message.jade} (100%) create mode 100644 app/styles/components/looking-for-people.scss diff --git a/app/coffee/modules/admin/memberships.coffee b/app/coffee/modules/admin/memberships.coffee index 4a1da796..e0404170 100644 --- a/app/coffee/modules/admin/memberships.coffee +++ b/app/coffee/modules/admin/memberships.coffee @@ -240,7 +240,7 @@ module.directive("tgMemberships", ["$tgTemplate", "$compile", MembershipsDirecti ## Member Avatar Directive ############################################################################# -MembershipsRowAvatarDirective = ($log, $template, $translate) -> +MembershipsRowAvatarDirective = ($log, $template, $translate, $compile) -> template = $template.get("admin/memberships-row-avatar.html", true) link = ($scope, $el, $attrs) -> @@ -255,6 +255,8 @@ MembershipsRowAvatarDirective = ($log, $template, $translate) -> } html = template(ctx) + html = $compile(html)($scope) + $el.html(html) if not $attrs.tgMembershipsRowAvatar? @@ -269,7 +271,7 @@ MembershipsRowAvatarDirective = ($log, $template, $translate) -> return {link: link} -module.directive("tgMembershipsRowAvatar", ["$log", "$tgTemplate", '$translate', MembershipsRowAvatarDirective]) +module.directive("tgMembershipsRowAvatar", ["$log", "$tgTemplate", '$translate', "$compile", MembershipsRowAvatarDirective]) ############################################################################# @@ -393,9 +395,7 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm, $compile, $transla - - - + """ @@ -406,9 +406,7 @@ MembershipsRowActionsDirective = ($log, $repo, $rs, $confirm, $compile, $transla - - - + """ diff --git a/app/coffee/modules/admin/project-profile.coffee b/app/coffee/modules/admin/project-profile.coffee index 5959330f..7bc7efbf 100644 --- a/app/coffee/modules/admin/project-profile.coffee +++ b/app/coffee/modules/admin/project-profile.coffee @@ -228,7 +228,7 @@ ProjectModulesDirective = ($repo, $confirm, $loading, projectService) -> event.preventDefault() submit() - $el.on "click", ".icon-save", (event) -> + $el.on "click", ".save", (event) -> event.preventDefault() submit() diff --git a/app/coffee/modules/admin/roles.coffee b/app/coffee/modules/admin/roles.coffee index f6d3ecff..fe49c8d2 100644 --- a/app/coffee/modules/admin/roles.coffee +++ b/app/coffee/modules/admin/roles.coffee @@ -292,9 +292,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm, $compile) -> title="{{ '<%- permission.name %>' | translate }}"> <% }) %> - - - + """) categoryTemplate = _.template(""" diff --git a/app/coffee/modules/auth.coffee b/app/coffee/modules/auth.coffee index 5267c509..a2e66632 100644 --- a/app/coffee/modules/auth.coffee +++ b/app/coffee/modules/auth.coffee @@ -275,6 +275,13 @@ LoginDirective = ($auth, $confirm, $location, $config, $routeParams, $navUrls, $ onError = (response) -> $confirm.notify("light-error", $translate.instant("LOGIN_FORM.ERROR_AUTH_INCORRECT")) + $scope.onKeyUp = (event) -> + target = angular.element(event.currentTarget) + value = target.val() + $scope.iscapsLockActivated = false + if value != value.toLowerCase() + $scope.iscapsLockActivated = true + submit = debounce 2000, (event) => event.preventDefault() diff --git a/app/coffee/modules/backlog/filters.coffee b/app/coffee/modules/backlog/filters.coffee index b114ac14..685e2619 100644 --- a/app/coffee/modules/backlog/filters.coffee +++ b/app/coffee/modules/backlog/filters.coffee @@ -38,9 +38,9 @@ module = angular.module("taigaBacklog") ## Issues Filters Directive ############################################################################# -BacklogFiltersDirective = ($q, $log, $location, $templates) -> - template = $templates.get("backlog/filters.html", true) - templateSelected = $templates.get("backlog/filter-selected.html", true) +BacklogFiltersDirective = ($q, $log, $location, $template, $compile) -> + template = $template.get("backlog/filters.html", true) + templateSelected = $template.get("backlog/filter-selected.html", true) link = ($scope, $el, $attrs) -> currentFiltersType = '' @@ -78,6 +78,8 @@ BacklogFiltersDirective = ($q, $log, $location, $templates) -> f.style = "border-left: 3px solid #{f.color}" html = templateSelected({filters: selectedFilters}) + html = $compile(html)($scope) + $el.find(".filters-applied").html(html) renderFilters = (filters) -> @@ -86,6 +88,7 @@ BacklogFiltersDirective = ($q, $log, $location, $templates) -> f.style = "border-left: 3px solid #{f.color}" html = template({filters:filters}) + html = $compile(html)($scope) $el.find(".filter-list").html(html) getFiltersType = () -> @@ -158,9 +161,9 @@ BacklogFiltersDirective = ($q, $log, $location, $templates) -> event.preventDefault() showCategories() - $el.on "click", ".filters-applied a", (event) -> + $el.on "click", ".remove-filter", (event) -> event.preventDefault() - target = angular.element(event.currentTarget) + target = angular.element(event.currentTarget).parent() id = target.data("id") type = target.data("type") toggleFilterSelection(type, id) @@ -179,4 +182,4 @@ BacklogFiltersDirective = ($q, $log, $location, $templates) -> return {link:link} -module.directive("tgBacklogFilters", ["$q", "$log", "$tgLocation", "$tgTemplate", BacklogFiltersDirective]) +module.directive("tgBacklogFilters", ["$q", "$log", "$tgLocation", "$tgTemplate", "$compile", BacklogFiltersDirective]) diff --git a/app/coffee/modules/backlog/sprints.coffee b/app/coffee/modules/backlog/sprints.coffee index 2ea49705..fb7ee961 100644 --- a/app/coffee/modules/backlog/sprints.coffee +++ b/app/coffee/modules/backlog/sprints.coffee @@ -62,7 +62,7 @@ BacklogSprintDirective = ($repo, $rootscope) -> $el.find(".sprint-table").slideToggle(slideOptions) - $el.on "click", ".sprint-name > .icon-edit", (event) -> + $el.on "click", ".edit-sprint", (event) -> event.preventDefault() sprint = $scope.$eval($attrs.tgBacklogSprint) diff --git a/app/coffee/modules/common.coffee b/app/coffee/modules/common.coffee index f8f9f237..a08eeca1 100644 --- a/app/coffee/modules/common.coffee +++ b/app/coffee/modules/common.coffee @@ -284,39 +284,52 @@ module.factory("$tgTemplate", ["$templateCache", Template]) ## Permission directive, hide elements when necessary ############################################################################# -Capslock = ($translate) -> - link = ($scope, $el, $attrs) -> - open = false +Capslock = () -> + template = """ + + """ + return { + template: template + } - warningIcon = ""; +module.directive("tgCapslock", [Capslock]) - hideIcon = () -> - $('.icon-capslock').fadeOut () -> - open = false +LightboxClose = () -> + template = """ + + + + """ - $(this).remove() + return { + template: template + } - showIcon = (e) -> - return if open - element = e.currentTarget - $(element).parent().append(warningIcon) - $('.icon-capslock').fadeIn() +module.directive("tgLightboxClose", [LightboxClose]) - open = true +Svg = () -> + template = """ + + + {{svgTitle}} + + + + """ - $el.on 'blur', (e) -> - hideIcon() + return { + scope: { + svgIcon: "@", + svgTitle: "@", + svgTitleTranslate: "@", + svgTitleTranslateValues: "=" + }, + template: template + } - $el.on 'keyup.capslock, focus', (e) -> - if $el.val() == $el.val().toLowerCase() - hideIcon(e) - else - showIcon(e) - - $scope.$on "$destroy", -> - $el.off('.capslock') - - return {link:link} - -module.directive("tgCapslock", ["$translate", Capslock]) +module.directive("tgSvg", [Svg]) diff --git a/app/coffee/modules/common/confirm.coffee b/app/coffee/modules/common/confirm.coffee index bb62cb60..bb8ff5ef 100644 --- a/app/coffee/modules/common/confirm.coffee +++ b/app/coffee/modules/common/confirm.coffee @@ -177,9 +177,9 @@ class ConfirmService extends taiga.Service useSVG.setAttributeNS('http://www.w3.org/1999/xlink','href', '#' + icon.name) detailImage = document.createElementNS("http://www.w3.org/2000/svg", "svg") - detailImage.classList.add("icon") - detailImage.classList.add("lb-icon") - detailImage.classList.add(icon.name) + taiga.addClass(detailImage, "icon") + taiga.addClass(detailImage, "lb-icon") + taiga.addClass(detailImage, icon.name) detailImage.appendChild(useSVG) if detailImage diff --git a/app/coffee/modules/common/custom-field-values.coffee b/app/coffee/modules/common/custom-field-values.coffee index 897cfe24..ad3e8049 100644 --- a/app/coffee/modules/common/custom-field-values.coffee +++ b/app/coffee/modules/common/custom-field-values.coffee @@ -117,7 +117,7 @@ CustomAttributesValuesDirective = ($templates, $storage) -> $ctrl.initialize($attrs.type, value.id) $ctrl.loadCustomAttributesValues() - $el.on "click", ".custom-fields-header .icon", -> + $el.on "click", ".custom-fields-header .collapse", -> hash = collapsedHash($attrs.type) collapsed = not($storage.get(hash) or false) $storage.set(hash, collapsed) diff --git a/app/coffee/modules/issues/list.coffee b/app/coffee/modules/issues/list.coffee index 132e5ab1..21ab8c3a 100644 --- a/app/coffee/modules/issues/list.coffee +++ b/app/coffee/modules/issues/list.coffee @@ -584,20 +584,20 @@ IssuesFiltersDirective = ($q, $log, $location, $rs, $confirm, $loading, $templat unwatchIssues() # Dom Event Handlers - $el.on "click", ".filters-cats > ul > li > a", (event) -> + $el.on "click", ".filters-cat-single", (event) -> event.preventDefault() target = angular.element(event.currentTarget) tags = $scope.filters[target.data("type")] renderFilters(_.reject(tags, "selected")) showFilters(target.attr("title"), target.data("type")) - $el.on "click", ".filters-inner > .filters-step-cat > .breadcrumb > .back", (event) -> + $el.on "click", ".back", (event) -> event.preventDefault() showCategories($el) - $el.on "click", ".filters-applied a", (event) -> + $el.on "click", ".filters-applied .remove-filter", (event) -> event.preventDefault() - target = angular.element(event.currentTarget) + target = angular.element(event.currentTarget).parent() id = target.data("id") or null type = target.data("type") @@ -617,7 +617,7 @@ IssuesFiltersDirective = ($q, $log, $location, $rs, $confirm, $loading, $templat toggleFilterSelection(type, id) - $el.on "click", ".filter-list .single-filter .remove-filter", (event) -> + $el.on "click", ".filter-list .remove-filter", (event) -> event.preventDefault() event.stopPropagation() diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee index f4edca5e..94484ba2 100644 --- a/app/coffee/modules/kanban/main.coffee +++ b/app/coffee/modules/kanban/main.coffee @@ -426,7 +426,7 @@ KanbanUserstoryDirective = ($rootscope, $loading, $rs, $rs2) -> else if not us.is_blocked and $el.hasClass("blocked") $el.removeClass("blocked") - $el.on 'click', '.icon-edit', (event) -> + $el.on 'click', '.edit-us', (event) -> if $el.find(".icon-edit").hasClass("noclick") return diff --git a/app/coffee/modules/related-tasks.coffee b/app/coffee/modules/related-tasks.coffee index 9095773f..9fbc4dfe 100644 --- a/app/coffee/modules/related-tasks.coffee +++ b/app/coffee/modules/related-tasks.coffee @@ -151,6 +151,7 @@ RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, return promise close = () -> + $el.removeClass('active') $el.off() $el.html("") @@ -173,7 +174,7 @@ RelatedTaskCreateFormDirective = ($repo, $compile, $confirm, $tgmodel, $loading, $el.on "click", ".icon-close", (event)-> $scope.$apply () -> close() - $el.on "click", ".icon-save", (event)-> + $el.on "click", ".save-task", (event)-> createTask(newTask).then -> close() diff --git a/app/coffee/modules/taskboard/main.coffee b/app/coffee/modules/taskboard/main.coffee index 757a0320..11dc0486 100644 --- a/app/coffee/modules/taskboard/main.coffee +++ b/app/coffee/modules/taskboard/main.coffee @@ -317,16 +317,16 @@ TaskboardTaskDirective = ($rootscope, $loading, $rs, $rs2) -> else if not task.is_blocked and $el.hasClass("blocked") $el.removeClass("blocked") - $el.find(".icon-edit").on "click", (event) -> - if $el.find('.icon-edit').hasClass('noclick') + $el.find(".edit-task").on "click", (event) -> + if $el.find('.edit-task').hasClass('noclick') return + $scope.$apply -> target = $(event.target) currentLoading = $loading() .target(target) .timeout(200) - .removeClasses("icon-edit") .start() task = $scope.task diff --git a/app/coffee/utils.coffee b/app/coffee/utils.coffee index 443bac59..a8ec6979 100644 --- a/app/coffee/utils.coffee +++ b/app/coffee/utils.coffee @@ -22,6 +22,12 @@ # File: utils.coffee ### +addClass = (el, className) -> + if (el.classList) + el.classList.add(className) + else + el.className += ' ' + className + nl2br = (str) => breakTag = '
' return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2') @@ -222,6 +228,7 @@ patch = (oldImmutable, newImmutable) -> return pathObj taiga = @.taiga +taiga.addClass = addClass taiga.nl2br = nl2br taiga.bindMethods = bindMethods taiga.bindOnce = bindOnce diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json index d2650ab2..dd95fec7 100644 --- a/app/locales/taiga/locale-en.json +++ b/app/locales/taiga/locale-en.json @@ -1413,6 +1413,7 @@ "PLACEHOLDER_PAGE": "Write your wiki page", "REMOVE": "Remove this wiki page", "DELETE_LIGHTBOX_TITLE": "Delete Wiki Page", + "DELETE_LINK_TITLE": "Delete Wiki link", "NAVIGATION": { "SECTION_NAME": "Links", "ACTION_ADD_LINK": "Add link" diff --git a/app/modules/attachments/attachment-list.scss b/app/modules/attachments/attachment-list.scss index df533f2b..7d1b66ae 100644 --- a/app/modules/attachments/attachment-list.scss +++ b/app/modules/attachments/attachment-list.scss @@ -51,10 +51,12 @@ opacity: 0; } .editable-settings { + display: block; opacity: 1; } svg { fill: $gray-light; + pointer-events: none; } .icon-edit, .icon-save { diff --git a/app/modules/components/attachment/attachment-gallery.jade b/app/modules/components/attachment/attachment-gallery.jade index b6c560a1..eda74610 100644 --- a/app/modules/components/attachment/attachment-gallery.jade +++ b/app/modules/components/attachment/attachment-gallery.jade @@ -34,5 +34,4 @@ title="{{'COMMON.DELETE' | translate}}" ng-click="vm.delete()" ) - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") diff --git a/app/modules/components/attachment/attachment.jade b/app/modules/components/attachment/attachment.jade index b0207960..16c99d8f 100644 --- a/app/modules/components/attachment/attachment.jade +++ b/app/modules/components/attachment/attachment.jade @@ -12,8 +12,7 @@ form.single-attachment( target="_blank" download="{{::vm.attachment.getIn(['file', 'name'])}}" ) - svg.icon.icon-attachment - use(xlink:href="#icon-attachment") + tg-svg(svg-icon="icon-attachment") span {{::vm.attachment.getIn(['file', 'name'])}} .attachment-comments(ng-if="!vm.attachment.get('editable') && vm.attachment.getIn(['file', 'description'])") @@ -52,8 +51,7 @@ form.single-attachment( title="{{'COMMON.SAVE' | translate}}" ng-click="vm.save()" ) - svg.drag.icon.icon-save - use(xlink:href="#icon-save") + tg-svg(svg-icon="icon-save") div a.editable-settings( @@ -61,8 +59,7 @@ form.single-attachment( title="{{'COMMON.CANCEL' | translate}}" ng-click="vm.editMode(false)" ) - svg.drag.icon.icon-close - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") .attachment-settings( ng-if="!vm.attachment.get('editable')" @@ -73,18 +70,15 @@ form.single-attachment( title="{{'COMMON.EDIT' | translate}}" ng-click="vm.editMode(true)" ) - svg.drag.icon.icon-edit - use(xlink:href="#icon-edit") + tg-svg.drag(svg-icon="icon-edit") a.settings( href="" title="{{'COMMON.DELETE' | translate}}" ng-click="vm.delete()" ) - svg.drag.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg.drag(svg-icon="icon-trash") a.settings( href="" title="{{'COMMON.DRAG' | translate}}" ) - svg.drag.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg.drag(svg-icon="icon-drag") diff --git a/app/modules/components/attachments-full/attachments-full.jade b/app/modules/components/attachments-full/attachments-full.jade index 1e4e58aa..d441def1 100644 --- a/app/modules/components/attachments-full/attachments-full.jade +++ b/app/modules/components/attachments-full/attachments-full.jade @@ -11,24 +11,21 @@ section.attachments( ng-click="vm.setMode('gallery')" title="{{ 'ATTACHMENT.GALLERY_VIEW_MODE' | translate }}" ) - svg.icon.icon-gallery - use(xlink:href="#icon-gallery") + tg-svg(svg-icon="icon-gallery") button.view-list( ng-class="{'is-active': vm.mode == 'list'}" ng-if="vm.attachments.size" ng-click="vm.setMode('list')" title="{{ 'ATTACHMENT.LIST_VIEW_MODE' | translate }}" ) - svg.icon.icon-list - use(xlink:href="#icon-list") + tg-svg(svg-icon="icon-list") .add-attach( tg-check-permission="modify_{{vm.type}}" title!="{{'ATTACHMENT.ADD' | translate}}" ) label.add-attachment-button(for="add-attach") - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") input( id="add-attach", @@ -55,8 +52,7 @@ section.attachments( .single-attachment(ng-repeat="file in vm.uploadingAttachments()") .attachment-name - svg.icon.icon-attachment - use(xlink:href="#icon-attachment") + tg-svg(svg-icon="icon-attachment") span {{file.name}} .attachment-size span {{file.size | sizeFormat}} diff --git a/app/modules/components/attachments-simple/attachments-simple.jade b/app/modules/components/attachments-simple/attachments-simple.jade index 9b4cdcc7..ca458d4a 100644 --- a/app/modules/components/attachments-simple/attachments-simple.jade +++ b/app/modules/components/attachments-simple/attachments-simple.jade @@ -5,8 +5,7 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files)") h3.attachments-title #[span.attachments-num {{vm.attachments.size}}] #[span.attachments-text(translate="ATTACHMENT.SECTION_NAME")] .add-attach(title!="{{'ATTACHMENT.ADD' | translate}}") label.add-attachment-button(for="add-attach") - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") input( id="add-attach" type="file" @@ -19,8 +18,7 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files)") .attachment-body.attachment-list .single-attachment(tg-repeat="attachment in vm.attachments track by $index") .attachment-name - svg.icon.icon-attachment - use(xlink:href="#icon-attachment") + tg-svg(svg-icon="icon-attachment") span {{attachment.get('name')}} .attachment-size span {{attachment.get('size') | sizeFormat}} @@ -31,5 +29,4 @@ section.attachments(tg-attachments-drop="vm.addAttachments(files)") title="{{'COMMON.DELETE' | translate}}" ng-click="vm.deleteAttachment(attachment)" ) - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") diff --git a/app/modules/components/live-announcement/live-announcement.jade b/app/modules/components/live-announcement/live-announcement.jade index 1c2a4225..d740640b 100644 --- a/app/modules/components/live-announcement/live-announcement.jade +++ b/app/modules/components/live-announcement/live-announcement.jade @@ -7,7 +7,6 @@ a.close( ng-click="vm.close()" href="" - title="{{ COMMON.CLOSE | translate }}" + ng-title="COMMON.CLOSE | translate" ) - svg.icon.icon-close - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") diff --git a/app/modules/components/live-announcement/live-announcement.scss b/app/modules/components/live-announcement/live-announcement.scss index d30cdd00..f1b7964e 100644 --- a/app/modules/components/live-announcement/live-announcement.scss +++ b/app/modules/components/live-announcement/live-announcement.scss @@ -56,13 +56,14 @@ } } .close { - height: 2.5rem; + display: block; position: absolute; right: 0; top: 1rem; - width: 2.5rem; svg { + @include svg-size(2rem); fill: lighten($tribe-secondary, 15%); + pointer-events: none; transition: fill .2s; &:hover { fill: $tribe-secondary; diff --git a/app/modules/components/project-menu/project-menu.jade b/app/modules/components/project-menu/project-menu.jade index 6b845c6e..ddb4e109 100644 --- a/app/modules/components/project-menu/project-menu.jade +++ b/app/modules/components/project-menu/project-menu.jade @@ -1,105 +1,96 @@ nav.menu( ng-if="vm.project" ng-class="{'menu-fixed': vm.fixed}", -) - div(class="menu-container") - ul(class="main-nav") - li(id="nav-search") +) + .menu-container + ul.main-nav + li#nav-search a( href="" ng-click="vm.search()" ng-class="{active: vm.active == 'search'}" aria-label="{{'PROJECT.SECTION.SEARCH' | translate}}" tabindex="1" - ) - svg.icon.icon-search - use(xlink:href="#icon-search") - span.helper(translate="PROJECT.SECTION.SEARCH") + ) + tg-svg(svg-icon="icon-search") + span.helper(translate="PROJECT.SECTION.SEARCH") - li(id="nav-timeline") + li#nav-timeline a( tg-nav="project:project=vm.project.get('slug')" ng-class="{active: vm.active == 'project-timeline'}" aria-label="{{'PROJECT.SECTION.TIMELINE' | translate}}" tabindex="2" ) - svg.icon.icon-timeline - use(xlink:href="#icon-timeline") + tg-svg(svg-icon="icon-timeline") span.helper(translate="PROJECT.SECTION.TIMELINE") - li(id="nav-backlog", ng-if="vm.menu.get('backlog')") + li#nav-backlog(ng-if="vm.menu.get('backlog')") a( tg-nav="project-backlog:project=vm.project.get('slug')" ng-class="{active: vm.active == 'backlog'}" aria-label="{{'PROJECT.SECTION.BACKLOG' | translate}}" tabindex="2" ) - svg.icon.icon-scrum - use(xlink:href="#icon-scrum") + tg-svg(svg-icon="icon-scrum") span.helper(translate="PROJECT.SECTION.BACKLOG") - li(id="nav-kanban", ng-if="vm.menu.get('kanban')") + li#nav-kanban(ng-if="vm.menu.get('kanban')") a( tg-nav="project-kanban:project=vm.project.get('slug')" ng-class="{active: vm.active == 'kanban'}" aria-label="{{'PROJECT.SECTION.KANBAN' | translate}}" tabindex="3" ) - svg.icon.icon-kanban - use(xlink:href="#icon-kanban") + tg-svg(svg-icon="icon-kanban") span.helper(translate="PROJECT.SECTION.KANBAN") - li(id="nav-issues", ng-if="vm.menu.get('issues')") + li#nav-issues(ng-if="vm.menu.get('issues')") a( tg-nav="project-issues:project=vm.project.get('slug')" ng-class="{active: vm.active == 'issues'}" aria-label="{{'PROJECT.SECTION.ISSUES' | translate}}" tabindex="4" ) - svg.icon.icon-issues - use(xlink:href="#icon-issues") + tg-svg(svg-icon="icon-issues") span.helper(translate="PROJECT.SECTION.ISSUES") - li(id="nav-wiki", ng-if="vm.menu.get('wiki')") + li#nav-wiki(ng-if="vm.menu.get('wiki')") a( tg-nav="project-wiki:project=vm.project.get('slug')" ng-class="{active: vm.active == 'wiki'}" aria-label="{{'PROJECT.SECTION.WIKI' | translate}}" tabindex="5" ) - svg.icon.icon-wiki - use(xlink:href="#icon-wiki") + tg-svg(svg-icon="icon-wiki") span.helper(translate="PROJECT.SECTION.WIKI") - li(id="nav-team") + li#nav-team a( tg-nav="project-team:project=vm.project.get('slug')" ng-class="{active: vm.active == 'team'}" aria-label="{{'PROJECT.SECTION.TEAM' | translate}}" tabindex="6" ) - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span.helper(translate="PROJECT.SECTION.TEAM") - li(id="nav-video", ng-if="vm.project.get('videoconferenceUrl')") + li#nav-video(ng-if="vm.project.get('videoconferenceUrl')") a( ng-href="{{vm.project.get('videoconferenceUrl')}}" target="_blank" aria-label="{{'PROJECT.SECTION.MEETUP' | translate}}" tabindex="7" ) - svg.icon.icon-bubble - use(xlink:href="#icon-bubble") + tg-svg(svg-icon="icon-bubble") span.helper(translate="PROJECT.SECTION.MEETUP") - li(id="nav-admin", ng-if="vm.project.get('i_am_admin')") + li#nav-admin(ng-if="vm.project.get('i_am_admin')") a( tg-nav="project-admin-home:project=vm.project.get('slug')" ng-class="{active: vm.active == 'admin'}" aria-label="{{'PROJECT.SECTION.ADMIN' | translate}}" tabindex="8" ) - svg.icon.icon-settings - use(xlink:href="#icon-settings") + tg-svg(svg-icon="icon-settings") span.helper(translate="PROJECT.SECTION.ADMIN") diff --git a/app/modules/components/vote-button/vote-button.jade b/app/modules/components/vote-button/vote-button.jade index f0b07a4c..3ae180ac 100644 --- a/app/modules/components/vote-button/vote-button.jade +++ b/app/modules/components/vote-button/vote-button.jade @@ -9,8 +9,7 @@ a.vote-inner( ng-mouseleave="vm.showTextWhenMouseIsLeave()" ) span.track-icon - svg.icon.icon-upvote - use(xlink:href="#icon-upvote") + tg-svg(svg-icon="icon-upvote") span.track-button-counter( title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.total_voters||0}:'messageformat' }}", tg-loading="vm.loading" @@ -19,8 +18,7 @@ a.vote-inner( //- Anonymous user button span.vote-inner(ng-if="::!vm.user") span.track-icon - svg.icon.icon-upvote - use(xlink:href="#icon-upvote") + tg-svg(svg-icon="icon-watch") span.track-button-counter( title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.total_voters||0}:'messageformat' }}" ) {{ ::vm.item.total_voters }} diff --git a/app/modules/components/watch-button/watch-button-ticket.jade b/app/modules/components/watch-button/watch-button-ticket.jade index 661be69b..0b802110 100644 --- a/app/modules/components/watch-button/watch-button-ticket.jade +++ b/app/modules/components/watch-button/watch-button-ticket.jade @@ -14,17 +14,14 @@ div.ticket-watch-inner ng-mouseleave="vm.showTextWhenMouseIsLeave()" ) span(ng-if="!vm.item.is_watcher") - svg.icon.icon-watch - use(xlink:href="#icon-watch") - | {{'COMMON.WATCH_BUTTON.WATCH' | translate}} + tg-svg(svg-icon="icon-watch") + span {{'COMMON.WATCH_BUTTON.WATCH' | translate}} span(ng-if="vm.item.is_watcher && !vm.isMouseOver",) - svg.icon.icon-watch - use(xlink:href="#icon-watch") - | {{'COMMON.WATCH_BUTTON.WATCHING' | translate}} + tg-svg(svg-icon="icon-watch") + span {{'COMMON.WATCH_BUTTON.WATCHING' | translate}} span(ng-if="vm.item.is_watcher && vm.isMouseOver") - svg.icon.icon-unwatch - use(xlink:href="#icon-unwatch") - | {{'COMMON.WATCH_BUTTON.UNWATCH' | translate}} + tg-svg(svg-icon="icon-unwatch") + span {{'COMMON.WATCH_BUTTON.UNWATCH' | translate}} a.add-watcher( href="" diff --git a/app/modules/components/watch-button/watch-button.jade b/app/modules/components/watch-button/watch-button.jade index 842f0d60..36e550d3 100644 --- a/app/modules/components/watch-button/watch-button.jade +++ b/app/modules/components/watch-button/watch-button.jade @@ -16,8 +16,7 @@ a.track-button.watch-button.watch-container( ng-mouseleave="vm.showTextWhenMouseIsLeave()" ) span.track-inner - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span( ng-if="!vm.item.is_watcher", translate="COMMON.WATCH_BUTTON.WATCH" @@ -38,7 +37,6 @@ span.track-button.watch-button.watch-container( ) span.track-inner span.track-icon - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span(translate="COMMON.WATCH_BUTTON.WATCHERS") +counter diff --git a/app/modules/discover/components/discover-home-order-by/discover-home-order-by.jade b/app/modules/discover/components/discover-home-order-by/discover-home-order-by.jade index 9379c7d0..40405343 100644 --- a/app/modules/discover/components/discover-home-order-by/discover-home-order-by.jade +++ b/app/modules/discover/components/discover-home-order-by/discover-home-order-by.jade @@ -3,8 +3,7 @@ href="#" ng-click="vm.open()" ) {{vm.currentText()}} - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") ul.filter-list(ng-if="vm.is_open") li(ng-click="vm.orderBy('week')") {{ 'DISCOVER.FILTERS.WEEK' | translate }} diff --git a/app/modules/discover/components/discover-search-bar/discover-search-bar.jade b/app/modules/discover/components/discover-search-bar/discover-search-bar.jade index 436c92af..7fd4157e 100644 --- a/app/modules/discover/components/discover-search-bar/discover-search-bar.jade +++ b/app/modules/discover/components/discover-search-bar/discover-search-bar.jade @@ -18,12 +18,11 @@ div.discover-header placeholder="{{ 'DISCOVER.SEARCH.INPUT_PLACEHOLDER' | translate }}" ng-model="vm.q" ) - svg.search-button.icon.icon-search( + tg-svg.search-button( ng-click="vm.submitFilter()" - href="#" - title="{{ 'DISCOVER.SEARCH.ACTION_TITLE' | translate }}" + svg-icon="icon-search" + svg-title-translate="DISCOVER.SEARCH.ACTION_TITLE" ) - use(xlink:href="#icon-search") fieldset.searchbox-filters(ng-if="vm.filter") input( diff --git a/app/modules/discover/components/discover-search-list-header/discover-search-list-header.jade b/app/modules/discover/components/discover-search-list-header/discover-search-list-header.jade index 42c854fb..123c0d84 100644 --- a/app/modules/discover/components/discover-search-list-header/discover-search-list-header.jade +++ b/app/modules/discover/components/discover-search-list-header/discover-search-list-header.jade @@ -1,8 +1,7 @@ .discover-results-header .discover-results-header-inner .title - svg.icon.icon-search - use(xlink:href="#icon-search") + tg-svg(svg-icon="icon-search") h2 {{ 'DISCOVER.SEARCH.RESULTS' | translate }} .filter-discover-search(ng-mouseleave="vm.toggleClose()") @@ -11,16 +10,14 @@ ng-click="vm.openLike()" ng-class="{active: vm.like_is_open}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{ 'DISCOVER.MOST_LIKED' | translate }} a.discover-search-filter( href="#" ng-click="vm.openActivity()" ng-class="{active: vm.activity_is_open}" ) - svg.icon.icon-activity - use(xlink:href="#icon-activity") + tg-svg(svg-icon="icon-activity") span {{ 'DISCOVER.MOST_ACTIVE' | translate }} .discover-search-subfilter.most-liked-subfilter(ng-if="vm.like_is_open") diff --git a/app/modules/discover/components/featured-projects/featured-projects.jade b/app/modules/discover/components/featured-projects/featured-projects.jade index 6811847e..f2450bd2 100644 --- a/app/modules/discover/components/featured-projects/featured-projects.jade +++ b/app/modules/discover/components/featured-projects/featured-projects.jade @@ -26,31 +26,28 @@ tg-nav="project:project=project.get('slug')" title="{{::project.get('name')}}" ) {{::project.get('name')}} - svg.look-for-people.icon.icon-recruit( + tg-svg.look-for-people( ng-if="project.get('is_looking_for_people')" + svg-icon="icon-recruit" + svg-title="{{ ::project.get('looking_for_people_note') }}" ) - use(xlink:href="#icon-recruit") - title="{{ ::project.get('looking_for_people_note') }}" p.project-card-description {{ ::project.get('description') | limitTo:100 }}{{ ::project.get('description').length < 100 ? '' : '...'}} .project-card-statistics span.statistic( ng-class="{'active': project.get('is_fan')}" title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{::project.get('total_fans')}} span.statistic( ng-class="{'active': project.get('is_watcher')}" title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{::project.get('total_watchers')}} span.statistic( ng-class="{'active': project.get('i_am_member')}" title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}" ) - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span.statistics-num {{ ::project.get('members').size }} diff --git a/app/modules/discover/components/highlighted/highlighted.jade b/app/modules/discover/components/highlighted/highlighted.jade index 3f29e101..08cd39a0 100644 --- a/app/modules/discover/components/highlighted/highlighted.jade +++ b/app/modules/discover/components/highlighted/highlighted.jade @@ -24,30 +24,29 @@ tg-nav="project:project=project.get('slug')" title="{{::project.get('name')}}" ) {{::project.get('name')}} - 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') }}" + tg-svg.look-for-people( + ng-if="project.get('is_looking_for_people')" + svg-icon="icon-recruit" + svg-title="{{ ::project.get('looking_for_people_note') }}" + ) .project-statistics span.statistic( ng-class="{'active': project.get('is_fan')}" title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{::project.get('total_fans')}} span.statistic( ng-class="{'active': project.get('is_watcher')}" title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{::project.get('total_watchers')}} span.statistic( ng-class="{'active': project.get('i_am_member')}" title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}" ) - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span.statistics-num {{ ::project.get('members').size }} p.project-description {{ ::project.get('description') | limitTo:150 }}{{ ::project.get('description').length < 150 ? '' : '...'}} diff --git a/app/modules/discover/components/highlighted/highlighted.scss b/app/modules/discover/components/highlighted/highlighted.scss index 8dced746..c54e6111 100644 --- a/app/modules/discover/components/highlighted/highlighted.scss +++ b/app/modules/discover/components/highlighted/highlighted.scss @@ -172,11 +172,6 @@ } } } - .look-for-people { - @include svg-size(); - fill: $gray-light; - margin-left: .5rem; - } .project-description { @extend %small; color: $gray; diff --git a/app/modules/discover/components/most-active/most-active.jade b/app/modules/discover/components/most-active/most-active.jade index e90666af..c439f840 100644 --- a/app/modules/discover/components/most-active/most-active.jade +++ b/app/modules/discover/components/most-active/most-active.jade @@ -1,8 +1,7 @@ .most-active(ng-if="vm.highlighted.size") .header .title-wrapper - svg.icon.icon-activity - use(xlink:href="#icon-activity") + tg-svg(svg-icon="icon-activity") h1.title {{ 'DISCOVER.MOST_ACTIVE' | translate }} tg-discover-home-order-by(on-change="vm.orderBy(orderBy)", order-by="vm.currentOrderBy") @@ -15,6 +14,5 @@ .empty-highlighted-project( ng-if="!vm.highlighted.size" ) - svg.icon.icon-activity - use(xlink:href="#icon-activity") + tg-svg(svg-icon="icon-activity") span {{ 'DISCOVER.MOST_ACTIVE_EMPTY' | translate }} diff --git a/app/modules/discover/components/most-liked/most-liked.jade b/app/modules/discover/components/most-liked/most-liked.jade index 031f35c3..daac385b 100644 --- a/app/modules/discover/components/most-liked/most-liked.jade +++ b/app/modules/discover/components/most-liked/most-liked.jade @@ -1,10 +1,12 @@ .most-liked(ng-if="vm.highlighted.size") .header .title-wrapper - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") h1.title {{ 'DISCOVER.MOST_LIKED' | translate }} - tg-discover-home-order-by(on-change="vm.orderBy(orderBy)", order-by="vm.currentOrderBy") + tg-discover-home-order-by( + on-change="vm.orderBy(orderBy)" + order-by="vm.currentOrderBy" + ) tg-highlighted( loading="vm.loading", highlighted="vm.highlighted" @@ -14,6 +16,5 @@ .empty-highlighted-project( ng-if="!vm.highlighted.size" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{ 'DISCOVER.MOST_LIKED_EMPTY' | translate }} diff --git a/app/modules/discover/discover-search/discover-search.jade b/app/modules/discover/discover-search/discover-search.jade index 3422ad60..1290ab83 100644 --- a/app/modules/discover/discover-search/discover-search.jade +++ b/app/modules/discover/discover-search/discover-search.jade @@ -43,9 +43,11 @@ div(tg-discover-search) tg-nav="project:project=project.get('slug')" title="{{ ::project.get('name') }}" ) {{project.get('name')}} - 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') }}" + tg-svg.look-for-people( + ng-if="project.get('is_looking_for_people')" + svg-icon="icon-recruit" + svg-title="{{ ::project.get('looking_for_people_note') }}" + ) p {{ ::project.get('description') | limitTo:300 }} span(ng-if="::project.get('description').length > 300") ... .list-itemtype-project-right.project-statistics @@ -53,22 +55,19 @@ div(tg-discover-search) ng-class="{'active': project.get('is_fan')}" title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{::project.get('total_fans')}} span.statistic( ng-class="{'active': project.get('is_watcher')}" title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{::project.get('total_watchers')}} span.statistic( ng-class="{'active': project.get('i_am_member')}" title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}" ) - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span.statistics-num {{ ::project.get('members').size }} a.button-green.more-results( diff --git a/app/modules/discover/discover-search/discover-search.scss b/app/modules/discover/discover-search/discover-search.scss index b97b58e8..d5d48788 100644 --- a/app/modules/discover/discover-search/discover-search.scss +++ b/app/modules/discover/discover-search/discover-search.scss @@ -71,10 +71,6 @@ flex: 1; vertical-align: middle; } - .look-for-people { - fill: $gray-light; - margin-left: .5rem; - } .project-statistics { display: flex; flex-basis: 300px; diff --git a/app/modules/home/duties/duty.jade b/app/modules/home/duties/duty.jade index c0678e0a..fa3b5411 100644 --- a/app/modules/home/duties/duty.jade +++ b/app/modules/home/duties/duty.jade @@ -16,18 +16,21 @@ 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") + + tg-svg( + ng-if="vm.duty.get('blockedProject')", + svg-icon="icon-blocked-project", + svg-title-translate="PROJECT.BLOCKED_PROJECT.BLOCKED" + ) h2 span.ticket-id(tg-bo-ref="duty.get('ref')") - span.ticket-title + span.ticket-title span.ticket-blocked( ng-if="::vm.duty.get('is_blocked')" title="{{::vm.duty.get('blocked_note')}}" - ) {{ 'COMMON.BLOCKED' | translate }} + ) {{ 'COMMON.BLOCKED' | translate }} span {{ ::duty.get('subject') }} diff --git a/app/modules/home/projects/home-project-list.jade b/app/modules/home/projects/home-project-list.jade index 87493385..273f0009 100644 --- a/app/modules/home/projects/home-project-list.jade +++ b/app/modules/home/projects/home-project-list.jade @@ -28,10 +28,25 @@ section.home-project-list(ng-if="vm.projects.size") tg-nav="project:project=project.get('slug')" title="{{::project.get('name')}}" ) {{::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") - + + tg-svg.look-for-people( + ng-if="project.get('is_looking_for_people')" + svg-icon="icon-recruit" + svg-title="{{ ::project.get('looking_for_people_note') }}" + ) + + tg-svg.owner-badge( + ng-if="project.get('i_am_owner')" + svg-icon="icon-badge" + svg-title="COMMON.OWNER" + ) + + tg-svg( + ng-if="project.get('blocked_code')" + svg-icon="icon-blocked-project" + svg-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 @@ -39,29 +54,25 @@ section.home-project-list(ng-if="vm.projects.size") ng-class="{'active': project.get('is_fan')}" title="{{ 'PROJECT.FANS_COUNTER_TITLE'|translate:{total:project.get('total_fans')||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{::project.get('total_fans')}} span.statistic( ng-class="{'active': project.get('is_watcher')}" title="{{ 'PROJECT.WATCHERS_COUNTER_TITLE'|translate:{total:project.get('total_watchers')||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{::project.get('total_watchers')}} span.statistic( ng-class="{'active': project.get('i_am_member')}" title="{{ 'PROJECT.MEMBERS_COUNTER_TITLE'|translate:{total:project.get('members').size||0}:'messageformat' }}" ) - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span.statistics-num {{ ::project.get('members').size }} span.statistic( ng-if="::project.get('is_private')" title="{{ 'PROJECT.PRIVATE' | translate }}" ) - svg.icon.icon-lock - use(xlink:href="#icon-lock") + tg-svg(svg-icon="icon-lock") a.see-more-projects-btn.button-gray( href="#", @@ -72,8 +83,7 @@ section.home-project-list(ng-if="vm.projects.size") ) section.projects-empty(ng-if="vm.projects != undefined && vm.projects.size === 0") - svg.icon.icon-project - use(xlink:href="#icon-project") + tg-svg(svg-icon="icon-project") p(translate="HOME.EMPTY_PROJECT_LIST") a.create-project-button.button-green(href="#", ng-click="vm.newProject()", title="{{'PROJECT.NAVIGATION.TITLE_CREATE_PROJECT' | translate}}", 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 10374374..7940b928 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 @@ -1,6 +1,9 @@ -a(href="", title="Projects", tg-nav="projects") - svg.icon.icon-project - use(xlink:href="#icon-project") +a( + href="" + title="Projects" + tg-nav="projects" +) + tg-svg(svg-icon="icon-project") div.navbar-dropdown.dropdown-project-list ul @@ -11,9 +14,11 @@ div.navbar-dropdown.dropdown-project-list 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") + tg-svg( + svg-icon="icon-blocked-project" + ng-if="project.get('blocked_code')" + svg-title="PROJECT.BLOCKED_PROJECT.BLOCKED" + ) a.see-more-projects-btn.button-gray( href="#", @@ -33,6 +38,5 @@ div.navbar-dropdown.dropdown-project-list 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 + tg-svg(svg-icon="icon-upload") + input.import-file.hidden(type="file") diff --git a/app/modules/navigation-bar/navigation-bar.jade b/app/modules/navigation-bar/navigation-bar.jade index e81794cc..c8ae3501 100644 --- a/app/modules/navigation-bar/navigation-bar.jade +++ b/app/modules/navigation-bar/navigation-bar.jade @@ -30,21 +30,19 @@ nav.navbar(ng-if="vm.isEnabledHeader") ) div.nav-right(ng-if="vm.isAuthenticated") - a(tg-nav="home", - ng-class="{active: vm.active}", - title="{{'PROJECT.NAVIGATION.DASHBOARD_TITLE' | translate}}") - - svg.icon.icon-dashboard - use(xlink:href="#icon-dashboard") + a( + tg-nav="home" + ng-class="{active: vm.active}" + title="{{'PROJECT.NAVIGATION.DASHBOARD_TITLE' | translate}}" + ) + tg-svg(svg-icon="icon-dashboard") a( href="#", tg-nav="discover", title="{{'PROJECT.NAVIGATION.DISCOVER_TITLE' | translate}}", ) - svg.icon.icon-discover - use(xlink:href="#icon-discover") + tg-svg(svg-icon="icon-discover") div.topnav-dropdown-wrapper(ng-show="vm.projects.size", tg-dropdown-project-list) - //- div.topnav-dropdown-wrapper(tg-dropdown-organization-list) div.topnav-dropdown-wrapper(tg-dropdown-user) diff --git a/app/modules/profile/profile-contacts/profile-contacts.jade b/app/modules/profile/profile-contacts/profile-contacts.jade index b752325e..30306343 100644 --- a/app/modules/profile/profile-contacts/profile-contacts.jade +++ b/app/modules/profile/profile-contacts/profile-contacts.jade @@ -4,8 +4,7 @@ section.profile-contacts img(src="/#{v}/svg/spinner-circle.svg", alt="Loading...") div.empty-tab(ng-if="vm.contacts && !vm.contacts.size") - svg.icon.icon-unwatch - use(xlink:href="#icon-unwatch") + tg-svg(svg-icon="icon-unwatch") div(ng-if="!vm.isCurrentUser") p(translate="USER.PROFILE.CONTACTS_EMPTY", translate-values="{username: vm.user.get('full_name_display')}") diff --git a/app/modules/profile/profile-favs/items/project.jade b/app/modules/profile/profile-favs/items/project.jade index 7e4521be..bcc8e293 100644 --- a/app/modules/profile/profile-favs/items/project.jade +++ b/app/modules/profile/profile-favs/items/project.jade @@ -18,12 +18,18 @@ tg-nav="project:project=vm.item.get('slug')" title="{{ ::vm.item.get('name') }}" ) {{ ::vm.item.get('name') }} - svg.icon.icon-lock.private(ng-if="::vm.item.get('project_is_private')") - use(xlink:href="#icon-lock") - title {{'PROJECT.PRIVATE' | translate}}" - 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") + + tg-svg( + ng-if="::vm.item.get('is_private')" + svg-icon="icon-lock" + svg-title-translate="PROJECT.PRIVATE" + ) + + tg-svg( + ng-if="vm.item.get('blocked_code')" + svg-icon="icon-blocked-project" + svg-title-translate="PROJECT.BLOCKED_PROJECT.BLOCKED" + ) p.list-itemtype-project-description {{ ::vm.item.get('description') }} .list-itemtype-track @@ -31,14 +37,12 @@ ng-class="{'active': vm.item.get('is_fan')}" title="{{ 'PROJECT.LIKE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_fans\")||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{ ::vm.item.get('total_fans') }} span.list-itemtype-track-watchers( ng-class="{'active': vm.item.get('is_watcher')}" title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_watchers\")||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{ ::vm.item.get('total_watchers') }} diff --git a/app/modules/profile/profile-favs/items/ticket.jade b/app/modules/profile/profile-favs/items/ticket.jade index 599fd041..7f974ea4 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(ng-class="{'blocked-project': vm.item.get('project_blocked_code')}") +.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')" @@ -20,7 +20,7 @@ div.list-itemtype-ticket(ng-class="{'blocked-project': vm.item.get('project_bloc alt="{{ 'COMMON.ASSIGNED_TO.NOT_ASSIGNED'|translate }}" ) - div.list-itemtype-ticket-data + .list-itemtype-ticket-data p span.ticket-project | {{:: vm.item.get('project_name') }} @@ -36,11 +36,12 @@ div.list-itemtype-ticket(ng-class="{'blocked-project': vm.item.get('project_bloc ng-if="::vm.item.get('type') === 'issue'" translate="COMMON.ISSUE" ) - 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") + span.ticket-status(ng-style="::{'color': vm.item.get('status_color')}") {{:: vm.item.get('status') }} + tg-svg( + ng-if="vm.item.get('project_blocked_code')" + svg-icon="icon-blocked-project" + svgTitleTranslate: "PROJECT.BLOCKED_PROJECT.BLOCKED" + ) h2 span.ticket-id(tg-bo-ref="vm.item.get('ref')") a.ticket-title( @@ -67,14 +68,12 @@ div.list-itemtype-ticket(ng-class="{'blocked-project': vm.item.get('project_bloc ng-class="{'active': vm.item.get('is_voter')}", title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_voters\")||0}:'messageformat' }}" ) - svg.icon.icon-upvote - use(xlink:href="#icon-upvote") + tg-svg(svg-icon="icon-upvote") span {{ ::vm.item.get('total_voters') }} span.list-itemtype-track-watchers( ng-class="{'active': vm.item.get('is_watcher')}" title="{{ 'COMMON.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_watchers\")||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{ ::vm.item.get('total_watchers') }} diff --git a/app/modules/profile/profile-favs/profile-favs.jade b/app/modules/profile/profile-favs/profile-favs.jade index 9ec621c7..880c25e6 100644 --- a/app/modules/profile/profile-favs/profile-favs.jade +++ b/app/modules/profile/profile-favs/profile-favs.jade @@ -1,8 +1,7 @@ section.profile-favs div.profile-filter div.searchbox(ng-if="::vm.enableFilterByTextQuery") - svg.icon.icon-search - use(xlink:href="#icon-search") + tg-svg(svg-icon="icon-search") input( type="text" ng-model="vm.q" diff --git a/app/modules/profile/profile-hints/profile-hints.jade b/app/modules/profile/profile-hints/profile-hints.jade index 364a9066..b96a1748 100644 --- a/app/modules/profile/profile-hints/profile-hints.jade +++ b/app/modules/profile/profile-hints/profile-hints.jade @@ -1,6 +1,5 @@ h4 - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="HINTS.SECTION_NAME") p {{::vm.hint.title}} diff --git a/app/modules/profile/profile-projects/profile-projects.jade b/app/modules/profile/profile-projects/profile-projects.jade index 5e3ff52d..a1d361f8 100644 --- a/app/modules/profile/profile-projects/profile-projects.jade +++ b/app/modules/profile/profile-projects/profile-projects.jade @@ -4,8 +4,7 @@ section.profile-projects img(src="/#{v}/svg/spinner-circle.svg", alt="Loading...") .empty-tab(ng-if="vm.projects && !vm.projects.size") - svg.icon.icon-unwatch - use(xlink:href="#icon-unwatch") + tg-svg(svg-icon="icon-unwatch") p( translate="USER.PROFILE.PROJECTS_EMPTY" @@ -33,9 +32,12 @@ section.profile-projects tg-nav="project:project=project.get('slug')" title="{{ ::project.get('name') }}" ) {{::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") + + tg-svg( + ng-if="project.get('blocked_code')", + svg-icon="icon-blocked-project" + svg-title-translate="PROJECT.BLOCKED_PROJECT.BLOCKED" + ) p.project-description {{ ::project.get('description') | limitTo:300 }} .list-itemtype-project-right @@ -45,16 +47,14 @@ section.profile-projects ng-class="{'active': project.get('is_fan')}" title="{{ 'PROJECT.LIKE_BUTTON.COUNTER_TITLE'|translate:{total:project.get(\"total_fans\")||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{ ::project.get('total_fans') }} span.list-itemtype-track-watchers( ng-class="{'active': project.get('is_watcher')}" title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:project.get(\"total_watchers\")||0}:'messageformat' }}" ) - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{ ::project.get('total_watchers') }} .list-itemtype-project-members diff --git a/app/modules/profile/profile-tab/profile-tab.directive.coffee b/app/modules/profile/profile-tab/profile-tab.directive.coffee index 252e7282..308a97ba 100644 --- a/app/modules/profile/profile-tab/profile-tab.directive.coffee +++ b/app/modules/profile/profile-tab/profile-tab.directive.coffee @@ -28,7 +28,6 @@ ProfileTabDirective = () -> scope.tab.title = title scope.tab.icon = attrs.tabIcon - scope.tab.iconName = '#' + attrs.tabIcon scope.tab.active = !!attrs.tabActive if scope.$eval(attrs.tabDisabled) != true diff --git a/app/modules/profile/profile-tabs/profile-tabs.jade b/app/modules/profile/profile-tabs/profile-tabs.jade index c7965c2f..23e861ec 100644 --- a/app/modules/profile/profile-tabs/profile-tabs.jade +++ b/app/modules/profile/profile-tabs/profile-tabs.jade @@ -7,8 +7,7 @@ div ng-click="vm.toggleTab(tab)" ng-class="{active: tab.active}" ) - svg.icon(ng-class="::tab.icon") - use(xlink:href="{{::tab.iconName}}") + tg-svg(svg-icon="{{::tab.icon}}") span {{::tab.name}} ng-transclude diff --git a/app/modules/projects/components/like-project-button/like-project-button.jade b/app/modules/projects/components/like-project-button/like-project-button.jade index 176c25fd..de8da23f 100644 --- a/app/modules/projects/components/like-project-button/like-project-button.jade +++ b/app/modules/projects/components/like-project-button/like-project-button.jade @@ -8,8 +8,7 @@ a.track-button.like-button.like-container( ) span.track-inner span.track-icon - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span( ng-if="!vm.project.get('is_fan')" translate="PROJECT.LIKE_BUTTON.LIKE" diff --git a/app/modules/projects/components/watch-project-button/watch-project-button.jade b/app/modules/projects/components/watch-project-button/watch-project-button.jade index 1c2671a5..632fb070 100644 --- a/app/modules/projects/components/watch-project-button/watch-project-button.jade +++ b/app/modules/projects/components/watch-project-button/watch-project-button.jade @@ -6,12 +6,10 @@ a.track-button.watch-button.watch-container( ) span.track-inner span.track-icon - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span(ng-if="!vm.project.get('is_watcher')", translate="PROJECT.WATCH_BUTTON.WATCH") span(ng-if="vm.project.get('is_watcher')", translate="PROJECT.WATCH_BUTTON.WATCHING") - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") span.track-button-counter( title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.project.get(\"total_watchers\")||0}:'messageformat' }}", @@ -37,8 +35,7 @@ ul.watch-options( ) span(translate="PROJECT.WATCH_BUTTON.OPTIONS.NOTIFY_ALL") span.watch-check(ng-if="vm.project.get('is_watcher') && vm.project.get('notify_level') == 2") - svg.icon.icon-check-empty - use(xlink:href="#icon-check-empty") + tg-svg(svg-icon="icon-check-empty") li a( href="", @@ -48,8 +45,7 @@ ul.watch-options( ) span(translate="PROJECT.WATCH_BUTTON.OPTIONS.NOTIFY_INVOLVED") span.watch-check(ng-if="vm.project.get('is_watcher') && vm.project.get('notify_level') == 1") - svg.icon.icon-check-empty - use(xlink:href="#icon-check-empty") + tg-svg(svg-icon="icon-check-empty") li(ng-if="vm.project.get('is_watcher')") a( diff --git a/app/modules/projects/listing/projects-listing.jade b/app/modules/projects/listing/projects-listing.jade index be8ad939..096af8b6 100644 --- a/app/modules/projects/listing/projects-listing.jade +++ b/app/modules/projects/listing/projects-listing.jade @@ -13,8 +13,7 @@ href="" title="{{'PROJECT.NAVIGATION.TITLE_IMPORT_PROJECT' | translate}}" ) - svg.icon.icon-upload - use(xlink:href="#icon-upload") + tg-svg(svg-icon="icon-upload") input.import-file.hidden(type="file") section.project-list-section @@ -44,23 +43,26 @@ tg-nav="project:project=project.get('slug')" title="{{ ::project.get('name') }}" ) {{project.get('name')}} - svg.icon.icon-lock.private(ng-if="project.get('is_private')") - use(xlink:href="#icon-lock") - title {{'PROJECT.PRIVATE' | translate}}" - - 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") - - + tg-svg( + ng-if="project.get('is_private')", + svg-icon="icon-lock", + svg-title-translate="PROJECT.PRIVATE" + ) + tg-svg( + ng-if="project.get('i_am_owner')", + svg-icon="icon-badge", + svg-title-translate="COMMON.OWNER" + ) + tg-svg( + ng-if="project.get('blocked_code')", + svg-icon="icon-blocked-project", + svg-title-translate="PROJECT.BLOCKED_PROJECT.BLOCKED" + ) + p.project-description {{ ::project.get('description') | limitTo:300 }} span(ng-if="::project.get('description').length > 300") ... - svg.drag.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg.drag(svg-icon="icon-drag") aside.help-area p(translate="PROJECT.HELP") diff --git a/app/modules/projects/listing/styles/project-list.scss b/app/modules/projects/listing/styles/project-list.scss index d22945ad..54191dbe 100644 --- a/app/modules/projects/listing/styles/project-list.scss +++ b/app/modules/projects/listing/styles/project-list.scss @@ -87,11 +87,13 @@ } .drag { align-self: center; - fill: $gray-light; - height: 1.1rem; - margin-right: .5rem; opacity: 0; - transition: opacity .2s; - width: 1.1rem; + svg { + fill: $gray-light; + height: 1.1rem; + margin-right: .5rem; + transition: opacity .2s; + width: 1.1rem; + } } } diff --git a/app/modules/projects/project/blocked-project.jade b/app/modules/projects/project/blocked-project.jade index be6b75b8..0cf464b8 100644 --- a/app/modules/projects/project/blocked-project.jade +++ b/app/modules/projects/project/blocked-project.jade @@ -6,9 +6,10 @@ 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") + tg-svg( + svg-icon="icon-blocked-project" + svgTitleTranslate: "PROJECT.BLOCKED_PROJECT.BLOCKED" + ) span.project-title {{::vm.project.get("name")}} .blocked-project-message h1.project-block-title {{'PROJECT.BLOCKED_PROJECT.BLOCKED' | translate}} diff --git a/app/modules/projects/project/project.jade b/app/modules/projects/project/project.jade index 44c479ee..731d3d59 100644 --- a/app/modules/projects/project/project.jade +++ b/app/modules/projects/project/project.jade @@ -16,10 +16,11 @@ div.wrapper .intro-title h1 span.project-name {{::vm.project.get("name")}} - - svg.icon.icon-lock.private(ng-if="::vm.project.get('is_private')") - use(xlink:href="#icon-lock") - title {{'PROJECT.PRIVATE' | translate}}" + tg-svg( + ng-if="::vm.project.get('is_private')" + svg-icon="icon-lock" + svgTitleTranslate: "PROJECT.PRIVATE" + ) div.track-buttons-container(ng-if="vm.user") tg-like-project-button(project="vm.project") @@ -30,15 +31,13 @@ div.wrapper span.list-itemtype-track-likers( title="{{ 'PROJECT.LIKE_BUTTON.COUNTER_TITLE'|translate:{total:vm.project.get(\"total_fans\")||0}:'messageformat' }}" ) - svg.icon.icon-like - use(xlink:href="#icon-like") + tg-svg(svg-icon="icon-like") span {{ ::vm.project.get('total_fans') }} span.list-itemtype-track-watchers( title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.project.get(\"total_watchers\")||0}:'messageformat' }}" ) - svg.icon.icon-watche - use(xlink:href="#icon-watch") + tg-svg(svg-icon="icon-watch") span {{ ::vm.project.get('total_watchers') }} p.description {{vm.project.get('description')}} @@ -70,6 +69,8 @@ div.wrapper title="{{::member.get('full_name')}}" ) img(ng-src="{{::member.get('photo')}}", alt="{{::member.get('full_name')}}") - svg.icon.icon-badge(ng-if="member.get('id') == vm.project.getIn(['owner', 'id'])") - use(xlink:href="#icon-badge") - title(translate="COMMON.OWNER") + tg-svg( + ng-if="member.get('id') == vm.project.getIn(['owner', 'id'])" + svg-icon="icon-badge" + svgTitleTranslate: "COMMON.OWNER" + ) diff --git a/app/modules/projects/transfer/transfer-project.jade b/app/modules/projects/transfer/transfer-project.jade index 681aa535..1524d421 100644 --- a/app/modules/projects/transfer/transfer-project.jade +++ b/app/modules/projects/transfer/transfer-project.jade @@ -9,12 +9,10 @@ h3.transfer-project-title {{::vm.project.get("name")}} .transfer-project-statistics span.transfer-project-private(ng-if="vm.project.get('is_private')") - svg.icon.icon-lock - use(xlink:href="#icon-lock") + tg-svg(svg-icon="icon-lock") span(translate="ADMIN.PROJECT_TRANSFER.PRIVATE") span.transfer-project-members - svg.icon.icon-team - use(xlink:href="#icon-team") + tg-svg(svg-icon="icon-team") span {{::vm.project.get("total_memberships")}} p( @@ -44,8 +42,10 @@ label.transfer-project-comment-label( translate="ADMIN.PROJECT_TRANSFER.ADD_COMMENT" ) - svg.icon.icon-close(ng-click="vm.hideComment()") - use(xlink:href="#icon-close") + tg-svg( + svg-icon="icon-close" + ng-click="vm.hideComment()" + ) textarea.transfer-project-comment( name="reason" ng-model="vm.reason" @@ -66,4 +66,4 @@ translate="ADMIN.PROJECT_TRANSFER.ACCEPT" ) - div(ng-if="!vm.canBeOwnedByUser.valid", tg-cant-own-project-explanation) + tg-cant-own-project-explanation(ng-if="!vm.canBeOwnedByUser.valid") diff --git a/app/modules/user-timeline/user-timeline-attachment/user-timeline-attachment.jade b/app/modules/user-timeline/user-timeline-attachment/user-timeline-attachment.jade index 8c086e97..c93b3238 100644 --- a/app/modules/user-timeline/user-timeline-attachment/user-timeline-attachment.jade +++ b/app/modules/user-timeline/user-timeline-attachment/user-timeline-attachment.jade @@ -1,6 +1,5 @@ div.single-attachment blockquote a(ng-href="{{ attachment.get('url') }}", title="Click to download {{ attachment.get('filename') }}", target="_blank") - svg.icon.icon-attachment - use(xlink:href="#icon-attachment") + tg-svg(svg-icon="icon-attachment") span {{attachment.get('filename')}} diff --git a/app/partials/admin/admin-project-export.jade b/app/partials/admin/admin-project-export.jade index 024e49da..7ab4997f 100644 --- a/app/partials/admin/admin-project-export.jade +++ b/app/partials/admin/admin-project-export.jade @@ -26,6 +26,5 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl", p.result-message a.help-button(href="https://taiga.io/support/import-export-projects/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.HELP") diff --git a/app/partials/admin/admin-project-modules.jade b/app/partials/admin/admin-project-modules.jade index 93ae5d6b..09f80d3a 100644 --- a/app/partials/admin/admin-project-modules.jade +++ b/app/partials/admin/admin-project-modules.jade @@ -19,8 +19,7 @@ div.wrapper( form.module-container .module.module-scrum(ng-class="{true:'active', false:''}[project.is_backlog_activated]") .module-icon - svg.icon.icon-scrum - use(xlink:href="#icon-scrum") + tg-svg(svg-icon="icon-scrum") .module-name(translate="ADMIN.MODULES.BACKLOG") .module-desc p(translate="ADMIN.MODULES.BACKLOG_DESCRIPTION") @@ -47,9 +46,10 @@ div.wrapper( placeholder="{{'ADMIN.MODULES.NUMBER_US_POINTS_HELP' | translate}}" ng-model="project.total_story_points" data-type="digits" - ) - svg.icon.icon-save(ng-if="project.is_backlog_activated") - use(xlink:href="#icon-save") + ) + .options + a.save(href="", ng-if="project.is_backlog_activated") + tg-svg(svg-icon="icon-save") .module-activation.module-direct-active div.check input.activate-input( @@ -65,8 +65,7 @@ div.wrapper( .module.module-kanban(ng-class="{true:'active', false:''}[project.is_kanban_activated]") .module-icon - svg.icon.icon-kanban - use(xlink:href="#icon-kanban") + tg-svg(svg-icon="icon-kanban") .module-name(translate="ADMIN.MODULES.KANBAN") .module-desc(translate="ADMIN.MODULES.KANBAN_DESCRIPTION") .module-activation.module-direct-active @@ -84,8 +83,7 @@ div.wrapper( .module.module-issues(ng-class="{true:'active', false:''}[project.is_issues_activated]") .module-icon - svg.icon.icon-issues - use(xlink:href="#icon-issues") + tg-svg(svg-icon="icon-issues") .module-name(translate="ADMIN.MODULES.ISSUES") .module-desc(translate="ADMIN.MODULES.ISSUES_DESCRIPTION") .module-activation.module-direct-active @@ -103,8 +101,7 @@ div.wrapper( .module.module-wiki(ng-class="{true:'active', false:''}[project.is_wiki_activated]") .module-icon - svg.icon.icon-wiki - use(xlink:href="#icon-wiki") + tg-svg(svg-icon="icon-wiki") .module-name(translate="ADMIN.MODULES.WIKI") .module-desc(translate="ADMIN.MODULES.WIKI_DESCRIPTION") .module-activation.module-direct-active @@ -122,8 +119,7 @@ div.wrapper( .module.module-videoconference(ng-class="{true:'active', false:''}[isVideoconferenceActivated]") .module-icon - svg.icon.icon-bubble-empty - use(xlink:href="#icon-bubble-empty") + tg-svg(svg-icon="icon-bubble-empty") .module-name(translate="ADMIN.MODULES.MEETUP") .module-desc p(translate="ADMIN.MODULES.MEETUP_DESCRIPTION") @@ -157,8 +153,9 @@ div.wrapper( data-type="url" data-required="true" ) - svg.icon.icon-save(ng-if="project.videoconferences") - use(xlink:href="#icon-save") + fieldset.options + a.save(href="", ng-if="project.videoconferences") + tg-svg(svg-icon="icon-save") .module-activation div.check diff --git a/app/partials/admin/admin-project-profile.jade b/app/partials/admin/admin-project-profile.jade index 7cd2f329..61516d24 100644 --- a/app/partials/admin/admin-project-profile.jade +++ b/app/partials/admin/admin-project-profile.jade @@ -83,7 +83,6 @@ div.wrapper( owner="project.owner", project-id="project.id" ) - fieldset(ng-if="project.owner.id == user.id") tg-admin-project-change-owner.admin-project-profile-owner-actions( members="project.members.length" @@ -95,9 +94,10 @@ div.wrapper( fieldset.looking-for-people .looking-for-people-selector span {{ 'ADMIN.PROJECT_PROFILE.RECRUITING' | translate }} - svg.icon.icon-recruit - use(xlink:href="#icon-recruit") - title {{ 'ADMIN.PROJECT_PROFILE.RECRUITING_MESSAGE' | translate }}" + tg-svg( + svg-icon="icon-recruit", + svg-title-translate="ADMIN.PROJECT_PROFILE.RECRUITING_MESSAGE" + ) div.check input( type="checkbox", @@ -146,9 +146,10 @@ div.wrapper( href="https://taiga.io/support/whats-the-difference-between-public-and-private-projects/" target="_blank" ) - svg.icon.icon-question - use(xlink:href="#icon-question") - title {{ 'ADMIN.PROJECT_PROFILE.PRIVATE_OR_PUBLIC' | translate }} + tg-svg( + svg-icon="icon-question", + svg-title-translate="ADMIN.PROJECT_PROFILE.PRIVATE_OR_PUBLIC" + ) span {{'ADMIN.PROJECT_PROFILE.PRIVATE_OR_PUBLIC' | translate }} button.button-green.submit-button( type="submit" diff --git a/app/partials/admin/admin-project-reports.jade b/app/partials/admin/admin-project-reports.jade index bde79213..b6bf41c5 100644 --- a/app/partials/admin/admin-project-reports.jade +++ b/app/partials/admin/admin-project-reports.jade @@ -22,6 +22,5 @@ div.wrapper(ng-controller="ProjectProfileController as ctrl", div a.help-button(href="https://taiga.io/support/csv-reports/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.REPORTS.HELP") diff --git a/app/partials/admin/admin-roles.jade b/app/partials/admin/admin-roles.jade index 1afdcc9b..657849c2 100644 --- a/app/partials/admin/admin-roles.jade +++ b/app/partials/admin/admin-roles.jade @@ -22,13 +22,11 @@ div.wrapper.roles(ng-controller="RolesController as ctrl", .edit-role input(type="text", value="{{ role.name }}") a.save(href="", title="{{'COMMON.SAVE' | translate}}") - svg.icon.icon-save - use(xlink:href="#icon-save") + tg-svg(svg-icon="icon-save") p.total span.role-name(title="{{'ADMIN.ROLES.COUNT_MEMBERS' | translate}}") {{ role.name }} - a.edit-value - svg.icon.icon-edit - use(xlink:href="#icon-edit") + a.edit-value(href="") + tg-svg(svg-icon="icon-edit") div.any-computable-role(ng-hide="anyComputableRole", translate="ADMIN.ROLES.WARNING_NO_ROLE") diff --git a/app/partials/admin/admin-third-parties-bitbucket.jade b/app/partials/admin/admin-third-parties-bitbucket.jade index b56beb19..73a02bec 100644 --- a/app/partials/admin/admin-third-parties-bitbucket.jade +++ b/app/partials/admin/admin-third-parties-bitbucket.jade @@ -24,8 +24,7 @@ div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as c .field-with-option input(type="text", ng-model="bitbucket.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url") .option-wrapper.select-input-content - svg.icon.icon-clipboard - use(xlink:href="#icon-clipboard") + tg-svg(svg-icon="icon-clipboard") .help-copy(translate="COMMON.COPY_TO_CLIPBOARD") fieldset @@ -35,6 +34,5 @@ div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as c button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE") a.help-button(href="https://taiga.io/support/bitbucket-integration/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.HELP") diff --git a/app/partials/admin/admin-third-parties-github.jade b/app/partials/admin/admin-third-parties-github.jade index 3500c73a..c779633b 100644 --- a/app/partials/admin/admin-third-parties-github.jade +++ b/app/partials/admin/admin-third-parties-github.jade @@ -23,13 +23,11 @@ div.wrapper.roles(tg-github-webhooks, ng-controller="GithubController as ctrl", .field-with-option input(type="text", ng-model="github.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url") .option-wrapper.select-input-content - svg.icon.icon-clipboard - use(xlink:href="#icon-clipboard") + tg-svg(svg-icon="icon-clipboard") .help-copy(translate="COMMON.COPY_TO_CLIPBOARD") button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE") a.help-button(href="https://taiga.io/support/github-integration/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.HELP") diff --git a/app/partials/admin/admin-third-parties-gitlab.jade b/app/partials/admin/admin-third-parties-gitlab.jade index 8867eee3..6f91a62d 100644 --- a/app/partials/admin/admin-third-parties-gitlab.jade +++ b/app/partials/admin/admin-third-parties-gitlab.jade @@ -23,8 +23,7 @@ div.wrapper.roles(tg-gitlab-webhooks, ng-controller="GitlabController as ctrl", .field-with-option input(type="text", ng-model="gitlab.webhooks_url", name="payload-url", readonly="readonly", placeholder="{{'ADMIN.THIRD_PARTIES.PAYLOAD_URL' | translate}}", id="payload-url") .option-wrapper.select-input-content - svg.icon.icon-clipboard - use(xlink:href="#icon-clipboard") + tg-svg(svg-icon="icon-clipboard") .help-copy(translate="COMMON.COPY_TO_CLIPBOARD") fieldset @@ -34,6 +33,5 @@ div.wrapper.roles(tg-gitlab-webhooks, ng-controller="GitlabController as ctrl", button.button-green.submit-button(type="submit", title="{{'COMMON.SAVE' | translate}}", translate="COMMON.SAVE") a.help-button(href="https://taiga.io/support/gitlab-integration/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.HELP") diff --git a/app/partials/admin/admin-third-parties-webhooks.jade b/app/partials/admin/admin-third-parties-webhooks.jade index 0b9349e6..774a6569 100644 --- a/app/partials/admin/admin-third-parties-webhooks.jade +++ b/app/partials/admin/admin-third-parties-webhooks.jade @@ -48,12 +48,16 @@ div.wrapper.roles(ng-controller="WebhooksController as ctrl", ng-model="webhook.key" ) div.webhook-options - a.edit-existing(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}") - svg.icon.icon-save - use(xlink:href="#icon-save") - a.cancel-existing(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") + a.edit-existing( + href="" + title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}" + ) + tg-svg(svg-icon="icon-save") + a.cancel-existing( + href="" + title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}" + ) + tg-svg(svg-icon="icon-close") div.visualization-mode div.row @@ -66,14 +70,11 @@ div.wrapper.roles(ng-controller="WebhooksController as ctrl", div.webhook-options div.webhook-options-wrapper a.test-webhook(href="", title="{{'ADMIN.WEBHOOKS.TEST' | translate}}") - svg.icon.icon-check-empty - use(xlink:href="#icon-check-empty") + tg-svg(svg-icon="icon-check-empty") a.edit-webhook(href="", title="{{'ADMIN.WEBHOOKS.EDIT' | translate}}") - svg.icon.icon-edit - use(xlink:href="#icon-edit") + tg-svg(svg-icon="icon-edit") a.delete-webhook(href="", title="{{'ADMIN.WEBHOOKS.DELETE' | translate}}") - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") div.webhooks-history(ng-show="webhook.logs") div.history-single-wrapper(ng-repeat="log in webhook.logs") @@ -81,15 +82,14 @@ div.wrapper.roles(ng-controller="WebhooksController as ctrl", div span.history-response-icon(ng-class="log.validStatus ? 'history-success' : 'history-error'", title="{{log.status}}") span.history-date(ng-bind="log.prettyDate") - svg.toggle-log.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + a.toggle-log(href="") + tg-svg(svg-icon="icon-arrow-down") div.history-single-response div.history-single-request-header span(translate="ADMIN.WEBHOOKS.REQUEST") a.resend-request(href="", title="{{'ADMIN.WEBHOOKS.RESEND_REQUEST' | translate}}", data-log="{{log.id}}") - svg.icon.icon-reload - use(xlink:href="#icon-reload") + tg-svg(svg-icon="icon-reload") span(translate="ADMIN.WEBHOOKS.RESEND_REQUEST") div.history-single-request-body div.response-container @@ -117,13 +117,10 @@ div.wrapper.roles(ng-controller="WebhooksController as ctrl", input(type="text", name="key", placeholder="{{'ADMIN.WEBHOOKS.TYPE_SERVICE_SECRET' | translate}}", data-required="true", ng-model="newValue.key") div.webhook-options a.add-new(href="", title="{{'ADMIN.WEBHOOKS.SAVE' | translate}}") - svg.icon.icon-save - use(xlink:href="#icon-save") + tg-svg(svg-icon="icon-save") a.cancel-new(href="", title="{{'ADMIN.WEBHOOKS.CANCEL' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") a.help-button(href="https://taiga.io/support/webhooks/", target="_blank") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="ADMIN.HELP") diff --git a/app/partials/admin/lightbox-add-members.jade b/app/partials/admin/lightbox-add-members.jade index 5ba1f1b0..dbdc66b4 100644 --- a/app/partials/admin/lightbox-add-members.jade +++ b/app/partials/admin/lightbox-add-members.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="close" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close .add-member-wrapper h2.title(translate="LIGHTBOX.ADD_MEMBER.TITLE") form.add-member-form(ng-submit="vm.submit()") @@ -37,15 +32,13 @@ a.close( ng-click="vm.addSingleMember()" ng-if="$last && vm.canAddUsers" ) - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") a.remove-fieldset.ng-animate-disabled( href="" ng-click="vm.removeSingleMember($index)" ng-if="!$last || ($last && !vm.canAddUsers && vm.membersLimit > 1)" ) - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") tg-lightbox-add-members-warning-message(ng-if="vm.showWarningMessage", project="vm.project") diff --git a/app/partials/admin/memberships-row-avatar.jade b/app/partials/admin/memberships-row-avatar.jade index 294a0143..dd81bfd4 100644 --- a/app/partials/admin/memberships-row-avatar.jade +++ b/app/partials/admin/memberships-row-avatar.jade @@ -3,9 +3,10 @@ figure.avatar figcaption span.name <%- full_name %> <% if (isOwner) { %> - svg.icon.icon-badge - use(xlink:href="#icon-badge") - title(translate="COMMON.OWNER") + tg-svg( + svg-icon="icon-badge", + svg-title-translate="COMMON.OWNER" + ) <% } %> div span.pending <%- pending %> diff --git a/app/partials/admin/lightbox-add-members-no-more=memberships-warning-message.jade b/app/partials/admin/memberships-warning-message.jade similarity index 100% rename from app/partials/admin/lightbox-add-members-no-more=memberships-warning-message.jade rename to app/partials/admin/memberships-warning-message.jade diff --git a/app/partials/admin/project-csv.jade b/app/partials/admin/project-csv.jade index 559b1fd0..632c164c 100644 --- a/app/partials/admin/project-csv.jade +++ b/app/partials/admin/project-csv.jade @@ -10,14 +10,11 @@ section.project-csv(tg-select-input-text) input(type="text", placeholder="{{'ADMIN.CSV.URL_FIELD_PLACEHOLDER' | translate}}", readonly, ng-model="csvUrl") div.option-wrapper.select-input-content - svg.icon.icon-clipboard - use(xlink:href="#icon-clipboard") + tg-svg(svg-icon="icon-clipboard") a(href="", title="{{'ADMIN.CSV.TITLE_REGENERATE_URL' | translate}}", ng-click="ctrl.regenerateUuid()") - svg.icon.icon-add(ng-hide="csvUrl") - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add", ng-hide="csvUrl") span(ng-hide="csvUrl", translate="ADMIN.CSV.ACTION_GENERATE_URL") - svg.icon.icon-reload(ng-Show="csvUrl") - use(xlink:href="#icon-reload") + tg-svg(svg-icon="icon-reload", ng-show="csvUrl") span(ng-Show="csvUrl", translate="ADMIN.CSV.ACTION_REGENERATE") diff --git a/app/partials/backlog/backlog.jade b/app/partials/backlog/backlog.jade index 11556f1a..def38f1d 100644 --- a/app/partials/backlog/backlog.jade +++ b/app/partials/backlog/backlog.jade @@ -12,8 +12,7 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl", include ../includes/components/summary div.empty-burndown(ng-if="showGraphPlaceholder && project.i_am_admin") - svg.icon.icon-graph - use(xlink:href="#icon-graph") + tg-svg(svg-icon="icon-graph") div.empty-text p.title(translate="BACKLOG.CUSTOMIZE_GRAPH") p {{'BACKLOG.CUSTOMIZE_GRAPH_TEXT' | translate}} #[a(href="", tg-nav="project-admin-project-profile-modules:project=project.slug", title="{{'BACKLOG.CUSTOMIZE_GRAPH_TITLE' | translate}}") {{'BACKLOG.CUSTOMIZE_GRAPH_ADMIN' | translate}}] @@ -30,8 +29,7 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl", title="{{'BACKLOG.MOVE_US_TO_CURRENT_SPRINT' | translate}}" id="move-to-current-sprint" ) - svg.icon.icon-move - use(xlink:href="#icon-move") + tg-svg(svg-icon="icon-move") span.text(translate="BACKLOG.MOVE_US_TO_CURRENT_SPRINT") a.trans-button.move-to-latest-sprint.move-to-sprint( ng-if="!currentSprint" @@ -39,8 +37,7 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl", title="{{'BACKLOG.MOVE_US_TO_LATEST_SPRINT' | translate}}" id="move-to-latest-sprint" ) - svg.icon.icon-move - use(xlink:href="#icon-move") + tg-svg(svg-icon="icon-move") span.text(translate="BACKLOG.MOVE_US_TO_LATEST_SPRINT") a.trans-button( ng-if="userstories.length" diff --git a/app/partials/backlog/filter-selected.jade b/app/partials/backlog/filter-selected.jade index 860c8423..29e0a12e 100644 --- a/app/partials/backlog/filter-selected.jade +++ b/app/partials/backlog/filter-selected.jade @@ -1,7 +1,9 @@ <% _.each(filters, function(f) { %> -a.single-filter.selected(data-type!="<%- f.type %>", data-id!="<%- f.id %>") - span.name(style!="<%- f.style %>") - | <%- f.name %> - svg.icon.icon-close.remove-filter - use(xlink:href="#icon-close") +.single-filter.selected( + data-type!="<%- f.type %>" + data-id!="<%- f.id %>" +) + span.name(style!="<%- f.style %>") <%- f.name %> + a.remove-filter(href="") + tg-svg(svg-icon="icon-close") <% }) %> diff --git a/app/partials/backlog/sprint-header.jade b/app/partials/backlog/sprint-header.jade index fb24bf95..71bb3238 100644 --- a/app/partials/backlog/sprint-header.jade +++ b/app/partials/backlog/sprint-header.jade @@ -1,12 +1,18 @@ .sprint-name a.compact-sprint(href="", title="{{'BACKLOG.COMPACT_SPRINT' | translate}}") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") - a(ng-if="::isVisible", href="{{::taskboardUrl}}", title="{{'BACKLOG.GO_TO_TASKBOARD' | translate}}") + tg-svg(svg-icon="icon-arrow-right") + a( + ng-if="::isVisible" + href="{{::taskboardUrl}}" + title="{{'BACKLOG.GO_TO_TASKBOARD' | translate}}" + ) span {{::name}} - - svg.icon.icon-edit.edit-sprint(ng-if="::isEditable", href="", title="{{'BACKLOG.EDIT_SPRINT' | translate}}") - use(xlink:href="#icon-edit") + a.edit-sprint( + ng-if="::isEditable" + href="" + title="{{'BACKLOG.EDIT_SPRINT' | translate}}" + ) + tg-svg(svg-icon="icon-edit") .sprint-summary .sprint-date {{::estimatedDateRange}} diff --git a/app/partials/common/components/add-button.jade b/app/partials/common/components/add-button.jade index 22606398..043fc063 100644 --- a/app/partials/common/components/add-button.jade +++ b/app/partials/common/components/add-button.jade @@ -1,5 +1,4 @@ a.add-button( href="" ) - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") diff --git a/app/partials/common/components/assigned-to.jade b/app/partials/common/components/assigned-to.jade index 2588a8b5..7642ed6e 100644 --- a/app/partials/common/components/assigned-to.jade +++ b/app/partials/common/components/assigned-to.jade @@ -2,8 +2,7 @@ img(src!="<%- photo %>", alt!="<%- fullName %>") <% if (isIocaine) { %> .iocaine-symbol(title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}") - svg.icon.icon-iocaine - use(xlink:href="#icon-iocaine") + tg-svg(svg-icon="icon-iocaine") <% }; %> .assigned-to @@ -24,8 +23,7 @@ <%- fullName %> <% }; %> <% if (isEditable && !isUnassigned) { %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }; %> <% if (isEditable && isUnassigned) { %> @@ -39,9 +37,8 @@ <% }; %> <% if (isEditable && !isUnassigned) { %> - svg.icon.icon-close.remove-user( - href="" + tg-svg.remove-user( + svg-icon="icon-close", title="{{'COMMON.ASSIGNED_TO.DELETE_ASSIGNMENT' | translate}}" ) - use(xlink:href="#icon-close") <% } %> diff --git a/app/partials/common/components/block-button.jade b/app/partials/common/components/block-button.jade index 0a499ff2..ad993bd6 100644 --- a/app/partials/common/components/block-button.jade +++ b/app/partials/common/components/block-button.jade @@ -2,11 +2,9 @@ a.button-gray.item-block( href="" title="{{ 'COMMON.BLOCK_TITLE' | translate }}" ) - svg.icon.icon-lock - use(xlink:href="#icon-lock") + tg-svg(svg-icon="icon-lock") a.button-red.item-unblock( href="" title="{{ 'COMMON.UNBLOCK_TITLE' | translate }}" ) - svg.icon.icon-lock - use(xlink:href="#icon-unlock") + tg-svg(svg-icon="icon-unlock") diff --git a/app/partials/common/components/delete-button.jade b/app/partials/common/components/delete-button.jade index 3f1d987c..18d13663 100644 --- a/app/partials/common/components/delete-button.jade +++ b/app/partials/common/components/delete-button.jade @@ -2,5 +2,4 @@ a.button-red.button-delete( href="" title="{{ 'COMMON.DELETE' | translate }}" ) - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") diff --git a/app/partials/common/components/editable-description.jade b/app/partials/common/components/editable-description.jade index 348ef613..f5b9f095 100644 --- a/app/partials/common/components/editable-description.jade +++ b/app/partials/common/components/editable-description.jade @@ -2,12 +2,14 @@ include wysiwyg.jade .view-description section.us-content.wysiwyg(tg-bind-html="item.description_html || noDescriptionMsg") - svg.icon.icon-edit.edit - use(xlink:href="#icon-edit") + tg-svg.edit(svg-icon="icon-edit") .edit-description textarea(ng-attr-placeholder="{{'COMMON.DESCRIPTION.EMPTY' | translate}}", ng-model="item.description", tg-markitup="tg-markitup") +wysihelp - span.save-container - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") + div.save-container + span.save + tg-svg( + svg-icon="icon-save", + svg-title-translate="COMMON.SAVE" + ) diff --git a/app/partials/common/components/editable-subject.jade b/app/partials/common/components/editable-subject.jade index e4cc7bb2..0a294cba 100644 --- a/app/partials/common/components/editable-subject.jade +++ b/app/partials/common/components/editable-subject.jade @@ -1,9 +1,14 @@ .view-subject | {{ item.subject }} - svg.edit.icon.icon-edit(href="" title="{{'COMMON.EDIT' | translate}}") - use(xlink:href="#icon-edit") + tg-svg.edit( + svg-icon="icon-edit", + title="{{'COMMON.EDIT' | translate}}" + ) .edit-subject input(type="text", ng-model="item.subject", data-required="true", data-maxlength="500", ng-model-options="{ debounce: 200 }") span.save-container - svg.save.icon.icon-save(href="", title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") + a.save(href="") + tg-svg( + svg-icon="icon-save" + svg-title-translate="COMMON.SAVE" + ) diff --git a/app/partials/common/components/watchers.jade b/app/partials/common/components/watchers.jade index fb5d9771..7959982f 100644 --- a/app/partials/common/components/watchers.jade +++ b/app/partials/common/components/watchers.jade @@ -10,11 +10,11 @@ span <%- watcher.full_name_display %> <% if(isEditable){ %> - svg.icon.icon-trash.js-delete-watcher.delete-watcher( + tg-svg.js-delete-watcher.delete-watcher( + svg-icon="icon-trash", + svg-title-translate="COMMON.WATCHERS.DELETE", data-watcher-id!="<%- watcher.id %>" - title="{{'COMMON.WATCHERS.DELETE' | translate}}" ) - use(xlink:href="#icon-trash") <% }; %> <% } %> <% }); %> diff --git a/app/partials/common/components/wysiwyg.jade b/app/partials/common/components/wysiwyg.jade index 4c10f363..237dbfa9 100644 --- a/app/partials/common/components/wysiwyg.jade +++ b/app/partials/common/components/wysiwyg.jade @@ -2,6 +2,5 @@ mixin wysihelp div.wysiwyg-help span.drag-drop-help Attach files by dragging & dropping on the textarea above. a.help-markdown(href="https://taiga.io/support/taiga-markdown-syntax/", target="_blank", title="{{'COMMON.WYSIWYG.MARKDOWN_HELP' | translate}}") - svg.icon.icon-question - use(xlink:href="#icon-question") + tg-svg(svg-icon="icon-question") span(translate="COMMON.WYSIWYG.MARKDOWN_HELP") diff --git a/app/partials/common/estimation/us-estimation-points-per-role.jade b/app/partials/common/estimation/us-estimation-points-per-role.jade index 298960c0..e7a2fbb0 100644 --- a/app/partials/common/estimation/us-estimation-points-per-role.jade +++ b/app/partials/common/estimation/us-estimation-points-per-role.jade @@ -1,11 +1,10 @@ ul.points-per-role <% _.each(roles, function(role) { %> li.ticket-role-points.total(class!="<% if(editable){ %>clickable<% } %>", data-role-id!="<%- role.id %>", title!="<%- role.name %>") - span.points + span.points <%- role.points %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") - span.role + tg-svg(svg-icon="icon-arrow-down") + span.role <%- role.name %> <% }); %> li.ticket-role-points.total diff --git a/app/partials/common/estimation/us-estimation-total.jade b/app/partials/common/estimation/us-estimation-total.jade index 013bd495..e2bb0388 100644 --- a/app/partials/common/estimation/us-estimation-total.jade +++ b/app/partials/common/estimation/us-estimation-total.jade @@ -1,6 +1,8 @@ a.us-points(href="", title!="<%= title %>", class!="<% if (!editable) { %>not-clickable<% } %>") span.points-value <%= text %> <% if (editable) { %> - svg.icon.icon-arrow-down(tg-check-permission="modify_us") - use(xlink:href="#icon-arrow-down") + tg-svg( + svg-icon="icon-arrow-down", + tg-check-permission="modify_us" + ) <% } %> diff --git a/app/partials/common/history/history-activity.jade b/app/partials/common/history/history-activity.jade index 7a7ce6ff..3b58f956 100644 --- a/app/partials/common/history/history-activity.jade +++ b/app/partials/common/history/history-activity.jade @@ -15,14 +15,16 @@ span(translate="COMMENTS.DELETED_INFO", translate-values!="{ user: '<%- deleteCommentUser %>', date: '<%- deleteCommentDate %>'}") <% } %> - .comment.wysiwyg(ng-non-bindable) - | <%= comment %> + .comment.wysiwyg + div(ng-non-bindable) + | <%= comment %> <% if (!deleteCommentDate && mode !== "activity" && canDeleteComment) { %> - svg.icon.icon-trash.comment-delete( + a.comment-delete( + href="", + title!="<%- deleteCommentActionTitle %>", data-activity-id!="<%- activityId %>" - title!="<%- deleteCommentActionTitle %>" ) - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") <% } %> <% } %> @@ -31,8 +33,7 @@ <% if (mode != "activity") { %> a.changes-title(href="", title="{{'ACTIVITY.SHOW_ACTIVITY' | translate}}") span <%- changesText %> - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") <% } %> <% _.each(changes, function(change) { %> | <%= change %> diff --git a/app/partials/common/history/history-base.jade b/app/partials/common/history/history-base.jade index bd5949e7..b085dd69 100644 --- a/app/partials/common/history/history-base.jade +++ b/app/partials/common/history/history-base.jade @@ -4,22 +4,22 @@ section.history <% if (commentsVisible || historyVisible) { %> ul.history-tabs <% if (commentsVisible) { %> - li( - class="active" - data-section-class="history-comments" - ) - a(href="") - svg.icon.icon-writer - use(xlink:href="#icon-writer") + li + a( + href="", + class="active", + data-section-class="history-comments" + ) + tg-svg(svg-icon="icon-writer") span.tab-title(translate="COMMENTS.TITLE") <% } %> <% if (historyVisible) { %> - li( - data-section-class="history-activity" - ) - a(href="") - svg.icon.icon-timeline - use(xlink:href="#icon-timeline") + li + a( + href="", + data-section-class="history-activity" + ) + tg-svg(svg-icon="icon-timeline") span.tab-title(translate="ACTIVITY.TITLE") <% } %> <% } %> diff --git a/app/partials/common/history/history-deleted-comment.jade b/app/partials/common/history/history-deleted-comment.jade index 51510e55..73a2f2e2 100644 --- a/app/partials/common/history/history-deleted-comment.jade +++ b/app/partials/common/history/history-deleted-comment.jade @@ -13,7 +13,6 @@ data-activity-id!="<%- activityId %>" title="{{ 'COMMENTS.RESTORE' | translate }}" ) - svg.icon.icon-reload - use(xlink:href="#icon-reload") + tg-svg(svg-icon="icon-reload") span(translate="COMMENTS.RESTORE") <% } %> diff --git a/app/partials/common/lightbox-feedback.jade b/app/partials/common/lightbox-feedback.jade index f46019c6..afb63f3f 100644 --- a/app/partials/common/lightbox-feedback.jade +++ b/app/partials/common/lightbox-feedback.jade @@ -1,5 +1,4 @@ -svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="LIGHTBOX.FEEDBACK.TITLE") fieldset diff --git a/app/partials/common/lightbox/lightbox-assigned-to-users.jade b/app/partials/common/lightbox/lightbox-assigned-to-users.jade index 78916665..d25096e0 100644 --- a/app/partials/common/lightbox/lightbox-assigned-to-users.jade +++ b/app/partials/common/lightbox/lightbox-assigned-to-users.jade @@ -7,15 +7,14 @@ ) img(src!="<%- selected.photo %>") a.user-list-name( - href="" + href="" title!="<%- selected.full_name_display %>" ) | <%-selected.full_name_display %> - svg.icon.icon-close.remove-assigned-to( - href="" - title="{{'COMMON.ASSIGNED_TO.REMOVE_ASSIGNED' | translate}}" + tg-svg.remove-assigned-to( + svg-icon="icon-close", + svg-title-translate="COMMON.ASSIGNED_TO.REMOVE_ASSIGNED" ) - use(xlink:href="#icon-close") <% } %> <% _.each(users, function(user) { %> diff --git a/app/partials/common/lightbox/lightbox-assigned-to.jade b/app/partials/common/lightbox/lightbox-assigned-to.jade index d97ab443..2f5c598e 100644 --- a/app/partials/common/lightbox/lightbox-assigned-to.jade +++ b/app/partials/common/lightbox/lightbox-assigned-to.jade @@ -1,5 +1,4 @@ -svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close div.form h2.title(translate="LIGHTBOX.ASSIGNED_TO.SELECT") diff --git a/app/partials/common/lightbox/lightbox-attachment-preview.jade b/app/partials/common/lightbox/lightbox-attachment-preview.jade index bf401bbf..84223a72 100644 --- a/app/partials/common/lightbox/lightbox-attachment-preview.jade +++ b/app/partials/common/lightbox/lightbox-attachment-preview.jade @@ -1,6 +1,5 @@ .attachment-preview - svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") + tg-lightbox-close a(href="{{::file.get('url')}}", title="{{::file.get('description')}}", target="_blank", download="{{::file.get('name')}}") img(src="{{::file.get('url')}}") diff --git a/app/partials/common/lightbox/lightbox-block.jade b/app/partials/common/lightbox/lightbox-block.jade index d7bd60da..27d53701 100644 --- a/app/partials/common/lightbox/lightbox-block.jade +++ b/app/partials/common/lightbox/lightbox-block.jade @@ -1,5 +1,5 @@ -svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close + div.form h2.title fieldset diff --git a/app/partials/common/lightbox/lightbox-change-owner.jade b/app/partials/common/lightbox/lightbox-change-owner.jade index 8fe0a128..a1264699 100644 --- a/app/partials/common/lightbox/lightbox-change-owner.jade +++ b/app/partials/common/lightbox/lightbox-change-owner.jade @@ -1,5 +1,4 @@ -svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close .form h2.title(translate="LIGHTBOX.CHANGE_OWNER.TITLE") @@ -53,12 +52,12 @@ svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") ) fieldset(ng-if="vm.commentOpen") - svg.icon.icon-close( - ng-click="vm.commentOpen = false" + tg-svg( + svg-icon="icon-close", + ng-click="vm.commentOpen = false", href="", title="{{'COMMON.CLOSE' | translate}}" ) - use(xlink:href="#icon-close") label(translate="LIGHTBOX.CHANGE_OWNER.ADD_COMMENT") textarea(ng-model="vm.comment") diff --git a/app/partials/common/lightbox/lightbox-import-error.jade b/app/partials/common/lightbox/lightbox-import-error.jade index 36273ea6..8f4e35c9 100644 --- a/app/partials/common/lightbox/lightbox-import-error.jade +++ b/app/partials/common/lightbox/lightbox-import-error.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close .content(ng-switch="key") .private-space(ng-switch-when="private-space") diff --git a/app/partials/common/lightbox/lightbox-leave-project-warning.jade b/app/partials/common/lightbox/lightbox-leave-project-warning.jade index 51fd7caa..9f6f4627 100644 --- a/app/partials/common/lightbox/lightbox-leave-project-warning.jade +++ b/app/partials/common/lightbox/lightbox-leave-project-warning.jade @@ -1,9 +1,7 @@ -a.close(href="", title="{{'COMMON.CLOSE' | translate}}") - svg.icon.icon-close(title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close + div.content - svg.icon.icon-exclamation - use(xlink:href="#icon-exclamation") + tg-svg(svg-icon="icon-exclamation") h2.title {{'LIGHTBOX.LEAVE_PROJECT_WARNING.TITLE' | translate}} diff --git a/app/partials/common/lightbox/lightbox-request-ownership.jade b/app/partials/common/lightbox/lightbox-request-ownership.jade index 54247951..1183a5d2 100644 --- a/app/partials/common/lightbox/lightbox-request-ownership.jade +++ b/app/partials/common/lightbox/lightbox-request-ownership.jade @@ -1,6 +1,4 @@ -a.close(href="", title="{{'COMMON.CLOSE' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close .content h2.title(translate="ADMIN.PROJECT_PROFILE.REQUEST_OWNERSHIP_CONFIRMATION_TITLE") diff --git a/app/partials/common/lightbox/lightbox-users.jade b/app/partials/common/lightbox/lightbox-users.jade index d6693258..e9556128 100644 --- a/app/partials/common/lightbox/lightbox-users.jade +++ b/app/partials/common/lightbox/lightbox-users.jade @@ -1,5 +1,5 @@ -svg.close.icon.icon-close(href="", title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close + div.form h2.title(translate="COMMON.WATCHERS.ADD") fieldset diff --git a/app/partials/common/tag/lb-tag-line-tags.jade b/app/partials/common/tag/lb-tag-line-tags.jade index 7f95583e..cfe107d7 100644 --- a/app/partials/common/tag/lb-tag-line-tags.jade +++ b/app/partials/common/tag/lb-tag-line-tags.jade @@ -1,6 +1,6 @@ <% _.each(tags, function(tag) { %> span(class="tag", style!="<%- tag.style %>") span.tag-name <%- tag.name %> - svg.icon.icon-close.remove-tag(title="{{ 'COMMON.TAGS.DELETE' | translate }}") - use(xlink:href="#icon-close") + a.remove-tag(href="", title="{{'COMMON.TAGS.DELETE' | translate}}") + tg-svg(svg-icon="icon-close") <% }); %> diff --git a/app/partials/common/tag/lb-tag-line.jade b/app/partials/common/tag/lb-tag-line.jade index 5fe8414b..7723823e 100644 --- a/app/partials/common/tag/lb-tag-line.jade +++ b/app/partials/common/tag/lb-tag-line.jade @@ -4,5 +4,4 @@ input.tag-input( placeholder="{{'COMMON.TAGS.PLACEHOLDER' | translate}}" ) span.save.hidden(title="{{'COMMON.SAVE' | translate}}") - svg.icon.icon-save - use(xlink:href="#icon-save") + tg-svg(svg-icon="icon-save") diff --git a/app/partials/common/tag/tag-line.jade b/app/partials/common/tag/tag-line.jade index 2d205441..336b3731 100644 --- a/app/partials/common/tag/tag-line.jade +++ b/app/partials/common/tag/tag-line.jade @@ -1,11 +1,9 @@ .tags-container a(href="#", class="add-tag hidden", title="{{'COMMON.TAGS.ADD' | translate}}") - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") span.add-tag-text(translate="COMMON.TAGS.ADD") span.add-tag-input input(type="text", placeholder="{{'COMMON.TAGS.PLACEHOLDER' | translate}}", class="tag-input hidden") span.save.hidden(title="{{'COMMON.SAVE' | translate}}") - svg.icon.icon-save - use(xlink:href="#icon-save") + tg-svg(svg-icon="icon-save") \ No newline at end of file diff --git a/app/partials/common/tag/tags-line-tags.jade b/app/partials/common/tag/tags-line-tags.jade index 9ea57c69..90b934e4 100644 --- a/app/partials/common/tag/tags-line-tags.jade +++ b/app/partials/common/tag/tags-line-tags.jade @@ -2,7 +2,7 @@ span(class="tag", style!="border-left: 5px solid <%- tag.color %>;") span.tag-name <%- tag.name %> <% if (isEditable) { %> - svg.icon.icon-close.remove-tag(title="{{ 'COMMON.TAGS.DELETE' | translate }}") - use(xlink:href="#icon-close") + a.remove-tag(href="", title="{{'COMMON.TAGS.DELETE' | translate}}") + tg-svg(svg-icon="icon-close") <% } %> <% }); %> diff --git a/app/partials/common/wysiwyg/wysiwyg-markitup-preview.jade b/app/partials/common/wysiwyg/wysiwyg-markitup-preview.jade index 791c2d2b..8555db5d 100644 --- a/app/partials/common/wysiwyg/wysiwyg-markitup-preview.jade +++ b/app/partials/common/wysiwyg/wysiwyg-markitup-preview.jade @@ -1,6 +1,8 @@ .preview .actions - svg.edit.icon.icon-edit(title="{{'COMMON.WYSIWYG.EDIT_BUTTON' | translate}}") - use(xlink:href="#icon-edit") + tg-svg.edit( + svg-icon="icon-edit", + svg-title-translate="COMMON.WYSIWYG.EDIT_BUTTON" + ) .content.wysiwyg | <%= data %> diff --git a/app/partials/custom-attributes/custom-attribute-value-edit.jade b/app/partials/custom-attributes/custom-attribute-value-edit.jade index a62c4f53..a716304a 100644 --- a/app/partials/custom-attributes/custom-attribute-value-edit.jade +++ b/app/partials/custom-attributes/custom-attribute-value-edit.jade @@ -22,5 +22,5 @@ form.custom-field-single.editable <% } %> div.custom-field-options - svg.icon.icon-save.js-save-description(title="{{'COMMON.CUSTOM_ATTRIBUTES.SAVE' | translate}}") - use(xlink:href="#icon-save") + a.js-save-description(href="", title="{{'COMMON.CUSTOM_ATTRIBUTES.SAVE' | translate}}") + tg-svg(svg-icon="icon-save") diff --git a/app/partials/custom-attributes/custom-attribute-value.jade b/app/partials/custom-attributes/custom-attribute-value.jade index 51e7bfeb..0350a24d 100644 --- a/app/partials/custom-attributes/custom-attribute-value.jade +++ b/app/partials/custom-attributes/custom-attribute-value.jade @@ -18,6 +18,6 @@ <% if (isEditable) { %> .custom-field-options - svg.icon.icon-edit.js-edit-description(title="{{'COMMON.CUSTOM_ATTRIBUTES.EDIT' | translate}}") - use(xlink:href="#icon-edit") + a.js-edit-description(href="", title="{{'COMMON.CUSTOM_ATTRIBUTES.EDIT' | translate}}") + tg-svg(svg-icon="icon-edit") <% } %> diff --git a/app/partials/custom-attributes/custom-attributes-values.jade b/app/partials/custom-attributes/custom-attributes-values.jade index 09d7ecf9..e2dbdcd3 100644 --- a/app/partials/custom-attributes/custom-attributes-values.jade +++ b/app/partials/custom-attributes/custom-attributes-values.jade @@ -2,7 +2,7 @@ section.duty-custom-fields(ng-show="ctrl.customAttributes.length") div.custom-fields-header span(translate="COMMON.CUSTOM_ATTRIBUTES.CUSTOM_FIELDS") // Remove .open class on click on this button in both .icon and .custom-fields-body to close - svg.icon.icon-arrow-down(class!="<% if (!collapsed) { %>open<% } %>") - use(xlink:href="#icon-arrow-down") + a.collapse(href="", class!="<% if (!collapsed) { %>open<% } %>") + tg-svg(svg-icon="icon-arrow-down") div.custom-fields-body(class!="<% if (!collapsed) { %>open<% } %>") div(ng-repeat="att in ctrl.customAttributes", tg-custom-attribute-value="ctrl.getAttributeValue(att)", required-edition-perm!="<%- requiredEditionPerm %>") diff --git a/app/partials/includes/components/addnewtask.jade b/app/partials/includes/components/addnewtask.jade index 6de3e427..03ce69e4 100644 --- a/app/partials/includes/components/addnewtask.jade +++ b/app/partials/includes/components/addnewtask.jade @@ -1,14 +1,13 @@ -svg.icon.icon-add( - tg-check-permission="add_task" - href="" - title="{{'TASKBOARD.TITLE_ACTION_ADD' | translate}}" - ng-click="ctrl.addNewTask('standard', us)" +tg-svg.add-action( + tg-check-permission="add_task", + title="{{'TASKBOARD.TITLE_ACTION_ADD' | translate}}", + ng-click="ctrl.addNewTask('standard', us)", + svg-icon="icon-add" ) - use(xlink:href="#icon-add") -svg.icon.icon-bulk( - tg-check-permission="add_task" - href="" - title="{{'TASKBOARD.TITLE_ACTION_ADD_BULK' | translate}}" - ng-click="ctrl.addNewTask('bulk', us)" + +tg-svg.bulk-action( + title="{{'TASKBOARD.TITLE_ACTION_ADD_BULK' | translate}}", + ng-click="ctrl.addNewTask('bulk', us)", + tg-check-permission="add_task", + svg-icon="icon-bulk" ) - use(xlink:href="#icon-bulk") diff --git a/app/partials/includes/components/addnewus.jade b/app/partials/includes/components/addnewus.jade index 27a9d870..80ba3a1f 100644 --- a/app/partials/includes/components/addnewus.jade +++ b/app/partials/includes/components/addnewus.jade @@ -6,5 +6,4 @@ div.new-us a.button-bulk(href="", title="{{'US.ADD_BULK' | translate}}", ng-click="ctrl.addNewUs('bulk')", tg-check-permission="add_us") - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg(svg-icon="icon-bulk") diff --git a/app/partials/includes/components/backlog-row.jade b/app/partials/includes/components/backlog-row.jade index e564a31b..554e617a 100644 --- a/app/partials/includes/components/backlog-row.jade +++ b/app/partials/includes/components/backlog-row.jade @@ -13,8 +13,7 @@ div.row.us-item-row( ng-class="{'inactive': !us.total_voters, 'is-voted': us.is_voter}" title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:us.total_voters||0}:'messageformat' }}" ) - svg.icon.icon-upvote - use(xlink:href="#icon-upvote") + tg-svg(svg-icon="icon-upvote") span {{ ::us.total_voters }} div.user-stories div.tags-block(tg-colorize-tags="us.tags", tg-colorize-tags-type="backlog") @@ -34,27 +33,26 @@ div.row.us-item-row( ng-click="ctrl.editUserStory(us.project, us.ref, $event)" title="{{'COMMON.EDIT' | translate}}" ) - svg.icon.icon-edit - use(xlink:href="#icon-edit") - + tg-svg(svg-icon="icon-edit") + a.icon-delete( href="" tg-check-permission="delete_us" ng-click="ctrl.deleteUserStory(us)" title="{{'COMMON.DELETE' | translate}}" ) - svg.icon.icon-trash - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") div.status(tg-us-status="us" on-update="ctrl.updateUserStoryStatus()") a.us-status(href="", title="{{'BACKLOG.STATUS_NAME' | translate}}") span.us-status-bind - svg.icon.icon-arrow-down(tg-check-permission="modify_us") - use(xlink:href="#icon-arrow-down") + tg-svg( + tg-check-permission="modify_us", + svg-icon="icon-arrow-down" + ) div.points(tg-backlog-us-points="us") a.us-points(href="", title="{{'COMMON.FIELDS.POINTS' | translate}}") a(tg-check-permission="modify_us", href="", title="{{'COMMON.DRAG' | translate}}") - svg.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg(svg-icon="icon-drag") diff --git a/app/partials/includes/components/notification-message.jade b/app/partials/includes/components/notification-message.jade index aae6172b..8a1a1467 100644 --- a/app/partials/includes/components/notification-message.jade +++ b/app/partials/includes/components/notification-message.jade @@ -15,18 +15,16 @@ div.notification-message.notification-message-success p div.notification-message.notification-message-error - svg.icon.icon-error - use(xlink:href="#icon-error") + tg-svg(svg-icon="icon-error") div.text - h4.warning - p - svg.icon.icon-close(href="", title="{{'NOTIFICATION.CLOSE' | translate}}") - use(xlink:href="#icon-close") + h4.warning(translate="NOTIFICATION.WARNING") + p(translate="NOTIFICATION.WARNING_TEXT") + a.close(href="", title="{{'NOTIFICATION.CLOSE' | translate}}") + tg-svg(svg-icon="icon-close") div.notification-light.notification-message-light-error div.text h4.warning p a.close(href="", title="{{'NOTIFICATION.CLOSE' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") diff --git a/app/partials/includes/components/sprint-summary.jade b/app/partials/includes/components/sprint-summary.jade index 87244b25..364a336a 100644 --- a/app/partials/includes/components/sprint-summary.jade +++ b/app/partials/includes/components/sprint-summary.jade @@ -13,8 +13,7 @@ div.summary.large-summary span.description(translate="BACKLOG.SPRINT_SUMMARY.COMPLETED_POINTS") div.summary-stats - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg(svg-icon="icon-bulk") span.number(ng-bind="stats.openTasks|default:'--'") span.description(translate="BACKLOG.SPRINT_SUMMARY.OPEN_TASKS") div.summary-stats @@ -22,11 +21,9 @@ div.summary.large-summary span.description(translate="BACKLOG.SPRINT_SUMMARY.CLOSED_TASKS") div.summary-stats(title="{{'COMMON.IOCAINE_TEXT' | translate}}") - svg.icon.icon-iocaine - use(xlink:href="#icon-iocaine") + tg-svg(svg-icon="icon-iocaine") span.number(ng-bind="stats.iocaine_doses|default:'--'") span.description(translate="BACKLOG.SPRINT_SUMMARY.IOCAINE_DOSES") - + div.stats.toggle-analytics-visibility(title="{{'BACKLOG.SPRINT_SUMMARY.SHOW_STATISTICS_TITLE' | translate}}") - svg.icon.icon-graph - use(xlink:href="#icon-graph") + tg-svg(svg-icon="icon-graph") diff --git a/app/partials/includes/components/summary.jade b/app/partials/includes/components/summary.jade index 282f43e5..6bff489d 100644 --- a/app/partials/includes/components/summary.jade +++ b/app/partials/includes/components/summary.jade @@ -22,5 +22,4 @@ div.summary title="{{'BACKLOG.SPRINT_SUMMARY.TOGGLE_BAKLOG_GRAPH' | translate}}", ng-if="!showGraphPlaceholder" ) - svg.icon.icon-graph - use(xlink:href="#icon-graph") + tg-svg(svg-icon="icon-graph") diff --git a/app/partials/includes/components/taskboard-task.jade b/app/partials/includes/components/taskboard-task.jade index 4716a763..07808869 100644 --- a/app/partials/includes/components/taskboard-task.jade +++ b/app/partials/includes/components/taskboard-task.jade @@ -1,18 +1,18 @@ div.taskboard-tagline(tg-colorize-tags="task.tags", tg-colorize-tags-type="taskboard") div.taskboard-task-inner - div.taskboard-user-avatar(tg-taskboard-user-avatar, users="usersById", task="task", project="project", ng-class="{iocaine: task.is_iocaine}") - svg.icon.icon-iocaine( + div.taskboard-user-avatar(tg-taskboard-user-avatar, users="usersById", task="task", project="project") + tg-svg.iocaine( ng-if="task.is_iocaine" - title="{{'COMMON.IOCAINE_TEXT' | translate}}" + svg-icon="icon-iocaine", + svg-title="{{'COMMON.IOCAINE_TEXT' | translate}}" ) - use(xlink:href="#icon-iocaine") p.taskboard-text a.task-assigned(href="", title="{{'TASKBOARD.TITLE_ACTION_ASSIGN' | translate}}") span.task-num(tg-bo-ref="task.ref") a.task-name(href="", title="#{{ ::task.ref }} {{ ::task.subject }}", ng-bind="task.subject", tg-nav="project-tasks-detail:project=project.slug,ref=task.ref") - svg.icon.icon-edit( + tg-svg.edit-task( tg-check-permission="modify_task" - title="{{'TASKBOARD.TITLE_ACTION_EDIT' | translate}}" + svg-icon="icon-edit", + svg-title-translate="TASKBOARD.TITLE_ACTION_EDIT" ) - use(xlink:href="#icon-edit") diff --git a/app/partials/includes/modules/admin/admin-custom-attributes.jade b/app/partials/includes/modules/admin/admin-custom-attributes.jade index 073dcbe5..ddbb11b0 100644 --- a/app/partials/includes/modules/admin/admin-custom-attributes.jade +++ b/app/partials/includes/modules/admin/admin-custom-attributes.jade @@ -1,51 +1,60 @@ section.custom-fields-table.basic-table - div.project-values-title + .project-values-title h2 {{ customFieldSectionTitle | translate }} a.button.button-gray.show-add-new.js-add-custom-field-button( href="" title="{{ customFieldButtonTitle | translate }}" + translate="ADMIN.CUSTOM_ATTRIBUTES.ADD" ) - span(translate="ADMIN.CUSTOM_ATTRIBUTES.ADD") - div.table-header - div.row - div.custom-name - span(translate="COMMON.FIELDS.NAME") - div.custom-description - span(translate="COMMON.FIELDS.DESCRIPTION") - div.custom-field-type - span(translate="COMMON.FIELDS.TYPE") - div.custom-options + .table-header + .row + .custom-name(translate="COMMON.FIELDS.NAME") + .custom-description(translate="COMMON.FIELDS.DESCRIPTION") + .custom-field-type(translate="COMMON.FIELDS.TYPE") + .custom-options - div.table-body - div.js-sortable - div(ng-repeat="attr in customAttributes track by attr.id", tg-bind-scope) + .table-body + .js-sortable + div( + ng-repeat="attr in customAttributes track by attr.id" + tg-bind-scope + ) form.js-form(tg-bind-scope) div.row.single-custom-field.js-view-custom-field - svg.icon.icon-drag - use(xlink:href="#icon-drag") - div.custom-name - span {{ attr.name }} - div.custom-description - span {{ attr.description }} + tg-svg(svg-icon="icon-drag") + div.custom-name {{ attr.name }} + div.custom-description {{ attr.description }} div.custom-field-type(ng-switch on="attr.type") - //- See TYPE_CHOICES in app/coffee/modules/admin/project-values.coffee - span(ng-switch-default, translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_TEXT") - span(ng-switch-when="multiline", translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI") - span(ng-switch-when="date", translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_DATE") - span(ng-switch-when="url", translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_URL") - div.custom-options - div.custom-options-wrapper - svg.js-edit-custom-field-button.icon.icon-edit( - href="" + span( + ng-switch-default + translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_TEXT" + ) + span( + ng-switch-when="multiline" + translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_MULTI" + ) + span( + ng-switch-when="date" + translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_DATE" + ) + span( + ng-switch-when="url" + translate="ADMIN.CUSTOM_FIELDS.FIELD_TYPE_URL" + ) + .custom-options + .custom-options-wrapper + a.js-edit-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.EDIT' | translate}}" ) - use(xlink:href="#icon-edit") - svg.js-delete-custom-field-button.icon.icon-trash( - href="" + tg-svg(svg-icon="icon-edit") + + a.js-delete-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.DELETE' | translate}}" ) - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") div.row.single-custom-field.js-edit-custom-field.hidden fieldset.custom-name @@ -71,16 +80,17 @@ section.custom-fields-table.basic-table ) fieldset.custom-options div.custom-options-wrapper - svg.js-update-custom-field-button.icon.icon-save( - href="" + a.js-update-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.ACTION_UPDATE' | translate}}" ) - use(xlink:href="#icon-save") - svg.js-cancel-edit-custom-field-button.icon.icon-close( - href="" + tg-svg(svg-icon="icon-save") + + a.js-cancel-edit-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.ACTION_CANCEL_EDITION' | translate}}" ) - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") form.row.single-custom-field.js-new-custom-field.hidden fieldset.custom-name @@ -108,13 +118,14 @@ section.custom-fields-table.basic-table fieldset.custom-options div.custom-options-wrapper - svg.js-create-custom-field-button.icon.icon-save( - href="" + a.js-create-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.SAVE_TITLE' | translate}}" ) - use(xlink:href="#icon-save") - svg.js-cancel-new-custom-field-button.icon.icon-trash( - href="" + tg-svg(svg-icon="icon-save") + + a.js-cancel-new-custom-field-button( + href="", title="{{'ADMIN.CUSTOM_ATTRIBUTES.CANCEL_TITLE' | translate}}" ) - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-close") diff --git a/app/partials/includes/modules/admin/project-points.jade b/app/partials/includes/modules/admin/project-points.jade index 6189a3d7..efb88ca4 100644 --- a/app/partials/includes/modules/admin/project-points.jade +++ b/app/partials/includes/modules/admin/project-points.jade @@ -18,8 +18,7 @@ section.project-values-table div(ng-repeat="value in values track by value.id", tg-bind-scope) form(tg-bind-scope) div.project-values-row.row.table-main.visualization - svg.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg(svg-icon="icon-drag") div.project-values-name span {{ value.name }} @@ -28,10 +27,16 @@ section.project-values-table span {{ value.value }} div.project-values-settings - svg.edit-value.icon.icon-edit(title="{{'ADMIN.POINTS.TITLE_ACTION_EDIT_VALUE' | translate}}") - use(xlink:href="#icon-edit") - svg.delete-value.icon.icon-trash(title="{{'ADMIN.POINTS.TITLE_ACTION_DELETE_VALUE' | translate}}") - use(xlink:href="#icon-trash") + a.edit-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}", + svg-icon="icon-edit" + ) + a.delete-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}" + svg-icon="icon-trash" + ) div.project-values-row.row.table-main.edition.hidden div.project-values-name @@ -41,10 +46,11 @@ section.project-values-table input(name="value", type="text", placeholder="{{'COMMON.FIELDS.VALUE' | translate}}", ng-model="value.value", data-type="number") div.project-values-settings - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.cancel.icon.icon-close(href="", title="{{'COMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") + a.save(href="", title="{{'COMMON.SAVE' | translate}}") + tg-svg(svg-icon="icon-save") + + a.cancel(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg.cancel(svg-icon="icon-close") form div.project-values-row.new-value.hidden @@ -67,7 +73,8 @@ section.project-values-table ) div.project-values-settings - svg.add-new.icon.icon-save(title="{{'COMMON.ADD' | translate}}") - use(xlink:href="#icon-save") - svg.delete-new.icon.icon-trash(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-trash") + a.add-new(href="", title="{{'COMMON.ADD' | translate}}") + tg-svg(svg-icon="icon-save") + + a.delete-new(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg(svg-icon="icon-close") diff --git a/app/partials/includes/modules/admin/project-status.jade b/app/partials/includes/modules/admin/project-status.jade index 1540413d..863405ae 100644 --- a/app/partials/includes/modules/admin/project-status.jade +++ b/app/partials/includes/modules/admin/project-status.jade @@ -17,8 +17,7 @@ section.colors-table.admin-status-table div(ng-repeat="value in values", tg-bind-scope) form(tg-bind-scope) div.row.table-main.visualization - svg.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg(svg-icon="icon-drag") div.color-column div.current-color(ng-style="{background: value.color}") @@ -29,14 +28,22 @@ section.colors-table.admin-status-table span {{ value.slug }} div.is-closed-column - svg.icon.icon-check(ng-show="value.is_closed") - use(xlink:href="#icon-check") + tg-svg( + ng-show="value.is_closed" + svg-icon="icon-check" + ) div.options-column - svg.edit-value.icon.icon-edit(title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}") - use(xlink:href="#icon-edit") - svg.delete-value.icon.icon-trash(title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}") - use(xlink:href="#icon-trash") + a.edit-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}", + svg-icon="icon-edit" + ) + a.delete-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}" + svg-icon="icon-trash" + ) div.row.table-main.edition.hidden div.color-column( @@ -64,10 +71,11 @@ section.colors-table.admin-status-table ng-options="e.id as e.name | translate for e in [{'id':true, 'name':'COMMON.YES'},{'id':false, 'name': 'COMMON.NO'}]") div.options-column - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.cancel.icon.icon-close(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") + a.save(href="", title="{{'COMMON.SAVE' | translate}}") + tg-svg(svg-icon="icon-save") + + a.cancel(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg.cancel(svg-icon="icon-close") form div.row.table-main.new-value.hidden @@ -97,7 +105,8 @@ section.colors-table.admin-status-table ) div.options-column - svg.add-new.icon.icon-save(title="{{'COMMON.ADD' | translate}}") - use(xlink:href="#icon-save") - svg.delete-new.icon.icon-close(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") + a.add-new(href="", title="{{'COMMON.ADD' | translate}}") + tg-svg(svg-icon="icon-save") + + a.delete-new(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg(svg-icon="icon-close") diff --git a/app/partials/includes/modules/admin/project-types.jade b/app/partials/includes/modules/admin/project-types.jade index 12a53bce..8624fd5f 100644 --- a/app/partials/includes/modules/admin/project-types.jade +++ b/app/partials/includes/modules/admin/project-types.jade @@ -16,8 +16,7 @@ section.colors-table div(ng-repeat="value in values", tg-bind-scope) form(tg-bind-scope) div.row.table-main.visualization - svg.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg(svg-icon="icon-drag") div.color-column div.current-color(ng-style="{background: value.color}") @@ -26,10 +25,17 @@ section.colors-table span {{ value.name }} div.options-column - svg.edit-value.icon.icon-edit(title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}") - use(xlink:href="#icon-edit") - svg.delete-value.icon.icon-trash(title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}") - use(xlink:href="#icon-trash") + a.edit-value(href="") + tg-svg( + svg-icon="icon-edit", + title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}" + ) + + a.delete-value(href="") + tg-svg( + svg-icon="icon-trash", + title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}" + ) div.row.table-main.edition.hidden div.color-column( @@ -50,10 +56,16 @@ section.colors-table ) div.options-column - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.cancel.icon.icon-trash(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-trash") + a.save(href="") + tg-svg( + title="{{'COMMON.SAVE' | translate}}", + svg-icon="icon-save" + ) + a.cancel(href="") + tg-svg( + title="{{'COMMON.CANCEL' | translate}}", + svg-icon="icon-close" + ) form div.row.table-main.new-value.hidden @@ -75,7 +87,13 @@ section.colors-table ) div.options-column - svg.add-new.icon.icon-save(title="{{'COMMON.ADD' | translate}}") - use(xlink:href="#icon-save") - svg.delete-new.icon.icon-trash(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-trash") + a.add-new(href="") + tg-svg( + title="{{'COMMON.ADD' | translate}}", + svg-icon="icon-save" + ) + a.delete-new(href="") + tg-svg( + title="{{'COMMON.CANCEL' | translate}}", + svg-icon="icon-close" + ) diff --git a/app/partials/includes/modules/admin/project-us-status.jade b/app/partials/includes/modules/admin/project-us-status.jade index 892990d8..5660d4d2 100644 --- a/app/partials/includes/modules/admin/project-us-status.jade +++ b/app/partials/includes/modules/admin/project-us-status.jade @@ -21,8 +21,7 @@ section.project-us-status div(ng-repeat="value in values", tg-bind-scope) form(tg-bind-scope) div.row.table-main.visualization - svg.icon.icon-drag - use(xlink:href="#icon-drag") + tg-svg(svg-icon="icon-drag") div.color-column div.current-color(ng-style="{background: value.color}") @@ -34,21 +33,31 @@ section.project-us-status span {{ value.slug }} div.is-closed-column - svg.icon.icon-check(ng-show="value.is_closed") - use(xlink:href="#icon-check") + tg-svg( + ng-show="value.is_closed", + svg-icon="icon-check" + ) div.is-archived-column - svg.icon.icon-check(ng-show="value.is_archived") - use(xlink:href="#icon-check") + tg-svg( + ng-show="value.is_archived", + svg-icon="icon-check" + ) div.status-wip-limit span(ng-hide="value.is_archived") {{ value.wip_limit }} div.options-column - svg.edit-value.icon.icon-edit(title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}") - use(xlink:href="#icon-edit") - svg.delete-value.icon.icon-trash(title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}") - use(xlink:href="#icon-trash") + a.edit-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_EDIT_VALUE' | translate}}", + svg-icon="icon-edit" + ) + a.delete-value(href="") + tg-svg( + title="{{'ADMIN.COMMON.TITLE_ACTION_DELETE_VALUE' | translate}}", + svg-icon="icon-trash" + ) div.row.table-main.edition.hidden .color-column(tg-color-selection, ng-model="value") @@ -93,10 +102,10 @@ section.project-us-status ) .options-column - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.cancel.icon.icon-close(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") + a.save.icon-save(href="", title="{{'COMMON.SAVE' | translate}}") + tg-svg(svg-icon="icon-save") + a.cancel(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg(svg-icon="icon-close") form div.row.table-main.new-value.hidden @@ -141,7 +150,8 @@ section.project-us-status ) div.options-column - svg.add-new.icon.icon-save(title="{{'COMMON.ADD' | translate}}") - use(xlink:href="#icon-save") - svg.delete-new.icon.icon-trash(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-trash") + a.add-new(href="", title="{{'COMMON.ADD' | translate}}") + tg-svg(svg-icon="icon-save") + + a.delete-new(href="", title="{{'COMMON.CANCEL' | translate}}") + tg-svg(svg-icon="icon-trash") diff --git a/app/partials/includes/modules/backlog-filters.jade b/app/partials/includes/modules/backlog-filters.jade index 01b04ad7..6198bfaa 100644 --- a/app/partials/includes/modules/backlog-filters.jade +++ b/app/partials/includes/modules/backlog-filters.jade @@ -6,8 +6,10 @@ section.filters form fieldset input(type="text", placeholder="{{'COMMON.FILTERS.INPUT_PLACEHOLDER' | translate}}", ng-model="filtersQ") - svg.icon.icon-search(href="", title="{{'COMMON.FILTERS.TITLE_ACTION_FILTER_BUTTON' | translate}}") - use(xlink:href="#icon-search") + tg-svg.search-action( + svg-icon="icon-search", + title="{{'COMMON.FILTERS.TITLE_ACTION_FILTER_BUTTON' | translate}}" + ) div.filters-step-cat div.filters-applied @@ -17,8 +19,7 @@ section.filters title="{{'COMMON.FILTERS.BREADCRUMB_TITLE' | translate}}" translate="BACKLOG.FILTERS.TITLE" ) - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") a.subfilter(href="") span.title(translate="COMMON.FILTERS.BREADCRUMB_STATUS") div.filters-cats @@ -26,12 +27,10 @@ section.filters li a(href="", title="{{'BACKLOG.FILTERS.FILTER_CATEGORY_STATUS' | translate}}", data-type="status") span.title(translate="BACKLOG.FILTERS.FILTER_CATEGORY_STATUS") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li a(href="", title="{{'BACKLOG.FILTERS.FILTER_CATEGORY_TAGS' | translate}}", data-type="tags") span.title(translate="BACKLOG.FILTERS.FILTER_CATEGORY_TAGS") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") div.filter-list.hidden diff --git a/app/partials/includes/modules/backlog-table.jade b/app/partials/includes/modules/backlog-table.jade index b666dbe2..d59048ee 100644 --- a/app/partials/includes/modules/backlog-table.jade +++ b/app/partials/includes/modules/backlog-table.jade @@ -6,8 +6,7 @@ div.backlog-table-header div.status(translate="COMMON.FIELDS.STATUS") div.points(tg-us-role-points-selector, title="{{'BACKLOG.TABLE.TITLE_COLUMN_POINTS' | translate}}") span.header-points(translate="COMMON.FIELDS.POINTS") - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") div.backlog-table-body(tg-backlog-sortable, ng-class="{'show-tags': ctrl.showTags, 'active-filters': ctrl.activeFilters}" ) include ../components/backlog-row diff --git a/app/partials/includes/modules/issues-filters.jade b/app/partials/includes/modules/issues-filters.jade index b879fd56..73a68419 100644 --- a/app/partials/includes/modules/issues-filters.jade +++ b/app/partials/includes/modules/issues-filters.jade @@ -6,59 +6,79 @@ section.filters fieldset input(type="text", placeholder="{{'ISSUES.FILTERS.INPUT_SEARCH_PLACEHOLDER' | translate}}", ng-model="filtersQ") - svg.icon.icon-search(title="{{'ISSUES.FILTERS.TITLE_ACTION_SEARCH' | translate}}") - use(xlink:href="#icon-search") + tg-svg(svg-icon="icon-search", title="{{'ISSUES.FILTERS.TITLE_ACTION_SEARCH' | translate}}") div.filters-step-cat div.filters-applied a.hide.button.button-gray.save-filters(href="", title="{{'COMMON.SAVE' | translate}}", ng-class="{hide: filters.length}", translate="ISSUES.FILTERS.ACTION_SAVE_CUSTOM_FILTER") h2.hidden.breadcrumb a.back(href="", title="{{'ISSUES.FILTERS.TITLE_BREADCRUMB' | translate}}", translate="ISSUES.FILTERS.BREADCRUMB") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") a.subfilter(href="", title="cat-name") span.title(translate="COMMON.FILTERS.BREADCRUMB_STATUS") div.filters-cats ul li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.TYPE' | translate}}", data-type="types") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.TYPE' | translate}}" + data-type="types" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.TYPE") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.STATUS' | translate}}", data-type="status") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.STATUS' | translate}}" + data-type="status" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.STATUS") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.SEVERITY' | translate}}", data-type="severities") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.SEVERITY' | translate}}" + data-type="severities" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.SEVERITY") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.PRIORITIES' | translate}}", data-type="priorities") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.PRIORITIES' | translate}}" + data-type="priorities" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.PRIORITIES") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.TAGS' | translate}}", data-type="tags") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.TAGS' | translate}}" + data-type="tags" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.TAGS") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.ASSIGNED_TO' | translate}}", data-type="assignedTo") + a.filters-cat-single(href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.ASSIGNED_TO' | translate}}" + data-type="assignedTo" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.ASSIGNED_TO") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.CREATED_BY' | translate}}", data-type="createdBy") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.CREATED_BY' | translate}}" + data-type="createdBy" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.CREATED_BY") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li.custom-filters(ng-if="filters.myFilters.length") - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.CUSTOM_FILTERS' | translate}}", - data-type="myFilters") + a.filters-cat-single( + href="" + title="{{ 'ISSUES.FILTERS.CATEGORIES.CUSTOM_FILTERS' | translate}}" + data-type="myFilters" + ) span.title(translate="ISSUES.FILTERS.CATEGORIES.CUSTOM_FILTERS") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") div.filter-list.hidden diff --git a/app/partials/includes/modules/issues-options.jade b/app/partials/includes/modules/issues-options.jade index 2a9692eb..dca113dc 100644 --- a/app/partials/includes/modules/issues-options.jade +++ b/app/partials/includes/modules/issues-options.jade @@ -3,5 +3,4 @@ section.issues-options(tg-check-permission="add_issue") a.button-green(href="", ng-click="ctrl.addNewIssue()") span.text(translate="ISSUES.ACTION_NEW_ISSUE") a.button-bulk(href="", ng-click="ctrl.addIssuesInBulk()") - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg(svg-icon="icon-bulk") diff --git a/app/partials/includes/modules/issues-table.jade b/app/partials/includes/modules/issues-table.jade index e23a3025..10f4473e 100644 --- a/app/partials/includes/modules/issues-table.jade +++ b/app/partials/includes/modules/issues-table.jade @@ -20,8 +20,7 @@ section.issues-table.basic-table(ng-class="{empty: !issues.length}") ng-class="{'inactive': !issue.total_voters, 'is-voted': issue.is_voter}" title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:issue.total_voters||0}:'messageformat' }}" ) - svg.icon.icon-upvote - use(xlink:href="#icon-upvote") + tg-svg(svg-icon="icon-upvote") span {{ ::issue.total_voters }} div.subject a( @@ -43,16 +42,20 @@ section.issues-table.basic-table(ng-class="{empty: !issues.length}") title="{{'ISSUES.TABLE.TITLE_ACTION_CHANGE_STATUS' | translate}}" ) span.issue-status-bind - svg.icon.icon-arrow-down(tg-check-permission="modify_issue") - use(xlink:href="#icon-arrow-down") + tg-svg( + tg-check-permission="modify_issue" + svg-icon="icon-arrow-down" + ) div.created-field(tg-bo-bind="issue.created_date|momentFormat:'DD MMM YYYY HH:mm'") div.assigned-field(tg-issue-assigned-to-inline-edition="issue") div.issue-assignedto(title="{{'ISSUES.TABLE.TITLE_ACTION_ASSIGNED_TO' | translate}}") figure.avatar - svg.icon.icon-arrow-down(tg-check-permission="modify_issue") - use(xlink:href="#icon-arrow-down") + tg-svg( + tg-check-permission="modify_issue" + svg-icon="icon-arrow-down" + ) section.empty-issues(ng-if="issues != undefined && issues.length == 0") img( diff --git a/app/partials/includes/modules/kanban-table.jade b/app/partials/includes/modules/kanban-table.jade index 502fef51..4706029f 100644 --- a/app/partials/includes/modules/kanban-table.jade +++ b/app/partials/includes/modules/kanban-table.jade @@ -13,32 +13,28 @@ div.kanban-table(tg-kanban-squish-column) title="{{'KANBAN.TITLE_ACTION_FOLD' | translate}}" ng-class='{hidden:folds[s.id]}' ) - svg.icon.icon-fold-column - use(xlink:href="#icon-fold-column") + tg-svg(svg-icon="icon-fold-column") a.option.hunfold( href="" ng-click='foldStatus(s)' title="{{'KANBAN.TITLE_ACTION_UNFOLD' | translate}}" ng-class='{hidden:!folds[s.id]}' ) - svg.icon.icon-unfold-column - use(xlink:href="#icon-unfold-column") + tg-svg(svg-icon="icon-unfold-column") a.option( href="" title="{{'KANBAN.TITLE_ACTION_FOLD_CARDS' | translate}}" ng-class="{hidden:statusViewModes[s.id] == 'minimized'}" ng-click="ctrl.updateStatusViewMode(s.id, 'minimized')" ) - svg.icon.icon-fold-row - use(xlink:href="#icon-fold-row") + tg-svg.fold-action(svg-icon="icon-fold-row") a.option( href="" title="{{'KANBAN.TITLE_ACTION_UNFOLD_CARDS' | translate}}" ng-class="{hidden:statusViewModes[s.id] == 'maximized'}" ng-click="ctrl.updateStatusViewMode(s.id, 'maximized')" ) - svg.icon.icon-unfold-row - use(xlink:href="#icon-unfold-row") + tg-svg.fold-action(svg-icon="icon-unfold-row") a.option( href="" @@ -47,8 +43,7 @@ div.kanban-table(tg-kanban-squish-column) tg-check-permission="add_us" ng-hide="s.is_archived" ) - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg.add-action(svg-icon="icon-add") a.option( href="" @@ -57,8 +52,7 @@ div.kanban-table(tg-kanban-squish-column) tg-check-permission="add_us" ng-hide="s.is_archived" ) - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg.bulk-action(svg-icon="icon-bulk") a.option( href="" @@ -66,8 +60,7 @@ div.kanban-table(tg-kanban-squish-column) ng-class="class" ng-if="s.is_archived" tg-kanban-archived-status-header="s") - svg.icon.icon-watch - use(xlink:href="#icon-watch") + tg-svg.bulk-action(svg-icon="icon-watch") div.kanban-table-body div.kanban-table-inner diff --git a/app/partials/includes/modules/lightbox-ask-choice.jade b/app/partials/includes/modules/lightbox-ask-choice.jade index c1f5a0fb..485661ef 100644 --- a/app/partials/includes/modules/lightbox-ask-choice.jade +++ b/app/partials/includes/modules/lightbox-ask-choice.jade @@ -1,6 +1,5 @@ -a.close(href="", title="{{'COMMON.CLOSE' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title p.question diff --git a/app/partials/includes/modules/lightbox-create-issue.jade b/app/partials/includes/modules/lightbox-create-issue.jade index 829d660f..d1f4f37b 100644 --- a/app/partials/includes/modules/lightbox-create-issue.jade +++ b/app/partials/includes/modules/lightbox-create-issue.jade @@ -1,9 +1,5 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title(translate="LIGHTBOX.CREATE_ISSUE.TITLE") fieldset diff --git a/app/partials/includes/modules/lightbox-delete-project.jade b/app/partials/includes/modules/lightbox-delete-project.jade index c360d23d..60352f3e 100644 --- a/app/partials/includes/modules/lightbox-delete-project.jade +++ b/app/partials/includes/modules/lightbox-delete-project.jade @@ -1,6 +1,4 @@ -a.close(href="", title="{{'close' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="LIGHTBOX.DELETE_PROJECT.TITLE") p diff --git a/app/partials/includes/modules/lightbox-generic-ask.jade b/app/partials/includes/modules/lightbox-generic-ask.jade index 6ddcaf0a..002715bc 100644 --- a/app/partials/includes/modules/lightbox-generic-ask.jade +++ b/app/partials/includes/modules/lightbox-generic-ask.jade @@ -1,6 +1,5 @@ -a.close(href="", title="{{'COMMON.CLOSE' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title p diff --git a/app/partials/includes/modules/lightbox-generic-error.jade b/app/partials/includes/modules/lightbox-generic-error.jade index 343dbaa6..a23abf90 100644 --- a/app/partials/includes/modules/lightbox-generic-error.jade +++ b/app/partials/includes/modules/lightbox-generic-error.jade @@ -1,9 +1,5 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + section h2.title .options diff --git a/app/partials/includes/modules/lightbox-generic-success.jade b/app/partials/includes/modules/lightbox-generic-success.jade index 02bf8c0a..40f704c3 100644 --- a/app/partials/includes/modules/lightbox-generic-success.jade +++ b/app/partials/includes/modules/lightbox-generic-success.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close section h2.title p.message diff --git a/app/partials/includes/modules/lightbox-issue-bulk.jade b/app/partials/includes/modules/lightbox-issue-bulk.jade index b418e7d5..b154c05b 100644 --- a/app/partials/includes/modules/lightbox-issue-bulk.jade +++ b/app/partials/includes/modules/lightbox-issue-bulk.jade @@ -1,9 +1,5 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title(translate="COMMON.NEW_BULK") fieldset diff --git a/app/partials/includes/modules/lightbox-sprint-add-edit.jade b/app/partials/includes/modules/lightbox-sprint-add-edit.jade index 148084eb..e0ceddc7 100644 --- a/app/partials/includes/modules/lightbox-sprint-add-edit.jade +++ b/app/partials/includes/modules/lightbox-sprint-add-edit.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="LIGHTBOX.ADD_EDIT_SPRINT.TITLE") @@ -51,7 +46,4 @@ form title="{{'LIGHTBOX.ADD_EDIT_SPRINT.TITLE_ACTION_DELETE_SPRINT' | translate}}" ) span {{'LIGHTBOX.ADD_EDIT_SPRINT.ACTION_DELETE_SPRINT' | translate }} - svg.icon.icon-trash( - href="" - ) - use(xlink:href="#icon-trash") + tg-svg(svg-icon="icon-trash") diff --git a/app/partials/includes/modules/lightbox-task-bulk.jade b/app/partials/includes/modules/lightbox-task-bulk.jade index 7fac9d2e..bc523dae 100644 --- a/app/partials/includes/modules/lightbox-task-bulk.jade +++ b/app/partials/includes/modules/lightbox-task-bulk.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="COMMON.NEW_BULK") fieldset diff --git a/app/partials/includes/modules/lightbox-task-create-edit.jade b/app/partials/includes/modules/lightbox-task-create-edit.jade index 68fef13c..41fcf957 100644 --- a/app/partials/includes/modules/lightbox-task-create-edit.jade +++ b/app/partials/includes/modules/lightbox-task-create-edit.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="LIGHTBOX.CREATE_EDIT_TASK.TITLE") fieldset @@ -65,8 +60,7 @@ form ng-value="true" ) label.iocaine.trans-button(for="iocaine-task") - svg.icon.icon-iocaine(for="iocaine-task icon-iocaine") - use(xlink:href="#icon-iocaine") + tg-svg(svg-icon="icon-iocaine") span Iocaine fieldset.blocking-flag diff --git a/app/partials/includes/modules/lightbox-us-bulk.jade b/app/partials/includes/modules/lightbox-us-bulk.jade index b522a0ed..73b65343 100644 --- a/app/partials/includes/modules/lightbox-us-bulk.jade +++ b/app/partials/includes/modules/lightbox-us-bulk.jade @@ -1,9 +1,4 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close form h2.title(translate="COMMON.NEW_BULK") fieldset diff --git a/app/partials/includes/modules/lightbox-us-create-edit.jade b/app/partials/includes/modules/lightbox-us-create-edit.jade index c03c8010..7345e627 100644 --- a/app/partials/includes/modules/lightbox-us-create-edit.jade +++ b/app/partials/includes/modules/lightbox-us-create-edit.jade @@ -1,9 +1,5 @@ -a.close( - href="" - title="{{'COMMON.CLOSE' | translate}}" -) - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title(translate="LIGHTBOX.CREATE_EDIT_US.TITLE") fieldset @@ -80,7 +76,7 @@ form type="checkbox" name="is_blocked" ng-model="us.is_blocked" - id="blocked-us" + id="blocked-us" ng-value="true" ) label.blocked.trans-button( diff --git a/app/partials/includes/modules/login-form.jade b/app/partials/includes/modules/login-form.jade index bb62082d..96927f3b 100644 --- a/app/partials/includes/modules/login-form.jade +++ b/app/partials/includes/modules/login-form.jade @@ -1,4 +1,4 @@ -div.login-form-container(tg-login) +.login-form-container(tg-login) form.login-form fieldset input( @@ -16,18 +16,20 @@ div.login-form-container(tg-login) input( type="password" name="password" - tg-capslock data-required="true" placeholder="{{'LOGIN_COMMON.PLACEHOLDER_AUTH_PASSWORD' | translate}}" + ng-focus="capslockIcon = !capslockIcon" + ng-keyup="onKeyUp($event)" ) - // This should be hidden when focus on pass a.forgot-pass( href="" tg-nav="forgot-password" title="{{'LOGIN_COMMON.TITLE_LINK_FORGOT_PASSWORD' | translate}}" translate="LOGIN_COMMON.LINK_FORGOT_PASSWORD" ) + + tg-capslock fieldset button.button-green.submit-button( diff --git a/app/partials/includes/modules/search-filter.jade b/app/partials/includes/modules/search-filter.jade index 3304a5cc..2cf10b90 100644 --- a/app/partials/includes/modules/search-filter.jade +++ b/app/partials/includes/modules/search-filter.jade @@ -4,8 +4,7 @@ ul.search-filter href="#" title="{{ 'SEARCH.FILTER_USER_STORIES' | translate }}" ) - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg(svg-icon="icon-bulk") span.num span.name(translate="SEARCH.FILTER_USER_STORIES") @@ -14,8 +13,7 @@ ul.search-filter href="#" title="{{ 'SEARCH.FILTER_ISSUES' | translate }}" ) - svg.icon.icon-issues - use(xlink:href="#icon-issues") + tg-svg(svg-icon="icon-issues") span.num span.name(translate="SEARCH.FILTER_ISSUES") @@ -24,8 +22,7 @@ ul.search-filter href="#" title="{{ 'SEARCH.FILTER_TASKS' | translate }}" ) - svg.icon.icon-bulk - use(xlink:href="#icon-bulk") + tg-svg(svg-icon="icon-bulk") span.num span.name(translate="SEARCH.FILTER_TASKS") @@ -34,7 +31,6 @@ ul.search-filter href="#" title="{{ 'SEARCH.FILTER_WIKI' | translate }}" ) - svg.icon.icon-wiki - use(xlink:href="#icon-wiki") + tg-svg(svg-icon="icon-wiki") span.num span.name(translate="SEARCH.FILTER_WIKI") diff --git a/app/partials/includes/modules/search-in.jade b/app/partials/includes/modules/search-in.jade index e16d70ee..748fc4f6 100644 --- a/app/partials/includes/modules/search-in.jade +++ b/app/partials/includes/modules/search-in.jade @@ -7,5 +7,4 @@ section.search-in ng-model="searchTerm" ) .icon-search-wrapper(tg-loading="loading") - svg.icon.icon-search(title="{{'SEARCH.TITLE_ACTION_SEARCH' | translate}}") - use(xlink:href="#icon-search") + tg-svg(svg-icon="icon-search", title="{{'SEARCH.TITLE_ACTION_SEARCH' | translate}}") diff --git a/app/partials/includes/modules/sprints.jade b/app/partials/includes/modules/sprints.jade index 82066a18..0b52dd40 100644 --- a/app/partials/includes/modules/sprints.jade +++ b/app/partials/includes/modules/sprints.jade @@ -13,8 +13,7 @@ section.sprints ng-if="totalMilestones" tg-check-permission="add_milestone" ) - svg.icon.icon-add - use(xlink:href="#icon-add") + tg-svg(svg-icon="icon-add") div.sprints-empty(ng-if="totalMilestones === 0") img( @@ -37,8 +36,7 @@ section.sprints a.filter-closed-sprints(href="", tg-backlog-toggle-closed-sprints-visualization, ng-if="totalClosedMilestones") - svg.icon.icon-archive - use(xlink:href="#icon-archive") + tg-svg(svg-icon="icon-archive") span.text(translate="BACKLOG.SPRINTS.ACTION_SHOW_CLOSED_SPRINTS") div.sprint.sprint-closed(ng-repeat="sprint in closedSprints track by sprint.id", diff --git a/app/partials/includes/modules/taskboard-table.jade b/app/partials/includes/modules/taskboard-table.jade index a87acc12..7f5f67c8 100644 --- a/app/partials/includes/modules/taskboard-table.jade +++ b/app/partials/includes/modules/taskboard-table.jade @@ -4,39 +4,39 @@ div.taskboard-table(tg-taskboard-squish-column) h2.task-colum-name(translate="TASKBOARD.TABLE.COLUMN") h2.task-colum-name(ng-repeat="s in taskStatusList track by s.id", ng-style="{'border-top-color':s.color}", ng-class="{'column-fold':statusesFolded[s.id]}", class="squish-status-{{s.id}}", tg-bo-title="s.name") span(tg-bo-bind="s.name") - svg.icon.icon-fold-row.hfold( - ng-click='foldStatus(s)' + + tg-svg.hfold.fold-action( + svg-icon="icon-fold-row", + ng-click='foldStatus(s)', title="{{'TASKBOARD.TABLE.TITLE_ACTION_FOLD' | translate}}" ng-class='{hidden:statusesFolded[s.id]}' ) - use(xlink:href="#icon-fold-row") - - svg.icon.icon-fold-row.hunfold( + + tg-svg.hunfold.fold-action( + svg-icon="icon-unfold-row", + ng-click='foldStatus(s)', title="{{'TASKBOARD.TABLE.TITLE_ACTION_UNFOLD' | translate}}" - ng-click='foldStatus(s)' ng-class='{hidden:!statusesFolded[s.id]}' ) - use(xlink:href="#icon-unfold-row") div.taskboard-table-body(tg-taskboard-table-height-fixer) div.taskboard-table-inner div.task-row(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked, 'row-fold':usFolded[us.id]}") div.taskboard-userstory-box.task-column(tg-bo-title="us.blocked_note") - - svg.icon.icon-fold-row.vfold( - title="{{'TASKBOARD.TABLE.TITLE_ACTION_FOLD_ROW' | translate}}" + tg-svg.vfold.fold-action( + svg-icon="icon-fold-row", ng-click='foldUs(us)' + title="{{'TASKBOARD.TABLE.TITLE_ACTION_FOLD_ROW' | translate}}" ng-class='{hidden:usFolded[us.id]}' ) - use(xlink:href="#icon-fold-row") - - svg.icon.icon-unfold-row.vunfold( - title="{{'TASKBOARD.TABLE.TITLE_ACTION_UNFOLD_ROW' | translate}}" + + tg-svg.vunfold.fold-action( + svg-icon="icon-unfold-row", ng-click='foldUs(us)' + title="{{'TASKBOARD.TABLE.TITLE_ACTION_UNFOLD_ROW' | translate}}" ng-class='{hidden:!usFolded[us.id]}' ) - use(xlink:href="#icon-fold-row") - + h3.us-title a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref", @@ -71,16 +71,14 @@ div.taskboard-table(tg-taskboard-squish-column) ng-click='foldUs()' ng-class="{hidden:usFolded[null]}" ) - svg.icon.icon-fold-row - use(xlink:href="#icon-fold-row") + tg-svg.fold-action(svg-icon="icon-fold-row") a.vunfold( href="" title="{{'TASKBOARD.TABLE.TITLE_ACTION_UNFOLD_ROW' | translate}}" ng-click='foldUs()' ng-class="{hidden:!usFolded[null]}" ) - svg.icon.icon-unfold-row - use(xlink:href="#icon-unfold-row") + tg-svg.fold-action(svg-icon="icon-unfold-row") h3.us-title span(translate="TASKBOARD.TABLE.ROW_UNASSIGED_TASKS_TITLE") include ../components/addnewtask.jade diff --git a/app/partials/includes/modules/team/team-filters.jade b/app/partials/includes/modules/team/team-filters.jade index 72b104a0..33059928 100644 --- a/app/partials/includes/modules/team/team-filters.jade +++ b/app/partials/includes/modules/team/team-filters.jade @@ -7,7 +7,9 @@ section.team-filters fieldset input(type="text", placeholder="{{'TEAM.PLACEHOLDER_INPUT_SEARCH' | translate}}", ng-model="filtersQ") .icon-search-wrapper - svg.icon.icon-search(title="{{'COMMON.FILTERS.TITLE_ACTION_FILTER_BUTTON' | translate}}") - use(xlink:href="#icon-search") + tg-svg( + svg-icon="icon-search", + title="{{'COMMON.FILTERS.TITLE_ACTION_FILTER_BUTTON' | translate}}" + ) nav(tg-team-filters) diff --git a/app/partials/issue/iocaine-button.jade b/app/partials/issue/iocaine-button.jade index 25406e92..74645c0c 100644 --- a/app/partials/issue/iocaine-button.jade +++ b/app/partials/issue/iocaine-button.jade @@ -3,8 +3,7 @@ fieldset(title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}") for="is-iocaine" class!="<% if(isEditable){ %>is-editable<% }; %> <% if(isIocaine){ %>active<% }; %>" ) - svg.icon.icon-iocaine - use(xlink:href="#icon-iocaine") + tg-svg(svg-icon="icon-iocaine") input( type="checkbox" id="is-iocaine" diff --git a/app/partials/issue/issue-priority-button.jade b/app/partials/issue/issue-priority-button.jade index 0e82506b..b01bdb08 100644 --- a/app/partials/issue/issue-priority-button.jade +++ b/app/partials/issue/issue-priority-button.jade @@ -2,8 +2,7 @@ div(class!="priority-data <% if(editable){ %>clickable<% }%>") span(class="level", style!="background-color:<%- priority.color %>") span(class="priority-priority") <%- priority.name %> <% if(editable){ %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }%> span(class="level-name", translate="COMMON.FIELDS.PRIORITY") diff --git a/app/partials/issue/issue-severity-button.jade b/app/partials/issue/issue-severity-button.jade index 377e7346..4920203f 100644 --- a/app/partials/issue/issue-severity-button.jade +++ b/app/partials/issue/issue-severity-button.jade @@ -1,16 +1,18 @@ -div(class!="severity-data <% if(editable){ %>clickable<% }%>") - span(class="level", style!="background-color:<%- severity.color %>") - span(class="severity-severity") <%- severity.name %> +.severity-data(class!="<% if(editable){ %>clickable<% }%>") + span.level(style!="background-color:<%- severity.color %>") + span.severity-severity <%- severity.name %> <% if(editable){ %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }%> - span(class="level-name", translate="COMMON.FIELDS.SEVERITY") + span.level-name(translate="COMMON.FIELDS.SEVERITY") - ul(class="popover pop-severity") + ul.popover.pop-severity <% _.each(severityes, function(sv) { %> li - a(href="" class="severity" title!="<%- sv.name %>" - data-severity-id!="<%- sv.id %>") + a.severity( + href="" + title!="<%- sv.name %>" + data-severity-id!="<%- sv.id %>" + ) <%- sv.name %> <% }); %> diff --git a/app/partials/issue/issue-type-button.jade b/app/partials/issue/issue-type-button.jade index 9a050bb2..1301b4a7 100644 --- a/app/partials/issue/issue-type-button.jade +++ b/app/partials/issue/issue-type-button.jade @@ -1,16 +1,17 @@ -div(class!="type-data <% if(editable){ %>clickable<% }%>") - span(class="level", style!="background-color:<%- type.color %>") - span(class="type-type") <%- type.name %> +.type-data(class!="<% if(editable){ %>clickable<% }%>") + span.level(style!="background-color:<%- type.color %>") + span.type-type <%- type.name %> <% if(editable){ %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }%> - span(class="level-name", translate="COMMON.FIELDS.TYPE") + span.level-name(translate="COMMON.FIELDS.TYPE") - ul(class="popover pop-type") + ul.popover.pop-type <% _.each(typees, function(tp) { %> li - a(href="", class="type", title!="<%- tp.name %>", - data-type-id!="<%- tp.id %>") - | <%- tp.name %> + a.type( + href="" + title!="<%- tp.name %>" + data-type-id!="<%- tp.id %>" + ) <%- tp.name %> <% }); %> diff --git a/app/partials/issue/issues-detail.jade b/app/partials/issue/issues-detail.jade index 056e718f..aa8dfefa 100644 --- a/app/partials/issue/issues-detail.jade +++ b/app/partials/issue/issues-detail.jade @@ -22,8 +22,7 @@ div.wrapper( span.us-number(tg-bo-ref="issue.ref") span.us-name(tg-editable-subject, ng-model="issue", required-perm="modify_issue") - p.us-related-task(ng-if="issue.generated_user_stories.length") - | {{ 'ISSUES.PROMOTED'|translate }} + p.us-related-task(ng-if="issue.generated_user_stories.length") {{ 'ISSUES.PROMOTED'|translate }} a( href="" ng-repeat="us in issue.generated_user_stories" @@ -52,21 +51,32 @@ div.wrapper( tg-bo-href="previousUrl" title="{{'ISSUES.TITLE_PREVIOUS_ISSUE' | translate}}" ) - svg.icon.icon-arrow-left - use(xlink:href="#icon-arrow-left") + tg-svg( + svg-icon="icon-arrow-left" + ) a( ng-show="nextUrl" tg-bo-href="nextUrl" title="{{'ISSUES.TITLE_NEXT_ISSUE' | translate}}" - ) - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + ) + tg-svg( + svg-icon="icon-arrow-right" + ) .subheader - div.tags-block(tg-tag-line, ng-model="issue", required-perm="modify_issue") + .tags-block( + tg-tag-line + ng-model="issue" + required-perm="modify_issue" + ) tg-created-by-display.ticket-created-by(ng-model="issue") - section.duty-content(tg-editable-description, tg-editable-wysiwyg, ng-model="issue", required-perm="modify_issue") + section.duty-content( + tg-editable-description + tg-editable-wysiwyg + ng-model="issue" + required-perm="modify_issue" + ) // Custom Fields tg-custom-attributes-values( @@ -83,10 +93,13 @@ div.wrapper( edit-permission = "modify_issue" ) - tg-history(ng-model="issue", type="issue") + tg-history( + ng-model="issue" + type="issue" + ) sidebar.menu-secondary.sidebar.ticket-data - + .ticket-header span.ticket-title( tg-issue-status-display @@ -96,15 +109,28 @@ div.wrapper( tg-issue-status-button ng-model="issue" ) - - //tg-created-by-display.ticket-created-by(ng-model="issue") - - div.ticket-data-container - div.ticket-status(tg-issue-type-button, ng-model="issue") - div.ticket-status(tg-issue-severity-button, ng-model="issue") - div.ticket-status(tg-issue-priority-button, ng-model="issue") - section.ticket-assigned-to(tg-assigned-to, ng-model="issue", required-perm="modify_issue") + //tg-created-by-display.ticket-created-by(ng-model="issue") + + div.ticket-data-container + div.ticket-status( + tg-issue-type-button + ng-model="issue" + ) + div.ticket-status( + tg-issue-severity-button + ng-model="issue" + ) + div.ticket-status( + tg-issue-priority-button + ng-model="issue" + ) + + section.ticket-assigned-to( + tg-assigned-to + ng-model="issue" + required-perm="modify_issue" + ) section.ticket-watch-buttons div.ticket-watch( @@ -122,11 +148,11 @@ div.wrapper( section.ticket-detail-settings tg-promote-issue-to-us-button( - tg-check-permission="add_us", + tg-check-permission="add_us", ng-model="issue" ) tg-block-button( - tg-check-permission="modify_issue", + tg-check-permission="modify_issue", ng-model="issue" ) tg-delete-button( diff --git a/app/partials/issue/issues-filters-selected.jade b/app/partials/issue/issues-filters-selected.jade index 187ba9f6..29e0a12e 100644 --- a/app/partials/issue/issues-filters-selected.jade +++ b/app/partials/issue/issues-filters-selected.jade @@ -1,9 +1,9 @@ <% _.each(filters, function(f) { %> -a.single-filter.selected( +.single-filter.selected( data-type!="<%- f.type %>" data-id!="<%- f.id %>" ) span.name(style!="<%- f.style %>") <%- f.name %> - svg.icon.icon-close.remove-filter - use(xlink:href="#icon-close") + a.remove-filter(href="") + tg-svg(svg-icon="icon-close") <% }) %> diff --git a/app/partials/issue/issues-filters.jade b/app/partials/issue/issues-filters.jade index 3dfa76ef..95763e72 100644 --- a/app/partials/issue/issues-filters.jade +++ b/app/partials/issue/issues-filters.jade @@ -1,17 +1,22 @@ <% _.each(filters, function(f) { %> <% if (!f.selected) { %> -a(class="single-filter", data-type!="<%- f.type %>", data-id!="<%- f.id %>") - span(class="name", style!="<%- f.style %>") - | <%- f.name %> +.single-filter( + data-type!="<%- f.type %>" + data-id!="<%- f.id %>" +) + span.name(style!="<%- f.style %>") <%- f.name %> <% if (f.count){ %> - span(class="number") <%- f.count %> + span.number <%- f.count %> <% } %> <% if (f.type == "myFilters"){ %> - svg.icon.icon-close.remove-filter - use(xlink:href="#icon-close") + a.remove-filter(href="") + tg-svg(svg-icon="icon-trash") <% } %> <% } %> <% }) %> span(class="new") -input(class="hidden my-filter-name", type="text", - placeholder="{{'ISSUES.PLACEHOLDER_FILTER_NAME' | translate}}") +input( + class="hidden my-filter-name" + type="text" + placeholder="{{'ISSUES.PLACEHOLDER_FILTER_NAME' | translate}}" +) diff --git a/app/partials/issue/issues-status-button.jade b/app/partials/issue/issues-status-button.jade index 39f67881..593ded89 100644 --- a/app/partials/issue/issues-status-button.jade +++ b/app/partials/issue/issues-status-button.jade @@ -5,8 +5,7 @@ span.detail-status-inner.js-edit-status( ) span <%- status.name %> <% if(editable){ %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }%> ul.popover.pop-status diff --git a/app/partials/issue/promote-issue-to-us-button.jade b/app/partials/issue/promote-issue-to-us-button.jade index 2a241ca1..fe2bd499 100644 --- a/app/partials/issue/promote-issue-to-us-button.jade +++ b/app/partials/issue/promote-issue-to-us-button.jade @@ -1,6 +1,6 @@ a.promote-button.is-editable( + href="" tg-check-permission="add_us" title="{{ 'ISSUES.ACTION_PROMOTE_TO_US' | translate }}" ) - svg.icon.icon-promote - use(xlink:href="#icon-promote") + tg-svg(svg-icon="icon-promote") diff --git a/app/partials/kanban/kanban-task.jade b/app/partials/kanban/kanban-task.jade index a863a07b..46fed783 100644 --- a/app/partials/kanban/kanban-task.jade +++ b/app/partials/kanban/kanban-task.jade @@ -24,9 +24,10 @@ div.kanban-task-inner(ng-class="{'task-archived': us.isArchived}") span.task-name(ng-bind="us.subject") p(translate="KANBAN.UNDO_ARCHIVED") - svg.icon.icon-edit( - tg-check-permission="modify_us" - title="{{'COMMON.EDIT' | translate}}" + a.edit-us( + href="", + title="{{'COMMON.EDIT' | translate}}", + tg-check-permission="modify_us", ng-hide="us.isArchived" ) - use(xlink:href="#icon-edit") + tg-svg(svg-icon="icon-edit") diff --git a/app/partials/project/wizard-create-project.jade b/app/partials/project/wizard-create-project.jade index ca9808be..e381369c 100644 --- a/app/partials/project/wizard-create-project.jade +++ b/app/partials/project/wizard-create-project.jade @@ -1,5 +1,4 @@ -svg.close.icon.icon-close(title="{{'COMMON.CLOSE' | translate}}") - use(xlink:href="#icon-close") +tg-lightbox-close form header h1.title(translate="WIZARD.SECTION_TITLE_CREATE_PROJECT") @@ -27,8 +26,7 @@ form data-required="true" ) label.template-label(for="template-{{ template.id }}") - svg.icon(ng-class="'icon-'+template.slug") - use(xlink:href="{{'#icon-' + template.slug }}") + tg-svg(svg-icon="{{'icon-'+template.slug}}") span.template-name {{ template.name }} .template-data legend(translate="WIZARD.PROJECT_DETAILS") @@ -64,8 +62,7 @@ form ng-checked="canCreatePublicProjects.valid" ) label.template-privacity(for="template-public") - svg.icon.icon-discover - use(xlink:href="#icon-discover") + tg-svg(svg-icon="icon-discover") span(translate="WIZARD.PUBLIC_PROJECT") fieldset input( @@ -81,12 +78,11 @@ form ng-checked="!canCreatePublicProjects.valid" ) label.template-privacity(for="template-private") - svg.icon.icon-lock - use(xlink:href="#icon-lock") + tg-svg(svg-icon="icon-lock") span(translate="WIZARD.PRIVATE_PROJECT") - + tg-create-project-restriction - + button.button-green.submit-button( translate="WIZARD.CREATE_PROJECT" title="{{'WIZARD.CREATE_PROJECT' | translate}}" diff --git a/app/partials/project/wizard-restrictions.jade b/app/partials/project/wizard-restrictions.jade index 798bf1fd..fb80f608 100644 --- a/app/partials/project/wizard-restrictions.jade +++ b/app/partials/project/wizard-restrictions.jade @@ -1,9 +1,7 @@ div.create-warning(ng-if="!canCreatePrivateProjects.valid && canCreatePrivateProjects.reason == 'max_private_projects'") - svg.icon.icon-exclamation - use(xlink:href="#icon-exclamation") + tg-svg(svg-icon="icon-exclamation") span {{ 'WIZARD.MAX_PRIVATE_PROJECTS' | translate }} - + div.create-warning(ng-if="!canCreatePublicProjects.valid && canCreatePublicProjects.reason == 'max_public_projects'") - svg.icon.icon-exclamation - use(xlink:href="#icon-exclamation") + tg-svg(svg-icon="icon-exclamation") span {{ 'WIZARD.MAX_PUBLIC_PROJECTS' | translate }} diff --git a/app/partials/search/lightbox-search.jade b/app/partials/search/lightbox-search.jade index 328deb21..5090ca52 100644 --- a/app/partials/search/lightbox-search.jade +++ b/app/partials/search/lightbox-search.jade @@ -1,6 +1,5 @@ -a.close(href="", title="{{'COMMON.CLOSE' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title(translate="LIGHTBOX.SEARCH.TITLE") fieldset diff --git a/app/partials/task/related-task-create-form.jade b/app/partials/task/related-task-create-form.jade index 997b8a60..996cf7e9 100644 --- a/app/partials/task/related-task-create-form.jade +++ b/app/partials/task/related-task-create-form.jade @@ -1,20 +1,15 @@ -.tasks - .task-name - input(type='text', placeholder="{{'TASK.PLACEHOLDER_SUBJECT' | translate}}") - .task-settings - svg.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.icon.icon-close.cancel-edit(href='', title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") +.task-name + input(type='text', placeholder="{{'TASK.PLACEHOLDER_SUBJECT' | translate}}") +.task-settings + a.save-task(title="{{'COMMON.SAVE' | translate}}") + tg-svg(svg-icon="icon-save") .status(tg-related-task-status='newTask', ng-model='newTask', not-auto-save='true') a.task-status(href='', title="{{'TASK.TITLE_SELECT_STATUS' | translate}}") span.task-status-bind - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") .assigned-to(tg-related-task-assigned-to-inline-edition='newTask', not-auto-save='true') .task-assignedto(title="{{'COMMON.FIELDS.ASSIGNED_TO' | translate}}") figure.avatar - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") diff --git a/app/partials/task/related-task-row-edit.jade b/app/partials/task/related-task-row-edit.jade index 93f32d63..0eee394a 100644 --- a/app/partials/task/related-task-row-edit.jade +++ b/app/partials/task/related-task-row-edit.jade @@ -1,20 +1,27 @@ -.tasks - .task-name - input(type='text', value!='<%- task.subject %>', placeholder="{{'TASK.PLACEHOLDER_SUBJECT' | translate}}") - .task-settings - svg.icon.icon-save.save-task(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.icon.icon-close.cancel-edit(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") +.task-name + input( + type='text' + value!='<%- task.subject %>' + placeholder="{{'TASK.PLACEHOLDER_SUBJECT' | translate}}" + ) +.task-settings + a.save-task( + href="" + title="{{'COMMON.SAVE' | translate}}" + ) + tg-svg(svg-icon="icon-save") + a.cancel-edit( + href="" + title="{{'COMMON.CANCEL' | translate}}" + ) + tg-svg(svg-icon="icon-cancel") .status(tg-related-task-status='task', ng-model='task') a.task-status(href='', title="{{'TASK.TITLE_SELECT_STATUS' | translate}}") span.task-status-bind - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") .assigned-to(tg-related-task-assigned-to-inline-edition='task') .task-assignedto(title="{{'COMMON.FIELDS.ASSIGNED_TO' | translate}}") figure.avatar - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") diff --git a/app/partials/task/related-task-row.jade b/app/partials/task/related-task-row.jade index 446b2017..e51deda1 100644 --- a/app/partials/task/related-task-row.jade +++ b/app/partials/task/related-task-row.jade @@ -1,51 +1,47 @@ -.tasks - .task-name - a.clickable( - tg-nav="project-tasks-detail:project=project.slug,ref=task.ref" - title!="#<%- task.ref %> <%- task.subject %>") - svg.icon.icon-iocaine - use(xlink:href="#icon-iocaine") - span #<%- task.ref %> - span <%- task.subject %> - .task-settings - <% if(perms.modify_task) { %> - svg.icon.icon-edit.edit-task( - href="" - title="{{'COMMON.EDIT' | translate}}" - ) - use(xlink:href="#icon-edit") - <% } %> - <% if(perms.delete_task) { %> - svg.icon.icon-trash.delete-task( - title="{{'COMMON.DELETE' | translate}}" - ) - use(xlink:href="#icon-trash") - <% } %> +.task-name + a.clickable( + tg-nav="project-tasks-detail:project=project.slug,ref=task.ref" + title!="#<%- task.ref %> <%- task.subject %>") + span #<%- task.ref %> + span <%- task.subject %> +.task-settings + <% if(perms.modify_task) { %> + a.edit-task( + href="" + title="{{'COMMON.EDIT' | translate}}" + ) + tg-svg(svg-icon="icon-edit") + <% } %> + <% if(perms.delete_task) { %> + a.delete-task( + title="{{'COMMON.DELETE' | translate}}" + href="" + ) + tg-svg(svg-icon="icon-trash") + <% } %> .status( tg-related-task-status="task" ng-model="task" ) a.task-status( - href="" + href="" title="{{'TASK.TITLE_SELECT_STATUS' | translate}}" ng-style="{'color': task.status_extra_info.color}" ) span.task-status-bind <% if(perms.modify_task) { %> - svg.icon.icon-arrow-down(ng-style="{'fill': task.status_extra_info.color}") - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down", ng-style="{'fill': task.status_extra_info.color}") <% } %> .assigned-to( tg-related-task-assigned-to-inline-edition="task" ) .task-assignedto( - title="{{'COMMON.FIELDS.ASSIGNED_TO' | translate}}" + title="{{'COMMON.FIELDS.ASSIGNED_TO' | translate}}" class="<% if(perms.modify_task) { %>editable<% } %>" ) figure.avatar <% if(perms.modify_task) { %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% } %> diff --git a/app/partials/task/task-detail.jade b/app/partials/task/task-detail.jade index e4060314..a0d00f8d 100644 --- a/app/partials/task/task-detail.jade +++ b/app/partials/task/task-detail.jade @@ -67,15 +67,13 @@ div.wrapper( tg-bo-href="previousUrl" title="{{'TASK.PREVIOUS' | translate}}" ) - svg.icon.icon-arrow-left - use(xlink:href='#icon-arrow-left') + tg-svg(svg-icon="icon-arrow-left") a( ng-show="nextUrl" tg-bo-href="nextUrl" title="{{'TASK.NEXT' | translate}}" ) - svg.icon.icon-arrow-right - use(xlink:href='#icon-arrow-right') + tg-svg(svg-icon="icon-arrow-right") .subheader div.tags-block(tg-tag-line, ng-model="task", required-perm="modify_task") tg-created-by-display.ticket-created-by(ng-model="task") diff --git a/app/partials/team/leave-project.jade b/app/partials/team/leave-project.jade index 04fa75c4..44853967 100644 --- a/app/partials/team/leave-project.jade +++ b/app/partials/team/leave-project.jade @@ -2,6 +2,5 @@ a.leave-project( ng-click="leave()" href="" ) - svg.icon.icon-close - use(xlink:href="#icon-close") + tg-svg(svg-icon="icon-close") span {{ 'TEAM.ACTION_LEAVE_PROJECT' | translate }} diff --git a/app/partials/team/team-filter.jade b/app/partials/team/team-filter.jade index 67ccfcd0..e9a76228 100644 --- a/app/partials/team/team-filter.jade +++ b/app/partials/team/team-filter.jade @@ -6,8 +6,7 @@ ul href="" ) span.title(translate="TEAM.SECTION_FILTER_ALL") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") li(ng-repeat="role in roles") a( @@ -16,5 +15,4 @@ ul href="" ) span.title(tg-bo-bind="role.name") - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") diff --git a/app/partials/team/team-member-current-user.jade b/app/partials/team/team-member-current-user.jade index 7275184f..caefc7e5 100644 --- a/app/partials/team/team-member-current-user.jade +++ b/app/partials/team/team-member-current-user.jade @@ -6,13 +6,19 @@ .avatar-data .name span(tg-bo-bind="currentUser.full_name_display") - svg.icon.icon-badge(ng-if="currentUser.id == owner") - use(xlink:href="#icon-badge") - title(translate="COMMON.OWNER") + tg-svg( + ng-if="currentUser.id == owner" + svg-icon="icon-badge" + svg-title-translate="COMMON.OWNER" + ) .position(tg-bo-bind="currentUser.role_name") - div(tg-leave-project="", project="project", user="currentUser") + div( + tg-leave-project="" + project="project" + user="currentUser" + ) .member-stats( tg-team-member-stats diff --git a/app/partials/team/team-member-stats.jade b/app/partials/team/team-member-stats.jade index 161683b0..575d9646 100644 --- a/app/partials/team/team-member-stats.jade +++ b/app/partials/team/team-member-stats.jade @@ -1,37 +1,37 @@ .attribute(ng-if="issuesEnabled") - svg.icon.icon-briefcase( - ng-style="{'opacity': stats.closed_bugs[userId]}" + tg-svg( + svg-icon="icon-briefcase", + ng-style="{'opacity': stats.closed_bugs[userId]}", ng-class="{'top': stats.closed_bugs[userId] == 1}" ) - use(xlink:href="#icon-briefcase") .attribute(ng-if="tasksEnabled") - svg.icon.icon-iocaine( - ng-style="{'opacity': stats.iocaine_tasks[userId]}" + tg-svg( + svg-icon="icon-iocaine", + ng-style="{'opacity': stats.iocaine_tasks[userId]}", ng-class="{'top': stats.iocaine_tasks[userId] == 1}" ) - use(xlink:href="#icon-iocaine") .attribute(ng-if="wikiEnabled") - svg.icon.icon-edit( - ng-style="{'opacity': stats.wiki_changes[userId]}" + tg-svg( + svg-icon="icon-edit", + ng-style="{'opacity': stats.wiki_changes[userId]}", ng-class="{'top': stats.wiki_changes[userId] == 1}" ) - use(xlink:href="#icon-edit") .attribute(ng-if="issuesEnabled") - svg.icon.icon-bug( - ng-style="{'opacity': stats.created_bugs[userId]}" + tg-svg( + svg-icon="icon-bug", + ng-style="{'opacity': stats.created_bugs[userId]}", ng-class="{'top': stats.created_bugs[userId] == 1}" ) - use(xlink:href="#icon-bug") .attribute(ng-if="tasksEnabled") - svg.icon.icon-task( - ng-style="{'opacity': stats.closed_tasks[userId]}" + tg-svg( + svg-icon="icon-task", + ng-style="{'opacity': stats.closed_tasks[userId]}", ng-class="{'top': stats.closed_tasks[userId] == 1}" ) - use(xlink:href="#icon-task") .attribute span.points(ng-bind="stats.totals[userId]") diff --git a/app/partials/team/team-members.jade b/app/partials/team/team-members.jade index 1c88dfde..795388bb 100644 --- a/app/partials/team/team-members.jade +++ b/app/partials/team/team-members.jade @@ -9,9 +9,8 @@ title="{{::user.full_name_display}}" ) {{::user.full_name_display}} svg.icon.icon-badge(ng-if="user.id == owner") - use(xlink:href="#icon-badge") - title(translate="COMMON.OWNER") - + tg-svg(svg-icon="icon-badge", svg-title-translate="COMMON.OWNER") + span.position {{::user.role_name}} .member-stats( diff --git a/app/partials/us/us-client-requirement-button.jade b/app/partials/us/us-client-requirement-button.jade index d9cb54a1..f0df30d6 100644 --- a/app/partials/us/us-client-requirement-button.jade +++ b/app/partials/us/us-client-requirement-button.jade @@ -3,8 +3,7 @@ label.button-gray.client-requirement( class!="<% if(canEdit){ %>is-editable<% }; %> <% if(isRequired){ %>active<% }; %>" title="{{ 'COMMON.CLIENT_REQUIREMENT' | translate }}" ) - svg.icon.icon-client-requirement - use(xlink:href="#icon-client-requirement") + tg-svg(svg-icon="icon-client-requirement") input( type="checkbox" id="client-requirement" diff --git a/app/partials/us/us-detail.jade b/app/partials/us/us-detail.jade index b6dcbcd0..193615e0 100644 --- a/app/partials/us/us-detail.jade +++ b/app/partials/us/us-detail.jade @@ -60,15 +60,13 @@ div.wrapper( tg-bo-href="previousUrl" title="{{'US.PREVIOUS' | translate}}" ) - svg.icon.icon-arrow-left - use(xlink:href="#icon-arrow-left") + tg-svg(svg-icon="icon-arrow-left") a( ng-show="nextUrl" tg-bo-href="nextUrl" title="{{'US.NEXT' | translate}}" ) - svg.icon.icon-arrow-right - use(xlink:href="#icon-arrow-right") + tg-svg(svg-icon="icon-arrow-right") .subheader .tags-block(tg-tag-line, ng-model="us", required-perm="modify_us") tg-created-by-display.ticket-created-by(ng-model="us") diff --git a/app/partials/us/us-status-button.jade b/app/partials/us/us-status-button.jade index 5066a9ab..7bcf995f 100644 --- a/app/partials/us/us-status-button.jade +++ b/app/partials/us/us-status-button.jade @@ -4,8 +4,7 @@ span.detail-status-inner.js-edit-status( ) span <%- status.name %> <% if(editable){ %> - svg.icon.icon-arrow-down - use(xlink:href="#icon-arrow-down") + tg-svg(svg-icon="icon-arrow-down") <% }%> ul.pop-status.popover diff --git a/app/partials/us/us-team-requirement-button.jade b/app/partials/us/us-team-requirement-button.jade index 9a4d186d..b32f1177 100644 --- a/app/partials/us/us-team-requirement-button.jade +++ b/app/partials/us/us-team-requirement-button.jade @@ -3,9 +3,7 @@ label.button-gray.team-requirement( class!=" <% if(canEdit){ %>is-editable<% }; %> <% if(isRequired){ %>active<% }; %>" title="{{ 'COMMON.TEAM_REQUIREMENT' | translate }}" ) - svg.icon.icon-team-requirement - use(xlink:href="#icon-team-requirement") - + tg-svg(svg-icon="icon-team-requirement") input( type="checkbox" id="team-requirement" diff --git a/app/partials/user/lightbox/lightbox-delete-account.jade b/app/partials/user/lightbox/lightbox-delete-account.jade index 087e25b3..4229ac26 100644 --- a/app/partials/user/lightbox/lightbox-delete-account.jade +++ b/app/partials/user/lightbox/lightbox-delete-account.jade @@ -1,6 +1,5 @@ -a.close(href="", title="{{'close' | translate}}") - svg.icon.icon-close - use(xlink:href="#icon-close") +tg-lightbox-close + form h2.title(translate="LIGHTBOX.DELETE_ACCOUNT.CONFIRM") diff --git a/app/partials/wiki/editable-wiki-content.jade b/app/partials/wiki/editable-wiki-content.jade index e5729ed0..4f27d874 100644 --- a/app/partials/wiki/editable-wiki-content.jade +++ b/app/partials/wiki/editable-wiki-content.jade @@ -2,19 +2,28 @@ include ../common/components/wysiwyg.jade .view-wiki-content section.wysiwyg(tg-bind-html='wiki.html') - svg.edit.icon.icon-edit( + a.edit( + href="" title="{{'COMMON.EDIT' | translate}}" - ng-if="wiki" ) - use(xlink:href="#icon-edit") + tg-svg(svg-icon="icon-edit") .edit-wiki-content(style='display: none;') - textarea(ng-attr-placeholder="{{'WIKI.PLACEHOLDER_PAGE' | translate}}", - ng-model='wiki.content', tg-markitup='tg-markitup') + textarea( + ng-attr-placeholder="{{'WIKI.PLACEHOLDER_PAGE' | translate}}", + ng-model='wiki.content' + tg-markitup='tg-markitup' + ) +wysihelp span.action-container - svg.save.icon.icon-save(title="{{'COMMON.SAVE' | translate}}") - use(xlink:href="#icon-save") - svg.cancel.icon.icon-close(title="{{'COMMON.CANCEL' | translate}}") - use(xlink:href="#icon-close") + a.save( + title="{{'COMMON.SAVE' | translate}}" + href="" + ) + tg-svg(svg-icon="icon-save") + a.cancel( + title="{{'COMMON.CANCEL' | translate}}" + href="" + ) + tg-svg(svg-icon="icon-close") diff --git a/app/partials/wiki/wiki-nav.jade b/app/partials/wiki/wiki-nav.jade index c26d5590..6d5c6f34 100644 --- a/app/partials/wiki/wiki-nav.jade +++ b/app/partials/wiki/wiki-nav.jade @@ -5,17 +5,27 @@ nav ul <% _.each(wikiLinks, function(link, index) { %> li.wiki-link(data-id!="<%- index %>") - a(title!="<%- link.title %>") - span.link-title <%- link.title %> - <% if (deleteWikiLinkPermission) { %> - svg.js-delete-link.icon.icon-trash - use(xlink:href="#icon-trash") - <% } %> - input(type="text" placeholder="{{'COMMON.FIELDS.NAME' | translate}}" class="hidden" value!="<%- link.title %>") + a.link-title(title!="<%- link.title %>") <%- link.title %> + <% if (deleteWikiLinkPermission) { %> + a.js-delete-link.remove-wiki-page(title!="{{'WIKI.DELETE_LINK_TITLE' | translate}}") + tg-svg(svg-icon="icon-trash") + <% } %> + input.hidden( + type="text" + placeholder="{{'COMMON.FIELDS.NAME' | translate}}" + value!="<%- link.title %>" + ) <% }) %> li.new.hidden - input(type="text" placeholder="{{'COMMON.FIELDS.NAME' | translate}}") + input( + type="text" + placeholder="{{'COMMON.FIELDS.NAME' | translate}}" + ) <% if (addWikiLinkPermission) { %> -a(href="" title="{{'WIKI.NAVIGATION.ACTION_ADD_LINK' | translate}}" class="add-button button-gray") +a( + href="" + title="{{'WIKI.NAVIGATION.ACTION_ADD_LINK' | translate}}" + class="add-button button-gray" +) span(translate="WIKI.NAVIGATION.ACTION_ADD_LINK") <% } %> diff --git a/app/partials/wiki/wiki.jade b/app/partials/wiki/wiki.jade index 1b30f29f..a7e59bd5 100644 --- a/app/partials/wiki/wiki.jade +++ b/app/partials/wiki/wiki.jade @@ -28,7 +28,12 @@ div.wrapper(ng-controller="WikiDetailController as ctrl", edit-permission = "modify_wiki_page" ) - a.remove(href="", ng-click="ctrl.delete()", ng-if="wiki.id", title="{{'WIKI.REMOVE' | translate}}", tg-check-permission="delete_wiki_page") - svg.icon.icon-trash - use(xlink:href="#icon-trash") + a.remove( + href="" + ng-click="ctrl.delete()" + ng-if="wiki.id" + title="{{'WIKI.REMOVE' | translate}}" + tg-check-permission="delete_wiki_page" + ) + tg-svg(svg-icon="icon-trash") span(translate="WIKI.REMOVE") diff --git a/app/styles/components/editor-help.scss b/app/styles/components/editor-help.scss index 5e77956a..038b2a18 100644 --- a/app/styles/components/editor-help.scss +++ b/app/styles/components/editor-help.scss @@ -4,6 +4,9 @@ justify-content: space-between; margin-top: -.5rem; padding: .25rem .5rem; + a { + display: inline-block; + } } .drag-drop-help { diff --git a/app/styles/components/filter.scss b/app/styles/components/filter.scss index 86994832..98d85f35 100644 --- a/app/styles/components/filter.scss +++ b/app/styles/components/filter.scss @@ -2,10 +2,13 @@ @extend %large; @extend %title; @include clearfix; - cursor: pointer; - display: block; + align-items: center; + background: darken($whitish, 10%); // Fallback + display: flex; + justify-content: space-between; margin-bottom: .5rem; opacity: .5; + padding-right: .5rem; position: relative; &:hover { color: $grayer; @@ -24,9 +27,7 @@ } .name { @include ellipsis(100%); - background: darken($whitish, 10%); // Fallback display: block; - padding-right: 2rem; width: 100%; } .number { @@ -36,13 +37,15 @@ top: 0; } .remove-filter { - fill: $gray; - position: absolute; - right: .5rem; - top: .75rem; - transition: fill .2s linear; + display: block; + svg { + fill: $gray; + transition: fill .2s linear; + } &:hover { - fill: $red; + svg { + fill: $red; + } } } } diff --git a/app/styles/components/kanban-task.scss b/app/styles/components/kanban-task.scss index 37406516..3a2c1f25 100644 --- a/app/styles/components/kanban-task.scss +++ b/app/styles/components/kanban-task.scss @@ -9,7 +9,7 @@ margin-bottom: 0; } &:hover { - .icon-edit { + .edit-us { display: block; fill: $card-dark; opacity: 1; @@ -95,15 +95,20 @@ bottom: .5rem; position: absolute; } - .icon-edit { - @include svg-size(1.1rem); - fill: $card-hover; + .edit-us { + display: block; opacity: 0; position: absolute; + svg { + @include svg-size(1.1rem); + fill: $card-hover; + } &:hover { cursor: pointer; - fill: darken($card-hover, 15%); - transition: color .3s linear; + svg { + fill: darken($card-hover, 15%); + transition: color .3s linear; + } } } } @@ -140,7 +145,7 @@ word-wrap: break-word; } .loading, - .icon-edit { + .edit-us { bottom: .2rem; right: .5rem; } diff --git a/app/styles/components/list-items.scss b/app/styles/components/list-items.scss index 12ebdb93..ed1c2e96 100644 --- a/app/styles/components/list-items.scss +++ b/app/styles/components/list-items.scss @@ -92,6 +92,7 @@ .ticket-project, .ticket-type, .ticket-status, + .ticket-id, .list-itemtype-avatar, .list-itemtype-track, .ticket-title { @@ -99,6 +100,7 @@ } .icon-blocked-project { @include svg-size(); + margin-left: .25rem; } } h2 { diff --git a/app/styles/components/looking-for-people.scss b/app/styles/components/looking-for-people.scss new file mode 100644 index 00000000..9e34a75a --- /dev/null +++ b/app/styles/components/looking-for-people.scss @@ -0,0 +1,5 @@ +.look-for-people { + @include svg-size(); + fill: $gray-light; + margin-left: .25rem; +} diff --git a/app/styles/components/markitup.scss b/app/styles/components/markitup.scss index dd121e40..93beffec 100644 --- a/app/styles/components/markitup.scss +++ b/app/styles/components/markitup.scss @@ -15,7 +15,7 @@ } .preview-icon { position: absolute; - right: 2.5rem; + right: 4rem; } } } diff --git a/app/styles/components/notification-message.scss b/app/styles/components/notification-message.scss index 33585da6..70e39a09 100644 --- a/app/styles/components/notification-message.scss +++ b/app/styles/components/notification-message.scss @@ -90,13 +90,16 @@ margin: 0; } } - .icon-close { - cursor: pointer; - fill: $white; + .close { + display: block; position: absolute; right: 1rem; top: 1rem; } + .icon-close { + cursor: pointer; + fill: $white; + } } .notification-message { @@ -141,6 +144,7 @@ line-height: 1.5rem; } .close { + display: block; margin-right: 1rem; width: 2rem; svg { diff --git a/app/styles/components/private.scss b/app/styles/components/private.scss index 8a40e013..f89e0620 100644 --- a/app/styles/components/private.scss +++ b/app/styles/components/private.scss @@ -1,4 +1,4 @@ -.private { +.icon-lock { fill: $gray-light; margin-left: .5rem; } diff --git a/app/styles/components/summary.scss b/app/styles/components/summary.scss index 28d6aaa5..47a2d596 100644 --- a/app/styles/components/summary.scss +++ b/app/styles/components/summary.scss @@ -32,6 +32,7 @@ $summary-background: $grayer; } .stats { cursor: pointer; + display: block; height: 2rem; margin-left: auto; width: 2rem; diff --git a/app/styles/components/tag.scss b/app/styles/components/tag.scss index 2e0254ac..80130150 100644 --- a/app/styles/components/tag.scss +++ b/app/styles/components/tag.scss @@ -42,11 +42,14 @@ padding: .4rem; width: 14rem; } + .save { + cursor: pointer; + display: inline-block; + margin-left: .5rem; + } .icon-save { @include svg-size(); - cursor: pointer; fill: $grayer; - margin-left: .5rem; &:hover { fill: $primary; transition: .2s linear; @@ -68,6 +71,7 @@ } .add-tag { color: $gray-light; + display: inline-block; &:hover { color: $primary-light; } @@ -78,4 +82,7 @@ .add-tag-text { @extend %small; } + .remove-tag { + display: inline-block; + } } diff --git a/app/styles/components/taskboard-task.scss b/app/styles/components/taskboard-task.scss index 7fa2daa4..4e3742e6 100644 --- a/app/styles/components/taskboard-task.scss +++ b/app/styles/components/taskboard-task.scss @@ -75,6 +75,9 @@ } } .iocaine { + left: .2rem; + position: absolute; + top: 1rem; img { filter: hue-rotate(150deg) saturate(200%); } @@ -84,10 +87,7 @@ border-radius: 5px; fill: $white; height: 1.75rem; - left: .2rem; padding: .25rem; - position: absolute; - top: 1rem; width: 1.75rem; } .task-assigned { @@ -119,13 +119,16 @@ bottom: .5rem; position: absolute; } + .edit-task { + bottom: .5rem; + position: absolute; + top: auto; + } .icon-edit { @include svg-size(1.1rem); - bottom: .5rem; cursor: pointer; fill: $card-hover; opacity: 0; - position: absolute; &:hover { fill: $card-dark; } diff --git a/app/styles/components/user-list.scss b/app/styles/components/user-list.scss index e39f8016..9105554f 100644 --- a/app/styles/components/user-list.scss +++ b/app/styles/components/user-list.scss @@ -49,6 +49,7 @@ transition-delay: .1s; } .remove-assigned-to { + display: block; fill: $grayer; opacity: 1; position: absolute; diff --git a/app/styles/core/animation.scss b/app/styles/core/animation.scss index 74d4cd56..79352045 100644 --- a/app/styles/core/animation.scss +++ b/app/styles/core/animation.scss @@ -45,20 +45,6 @@ } } -// Drop Down element animations -@keyframes dropdownFade { - 0% { - opacity: 0; - transform: translateY(-.25rem); - } - 60% { - opacity: 1; - } - 100% { - transform: translateY(0); - } -} - // Drop Down element animations @keyframes dropdownFade { diff --git a/app/styles/core/forms.scss b/app/styles/core/forms.scss index ebd15ecd..b1a03811 100644 --- a/app/styles/core/forms.scss +++ b/app/styles/core/forms.scss @@ -40,12 +40,20 @@ textarea { padding: .2rem; } } -.icon-capslock { - bottom: .8rem; - display: none; - fill: $gray; - height: .9rem; - position: absolute; - right: 1rem; - width: .9rem; +.capslock { + &.ng-enter { + animation: dropdownFade .2s ease-in; + } + &.ng-leave { + animation: dropdownFade .2s ease-in; + animation-direction: reverse; + } + .icon-capslock { + bottom: .8rem; + fill: $gray; + height: .9rem; + position: absolute; + right: 1rem; + width: .9rem; + } } diff --git a/app/styles/dependencies/helpers.scss b/app/styles/dependencies/helpers.scss index f9080da8..9125f084 100644 --- a/app/styles/dependencies/helpers.scss +++ b/app/styles/dependencies/helpers.scss @@ -27,16 +27,19 @@ .close { @include svg-size(2rem); cursor: pointer; + display: block; fill: $gray; position: absolute; right: 3rem; top: 3rem; transition: fill .2s; + display: block; &:hover { fill: $red-light; } svg { @include svg-size(2rem); + pointer-events: none; } } &.open { diff --git a/app/styles/dependencies/mixins.scss b/app/styles/dependencies/mixins.scss index 746cc5d6..f50d41bc 100644 --- a/app/styles/dependencies/mixins.scss +++ b/app/styles/dependencies/mixins.scss @@ -139,7 +139,6 @@ } } .icon { - @include svg-size(.75rem); fill: $gray-light; } } diff --git a/app/styles/dependencies/mixins/project-card.scss b/app/styles/dependencies/mixins/project-card.scss index efd82701..20a11202 100644 --- a/app/styles/dependencies/mixins/project-card.scss +++ b/app/styles/dependencies/mixins/project-card.scss @@ -71,9 +71,4 @@ } } } - .look-for-people { - @include svg-size(1rem); - fill: $gray-light; - margin: 0 .5rem; - } } diff --git a/app/styles/layout/ticket-detail.scss b/app/styles/layout/ticket-detail.scss index c2289163..38dadffc 100644 --- a/app/styles/layout/ticket-detail.scss +++ b/app/styles/layout/ticket-detail.scss @@ -66,6 +66,9 @@ } .save-container { flex-grow: 1; + .save { + display: block; + } } .us-title-text { @extend %larger; @@ -99,11 +102,13 @@ padding-right: 1rem; width: 100%; } - .edit, - .save { + .save, + .edit { cursor: pointer; - fill: $gray-light; margin-left: .5rem; + svg { + fill: $gray-light; + } } .edit { opacity: 0; @@ -167,6 +172,9 @@ position: absolute; right: 1rem; top: 1rem; + a { + display: inline-block; + } svg { @include svg-size(1.2rem); fill: currentColor; @@ -262,10 +270,12 @@ margin-bottom: 2rem; .save { cursor: pointer; + display: inline-block; position: relative; top: .3rem; } .edit { + display: inline-block; position: absolute; right: 2.5rem; top: .4rem; diff --git a/app/styles/layout/wiki.scss b/app/styles/layout/wiki.scss index dbec51e2..cc15bd3e 100644 --- a/app/styles/layout/wiki.scss +++ b/app/styles/layout/wiki.scss @@ -55,31 +55,39 @@ cursor: pointer; } } - .edit-wiki-content { - .icon { - &:hover { - cursor: pointer; + .preview { + padding-top: 1.8rem; + } +} + +.edit-wiki-content { + a { + display: inline-block; + margin-right: .5rem; + &:last-child { + margin: 0; + } + &:hover { + cursor: pointer; + .icon { fill: $primary-dark; opacity: .3; transition: all .2s linear; } } - .preview-icon { - position: absolute; - right: 3.5rem; - } - .action-container { - position: absolute; - right: 1rem; - top: .3rem; - } - .edit { - position: absolute; - right: 3.5rem; - top: .4rem; - } } - .preview { - padding-top: 1.8rem; + .preview-icon { + position: absolute; + right: 3.5rem; + } + .action-container { + position: absolute; + right: 1rem; + top: .3rem; + } + .edit { + position: absolute; + right: 3.5rem; + top: .4rem; } } diff --git a/app/styles/modules/admin/admin-custom-attributes.scss b/app/styles/modules/admin/admin-custom-attributes.scss index ef5a1767..73c45584 100644 --- a/app/styles/modules/admin/admin-custom-attributes.scss +++ b/app/styles/modules/admin/admin-custom-attributes.scss @@ -12,17 +12,12 @@ .table-header { @extend %bold; border-bottom: 3px solid $whitish; - .custom-name span, - .custom-description span { + .custom-name, + .custom-description { padding-left: 1.1rem; } } .table-body { - form:last-child { - .row { - border: 0; - } - } .row:hover { background: rgba($primary-light, .05); cursor: move; @@ -50,18 +45,11 @@ .icon-drag { fill: $gray-light; opacity: 0; - padding: 0 .1rem; + padding: 0 .25rem 0 .1rem; transition: color .2s linear; - vertical-align: middle; - &:hover { - cursor: move; - fill: $gray; - transition: color .2s linear; - } } .custom-name, .custom-description { - color: $gray; margin-right: .5rem; } .custom-name { @@ -74,8 +62,9 @@ flex-grow: 8; } .custom-field-type { - flex-basis: 25%; + flex-basis: 10%; flex-grow: 0; + flex-shrink: 0; } .custom-options { flex-basis: 100px; @@ -102,6 +91,9 @@ .custom-options-wrapper { opacity: 0; transition: opacity .3s linear; + a { + display: inline-block; + } } form { .custom-options-wrapper { diff --git a/app/styles/modules/admin/admin-functionalities.scss b/app/styles/modules/admin/admin-functionalities.scss index cc29e8e6..39e1b53c 100644 --- a/app/styles/modules/admin/admin-functionalities.scss +++ b/app/styles/modules/admin/admin-functionalities.scss @@ -48,14 +48,16 @@ align-items: flex-start; display: flex; margin-top: .5rem; + .options { + align-items: center; + display: flex; + height: 2.5rem; + } fieldset, .icon { margin: 0 .5rem; } .icon { - @include svg-size(2.5rem); - align-self: center; - cursor: pointer; fill: $gray-light; &:hover { fill: $primary; @@ -63,12 +65,12 @@ } } .module-scrum { - .icon { + .options { align-self: flex-end; } } .module-videoconference { - .icon { + .options { align-self: flex-start; } } diff --git a/app/styles/modules/admin/admin-roles.scss b/app/styles/modules/admin/admin-roles.scss index cd817290..5507d1b0 100644 --- a/app/styles/modules/admin/admin-roles.scss +++ b/app/styles/modules/admin/admin-roles.scss @@ -1,4 +1,7 @@ .admin-roles { + .save { + display: inline-block; + } .role-name { @extend %xlarge; @extend %light; diff --git a/app/styles/modules/admin/admin-third-parties-webhooks.scss b/app/styles/modules/admin/admin-third-parties-webhooks.scss index 825314eb..7b280b39 100644 --- a/app/styles/modules/admin/admin-third-parties-webhooks.scss +++ b/app/styles/modules/admin/admin-third-parties-webhooks.scss @@ -25,11 +25,6 @@ .single-webhook-wrapper { border-bottom: 1px solid $whitish; } - .webhooks-options { - margin-bottom: 1rem; - text-align: right; - } - .webhook-service, .webhook-url { margin-right: .5rem; @@ -58,9 +53,9 @@ .webhook-options { flex-basis: 100px; flex-grow: 0; - min-width: 100px; - text-align: center; + flex-shrink: 0; a { + display: inline-block; margin-right: .5rem; } svg { diff --git a/app/styles/modules/admin/project-values.scss b/app/styles/modules/admin/project-values.scss index d55a0516..e1ce865a 100644 --- a/app/styles/modules/admin/project-values.scss +++ b/app/styles/modules/admin/project-values.scss @@ -61,8 +61,11 @@ } .project-values-settings { - svg { + a { + display: inline-block; margin-right: .5rem; + } + svg { &.icon-trash { fill: $red-light; } diff --git a/app/styles/modules/backlog/backlog-table.scss b/app/styles/modules/backlog/backlog-table.scss index 934d5b64..b3425e3f 100644 --- a/app/styles/modules/backlog/backlog-table.scss +++ b/app/styles/modules/backlog/backlog-table.scss @@ -281,6 +281,11 @@ cursor: auto; padding-right: 45px; } + .us-status { + tg-svg { + display: inline-block; + } + } } .empty-backlog { diff --git a/app/styles/modules/backlog/sprints.scss b/app/styles/modules/backlog/sprints.scss index e2d11194..fcc7a9c4 100644 --- a/app/styles/modules/backlog/sprints.scss +++ b/app/styles/modules/backlog/sprints.scss @@ -58,23 +58,23 @@ header { position: relative; } - &:hover { - .icon-edit { + .edit-sprint { opacity: 1; transition: opacity .2s ease-in; } } .edit-sprint { - fill: $gray-light; opacity: 0; position: absolute; right: 0; top: 0; transition: opacity .2s ease-in; vertical-align: baseline; + } + svg { + fill: $gray-light; &:hover { - cursor: pointer; fill: $primary; transition: fill .2s ease-in; } diff --git a/app/styles/modules/backlog/taskboard-table.scss b/app/styles/modules/backlog/taskboard-table.scss index cd99e5a4..dab4947f 100644 --- a/app/styles/modules/backlog/taskboard-table.scss +++ b/app/styles/modules/backlog/taskboard-table.scss @@ -87,21 +87,6 @@ $column-margin: 0 10px 0 0; &:last-child { margin-right: 0; } - .icon { - @extend %medium; - fill: $gray-light; - margin-right: .3rem; - transition: fill .2s linear; - &:hover { - cursor: pointer; - fill: $primary; - } - &.hfold, - &.hunfold { - display: inline-block; - transform: rotate(90deg); - } - } &.column-fold { align-items: center; justify-content: center; @@ -115,6 +100,28 @@ $column-margin: 0 10px 0 0; } } } + tg-svg { + display: block; + margin-right: .3rem; + svg { + @extend %medium; + fill: $gray-light; + transition: fill .2s linear; + } + &:hover { + cursor: pointer; + svg { + fill: $primary; + } + } + &.hfold, + &.hunfold { + display: inline-block; + svg { + transform: rotate(90deg); + } + } + } } .taskboard-table-body { @@ -184,26 +191,6 @@ $column-margin: 0 10px 0 0; .taskboard-userstory-box { padding: .5rem .5rem .5rem 1.5rem; - .icon { - cursor: pointer; - fill: $gray-light; - position: absolute; - right: .5rem; - top: .7rem; - transition: fill .2s linear; - &:hover { - fill: $primary; - } - &.icon-add { - right: 2rem; - } - &.icon-fold-row, - &.icon-unfold-row { - left: 0; - right: inherit; - top: 1rem; - } - } } .avatar-task-link { display: none; @@ -211,6 +198,29 @@ $column-margin: 0 10px 0 0; .avatar-assigned-to { display: block; } + .icon { + transition: fill .2s linear; + } + tg-svg { + cursor: pointer; + display: block; + position: absolute; + right: .5rem; + top: .7rem; + &:hover { + svg { + fill: $primary; + } + } + &.add-action { + right: 2rem; + } + &.fold-action { + left: 0; + right: inherit; + top: 1rem; + } + } } .taskboard-userstory-box { diff --git a/app/styles/modules/common/colors-table.scss b/app/styles/modules/common/colors-table.scss index fa1f15bb..920a1bf4 100644 --- a/app/styles/modules/common/colors-table.scss +++ b/app/styles/modules/common/colors-table.scss @@ -24,6 +24,11 @@ transition: opacity .3s linear; } } + .options-column { + a { + display: inline-block; + } + } } form { &:last-child { @@ -136,5 +141,4 @@ } } } - } diff --git a/app/styles/modules/common/custom-fields.scss b/app/styles/modules/common/custom-fields.scss index 4adab4e5..4d5d6413 100644 --- a/app/styles/modules/common/custom-fields.scss +++ b/app/styles/modules/common/custom-fields.scss @@ -11,6 +11,9 @@ .icon { cursor: pointer; } + .collapse { + display: block; + } } .custom-fields-body { @include slide(1000px, hidden, $min: 0); @@ -35,8 +38,10 @@ margin: 0; opacity: 0; transition: opacity .2s linear; + a { + display: inline-block; + } svg { - cursor: pointer; fill: $gray-light; &:hover { fill: $primary; diff --git a/app/styles/modules/common/history.scss b/app/styles/modules/common/history.scss index 9cb43032..08495746 100644 --- a/app/styles/modules/common/history.scss +++ b/app/styles/modules/common/history.scss @@ -214,6 +214,7 @@ .comment-restore { @extend %small; color: $gray-light; + display: block; position: absolute; right: 0; top: .4rem; @@ -264,15 +265,20 @@ } .comment-delete { cursor: pointer; - fill: $red-light; + display: block; opacity: 0; position: absolute; right: .5rem; top: 2rem; - transition: all .2s linear; + svg { + fill: $red-light; + transition: all .2s linear; + } &:hover { - fill: $red; - transition: color .2s linear; + svg { + fill: $red; + transition: color .2s linear; + } } } &.activity { diff --git a/app/styles/modules/common/related-tasks.scss b/app/styles/modules/common/related-tasks.scss index 268fd5e3..6aa197ea 100644 --- a/app/styles/modules/common/related-tasks.scss +++ b/app/styles/modules/common/related-tasks.scss @@ -38,32 +38,26 @@ width: 100%; .row { @extend %small; - align-content: center; align-items: center; border-bottom: 1px solid $whitish; display: flex; - justify-content: center; padding: .5rem 0 .5rem .5rem; - position: relative; - text-align: left; - width: 100%; &:hover { - background: transparent; .task-settings { opacity: 1; transition: all .2s ease-in; } } - &:last-child { - border: 0; + .task-name { + flex: 1; } - .tasks { - overflow: hidden; - width: 100%; + .task-settings { + flex-shrink: 0; + width: 60px; } .status { flex-shrink: 0; - width: 100px; + width: 125px; } .assigned-to { cursor: pointer; @@ -77,60 +71,14 @@ padding: .5rem 0 .5rem .5rem; } } - .status { - position: relative; - text-align: left; - &:hover { - .icon { - opacity: 1; - transition: opacity .2s ease-in; - } - } - .not-clickable { - &:hover { - color: $grayer; - } - } - .popover { - a { - text-align: left; - width: 100%; - } - .point { - text-align: center; - } - } - .icon { - @include svg-size(.8rem); - fill: $gray-light; - margin-left: .2rem; - opacity: 0; - } - } - .pop-status { - @include popover(200px, 0, 40%); - padding-right: 1rem; - &.fix { - bottom: 0; - top: auto; - } + + .iocaine { + background: rgba($primary-light, .1); + border-left: 10px solid $primary-light; } .task-name { display: flex; - justify-content: space-between; - position: relative; - a { - display: inline-block; - max-width: 90%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - svg, - span { - margin-right: .25rem; - } - } - svg, + margin-right: 1rem; span { margin-right: .25rem; } @@ -150,38 +98,25 @@ } } } - .iocaine, - .iocaine:hover { - background: rgba($primary-light, .3); - .icon-iocaine { - @extend %large; - display: inline-block; - margin-right: .5rem; - vertical-align: top; - } - a, - svg { - color: $primary-dark; - fill: $primary-dark; + .status { + position: relative; + .not-clickable { &:hover { - color: currentColor; - fill: currentColor; + color: $grayer; } } - } - .blocked, - .blocked:hover { - background: $red-light; - color: $white; - a, - svg { - color: $white; - fill: $white; - &:hover { - color: currentColor; - fill: currentColor; + .popover { + left: 0; + top: 1rem; + a { + display: block; } } + .icon { + @include svg-size(.8rem); + fill: currentColor; + margin-left: .2rem; + } } .closed, .closed:hover { @@ -200,6 +135,19 @@ .icon-iocaine { display: none; } + .pop-status { + @include popover(200px, 0, 40%); + padding-right: 1rem; + &.fix { + bottom: 0; + top: auto; + } + } + .blocked, + .blocked:hover { + background: rgba($red-light, .2); + border-left: 10px solid $red-light; + } .task-settings { align-items: center; display: flex; @@ -207,20 +155,32 @@ svg { @include svg-size(1.1rem); fill: $gray-light; - margin-right: 2rem; + margin-right: .5rem; transition: fill .2s ease-in; &:hover { - cursor: pointer; - fill: $grayer; + fill: $gray; } - &.icon-close:hover { - fill: $red-light; + } + a { + &:hover { + cursor: pointer; } } } - .assigned-to { - position: relative; - text-align: left; + .edit-task, + .save-task, + .delete-task { + &:hover { + .icon-edit { + fill: $grayer; + } + .icon-save { + fill: $primary; + } + .icon-trash { + fill: $red-light; + } + } } .task-assignedto { position: relative; diff --git a/app/styles/modules/common/ticket-data.scss b/app/styles/modules/common/ticket-data.scss index b5723c38..a69f36ca 100644 --- a/app/styles/modules/common/ticket-data.scss +++ b/app/styles/modules/common/ticket-data.scss @@ -222,4 +222,7 @@ max-width: 1.25rem; width: 100%; } + a { + display: block; + } } diff --git a/app/styles/modules/common/wizard.scss b/app/styles/modules/common/wizard.scss index 81a1b6c0..7c12627d 100644 --- a/app/styles/modules/common/wizard.scss +++ b/app/styles/modules/common/wizard.scss @@ -59,7 +59,7 @@ transition: background .2s ease-in; } .icon { - @include svg-size(1.4rem); + @include svg-size(1.5rem); fill: currentColor; margin-right: 1rem; vertical-align: text-top; diff --git a/app/styles/modules/filters/filters.scss b/app/styles/modules/filters/filters.scss index e1309796..53fc5ab2 100644 --- a/app/styles/modules/filters/filters.scss +++ b/app/styles/modules/filters/filters.scss @@ -27,8 +27,7 @@ color: $gray-light; } } - .icon-search { - color: $gray-light; + .search-action { position: absolute; right: .7rem; top: .7rem; @@ -71,6 +70,12 @@ } } +.filter-list { + .single-filter { + cursor: pointer; + } +} + .filters-cats { margin-top: 2rem; li { diff --git a/app/styles/modules/issues/issues-table.scss b/app/styles/modules/issues/issues-table.scss index 9b03dc47..fadd1ed3 100644 --- a/app/styles/modules/issues/issues-table.scss +++ b/app/styles/modules/issues/issues-table.scss @@ -153,6 +153,9 @@ display: none; } } + .issue-status { + display: inline-block; + } } .empty-issues { diff --git a/app/styles/modules/kanban/kanban-table.scss b/app/styles/modules/kanban/kanban-table.scss index 5de4736d..d7492a9b 100644 --- a/app/styles/modules/kanban/kanban-table.scss +++ b/app/styles/modules/kanban/kanban-table.scss @@ -15,7 +15,6 @@ $column-margin: 0 10px 0 0; .vfold { &.task-colum-name { align-items: center; - cursor: pointer; display: flex; justify-content: center; opacity: .8; diff --git a/app/styles/modules/wiki/wiki-nav.scss b/app/styles/modules/wiki/wiki-nav.scss index f1f72c76..0c761b37 100644 --- a/app/styles/modules/wiki/wiki-nav.scss +++ b/app/styles/modules/wiki/wiki-nav.scss @@ -1,48 +1,39 @@ -.wiki-nav { - li { - @extend %large; - @extend %title; - border-bottom: 1px solid $gray-light; - text-transform: uppercase; +.wiki-link { + @extend %large; + @extend %title; + align-items: center; + border-bottom: 1px solid $gray-light; + display: flex; + justify-content: space-between; + padding: 1rem 0 1rem 1rem; + text-transform: uppercase; + &:hover { + .remove-wiki-page { + cursor: pointer; + opacity: 1; + transition: opacity .2s linear; + transition-delay: .2s; + } + } + .remove-wiki-page { + opacity: 0; &:hover { .icon { - opacity: 1; - transition: opacity .2s linear; - transition-delay: .2s; - } - } - a { - align-items: center; - display: flex; - justify-content: space-between; - padding: 1rem 0 1rem 1rem; - span { - cursor: pointer; - } - } - .icon { - fill: $gray-light; - opacity: 0; - &:hover { - cursor: pointer; fill: $red; } } - input { - @extend %text; - @extend %medium; - background: $grayer; - color: $whitish; - @include placeholder { - color: $gray-light; - } - } - .loading { - margin: 0; - padding: 8px; - text-align: center; - width: 100%; - } + } + .link-title { + cursor: pointer; + } + .icon-trash { + fill: $gray-light; + } +} + +.wiki-nav { + ul { + border-top: 1px solid $gray-light; } .add-button { color: $white; @@ -50,4 +41,19 @@ margin-bottom: .5rem; text-align: center; } + input[type="text"] { + @extend %text; + @extend %medium; + background: $grayer; + color: $whitish; + @include placeholder { + color: $gray-light; + } + } + .loading { + margin: 0; + padding: 8px; + text-align: center; + width: 100%; + } } diff --git a/app/styles/shame/shame.scss b/app/styles/shame/shame.scss index 152b9fa4..442e4a43 100644 --- a/app/styles/shame/shame.scss +++ b/app/styles/shame/shame.scss @@ -14,3 +14,15 @@ _:-ms-fullscreen, line-height: 1.5; font-family: monospace; } + +// Prevent IE Bug when the user clicks in the svg path the js event click doesn't work + +svg { + pointer-events: none; +} + +// Avoid previous selector to remove event on child SVG click. + +a[ng-click] svg { + pointer-events: auto; +} diff --git a/conf.e2e.js b/conf.e2e.js index b6b82dee..0a08bc0b 100644 --- a/conf.e2e.js +++ b/conf.e2e.js @@ -18,13 +18,13 @@ exports.config = { } }, mochaOpts: { - timeout: 45000, + timeout: 55000, compilers: 'js:babel-register', require: 'babel-polyfill' }, - // capabilities: { - // 'browserName': 'firefox' - // }, + capabilities: { + 'browserName': 'firefox' + }, // capabilities: { // browserName: 'internet explorer', // version: '11' @@ -47,59 +47,65 @@ exports.config = { discover: "e2e/suites/discover/*.e2e.js" }, onPrepare: function() { + // disable by default because performance problems on IE // track mouse movements - var trackMouse = function() { - angular.module('trackMouse', []).run(function($document) { + // var trackMouse = function() { + // angular.module('trackMouse', []).run(function($document) { - function addDot(ev) { - var color = 'black', - size = 6; + // function addDot(ev) { + // var color = 'black', + // size = 6; - switch (ev.type) { - case 'click': - color = 'red'; - break; - case 'dblclick': - color = 'blue'; - break; - case 'mousemove': - color = 'green'; - break; - } + // switch (ev.type) { + // case 'click': + // color = 'red'; + // break; + // case 'dblclick': + // color = 'blue'; + // break; + // case 'mousemove': + // color = 'green'; + // break; + // } - var dotEl = $('
') - .css({ - position: 'fixed', - height: size + 'px', - width: size + 'px', - 'background-color': color, - top: ev.clientY, - left: ev.clientX, + // var dotEl = $('
') + // .css({ + // position: 'fixed', + // height: size + 'px', + // width: size + 'px', + // 'background-color': color, + // top: ev.clientY, + // left: ev.clientX, - 'z-index': 9999, + // 'z-index': 9999, - // make sure this dot won't interfere with the mouse events of other elements - 'pointer-events': 'none' - }) - .appendTo('body'); + // // make sure this dot won't interfere with the mouse events of other elements + // 'pointer-events': 'none' + // }) + // .appendTo('body'); - setTimeout(function() { - dotEl.remove(); - }, 1000); - } + // setTimeout(function() { + // dotEl.remove(); + // }, 1000); + // } - $document.on({ - click: addDot, - dblclick: addDot, - mousemove: addDot - }); + // $document.on({ + // click: addDot, + // dblclick: addDot, + // mousemove: addDot + // }); - }); - }; - browser.addMockModule('trackMouse', trackMouse); + // }); + // }; + // browser.addMockModule('trackMouse', trackMouse); require('./e2e/capabilities.js'); + browser.get(browser.params.glob.host); + + browser.executeScript('window.sessionStorage.clear();'); + browser.executeScript('window.localStorage.clear();'); + browser.driver.manage().window().maximize(); browser.get(browser.params.glob.host + 'login'); diff --git a/e2e/helpers/admin-memberships.js b/e2e/helpers/admin-memberships.js index bcef88a6..89cdb4d5 100644 --- a/e2e/helpers/admin-memberships.js +++ b/e2e/helpers/admin-memberships.js @@ -22,10 +22,10 @@ helper.getNewMemberLightbox = function() { el.$('.add-fieldset').click(); }, getRows: function() { - return el.$$('.add-member-wrapper'); + return el.$$('.add-single-member'); }, deleteRow: function(index) { - el.$$('.delete-fieldset').get(index).click(); + el.$$('.remove-fieldset').get(index).click(); }, submit: function() { el.$('.submit-button').click(); diff --git a/e2e/helpers/issues-helper.js b/e2e/helpers/issues-helper.js index ec081fc6..2308fa26 100644 --- a/e2e/helpers/issues-helper.js +++ b/e2e/helpers/issues-helper.js @@ -100,7 +100,7 @@ helper.filtersCats = function() { }; helper.filtersList = function() { - return $$('.filter-list a'); + return $$('.filter-list .single-filter'); }; helper.selectFilter = async function(index) { @@ -123,14 +123,14 @@ helper.removeFilters = async function() { let count = await $$('.filters-applied .single-filter.selected').count(); while(count) { - $$('.single-filter.selected').get(0).click(); + $$('.single-filter.selected').get(0).$('.remove-filter').click(); count = await $$('.single-filter.selected').count(); } }; helper.getCustomFilters = function() { - return $$('.filter-list a[data-type="myFilters"]'); + return $$('.filter-list div[data-type="myFilters"]'); }; helper.removeCustomFilters = async function() { diff --git a/e2e/helpers/taskboard-helper.js b/e2e/helpers/taskboard-helper.js index 44e9971e..4a6d7e5b 100644 --- a/e2e/helpers/taskboard-helper.js +++ b/e2e/helpers/taskboard-helper.js @@ -29,25 +29,25 @@ helper.openBulkTaskLb = function(row) { }; helper.foldRow = function(row) { - let icon = $$('.icon-fold-row.vfold').get(row); + let icon = $$('.vfold.fold-action').get(row); icon.click(); }; helper.unFoldRow = function(row) { - let icon = $$('.icon-unfold-row.vunfold').get(row); + let icon = $$('.vunfold.fold-action').get(row); icon.click(); }; helper.foldColumn = function(row) { - let icon = $$('.icon-fold-row.hfold').get(row); + let icon = $$('.hfold.fold-action').get(row); icon.click(); }; helper.unFoldColumn = function(row) { - let icon = $$('.icon-fold-row.hunfold').get(row); + let icon = $$('.hunfold.fold-action').get(row); icon.click(); }; diff --git a/e2e/helpers/wiki-helper.js b/e2e/helpers/wiki-helper.js index dcbabea9..2d4c8c0e 100644 --- a/e2e/helpers/wiki-helper.js +++ b/e2e/helpers/wiki-helper.js @@ -18,7 +18,7 @@ helper.links = function() { }, get: function() { - return el.$$(".wiki-link a"); + return el.$$(".wiki-link a.link-title"); }, deleteLink: async function(link){ diff --git a/e2e/shared/detail.js b/e2e/shared/detail.js index 40bac601..53d14046 100644 --- a/e2e/shared/detail.js +++ b/e2e/shared/detail.js @@ -21,8 +21,12 @@ shared.titleTesting = async function() { titleHelper.setTitle("New title " + date); titleHelper.save(); + let notificationSuccess = await notifications.success.open(); + + expect(notificationSuccess).to.be.true; + let newTitle = await titleHelper.getTitle(); - expect(notifications.success.open()).to.be.eventually.true; + expect(newTitle).to.be.not.equal(title); await notifications.success.close(); @@ -51,8 +55,9 @@ shared.descriptionTesting = async function() { descriptionHelper.save(); let newDescription = await descriptionHelper.getInnerHtml(); + let notificationOpen = notifications.success.open(); - expect(notifications.success.open()).to.be.eventually.true; + expect(notificationOpen).to.be.equal.true; expect(newDescription).to.be.not.equal(description); await notifications.success.close(); @@ -203,12 +208,16 @@ shared.blockTesting = async function() { await blockLightboxHelper.waitClose(); - expect($('.block-description').getText()).to.be.eventually.equal('This is a testing block reason'); - expect($('.block-description').isDisplayed()).to.be.eventually.true; + let descriptionText = await $('.block-description').getText(); + expect(descriptionText).to.be.equal('This is a testing block reason'); + + let isDisplayed = $('.block-description').isDisplayed(); + expect(isDisplayed).to.be.equal.true; blockHelper.unblock(); - expect($('.block-description').isDisplayed()).to.be.eventually.false; + isDisplayed = $('.block-description').isDisplayed(); + expect(isDisplayed).to.be.equal.false; await notifications.success.close(); } diff --git a/e2e/suites/admin/project/create-delete.e2e.js b/e2e/suites/admin/project/create-delete.e2e.js index fa338d0a..9e3041e2 100644 --- a/e2e/suites/admin/project/create-delete.e2e.js +++ b/e2e/suites/admin/project/create-delete.e2e.js @@ -37,16 +37,16 @@ describe('create-delete project', function() { }); it('create project', async function() { + let originalUrl = await browser.getCurrentUrl(); + lb.name().sendKeys('aaa'); lb.description().sendKeys('bbb'); await lb.submit(); - let open = utils.notifications.success.open(); + let projectUrl = await browser.getCurrentUrl(); - expect(open).to.be.equal.true; - - await utils.notifications.success.close(); + expect(projectUrl).not.to.be.equal(originalUrl); }); it('delete', async function() { diff --git a/e2e/suites/admin/project/modules.e2e.js b/e2e/suites/admin/project/modules.e2e.js index 4e56f925..7577e198 100644 --- a/e2e/suites/admin/project/modules.e2e.js +++ b/e2e/suites/admin/project/modules.e2e.js @@ -13,6 +13,19 @@ describe('modules', function() { await utils.common.waitLoader(); utils.common.takeScreenshot('admin', 'project-modules'); + + // enable if the first module is disable + let functionalities = $$('.module'); + let functionality = functionalities.get(0); + + let input = functionality.$('.check input'); + + browser.actions() + .mouseMove(input) + .click() + .perform(); + + await utils.notifications.success.open(); }); it('disable module', async function() { @@ -47,9 +60,12 @@ describe('modules', function() { .click() .perform(); + let notificationSuccess = await utils.notifications.success.open(); + + expect(notificationSuccess).to.be.equal(true); + let active = await utils.common.hasClass(functionality, 'active'); - expect(utils.notifications.success.open()).to.be.eventually.equal(true); expect(active).to.be.true; await utils.notifications.success.close(); @@ -74,6 +90,9 @@ describe('modules', function() { salt.sendKeys('abccceee'); functionality.$('.icon-save').click(); - expect(utils.notifications.success.open()).to.be.eventually.equal(true); + + let notificationSuccess = await utils.notifications.success.open(); + + expect(notificationSuccess).to.be.equal(true); }); }); diff --git a/e2e/suites/issues/issue-detail.e2e.js b/e2e/suites/issues/issue-detail.e2e.js index b713dbaa..f7f657e2 100644 --- a/e2e/suites/issues/issue-detail.e2e.js +++ b/e2e/suites/issues/issue-detail.e2e.js @@ -7,7 +7,7 @@ var chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised); var expect = chai.expect; -describe('Issue detail', async function(){ +describe.only('Issue detail', async function(){ let issueUrl = ''; before(async function(){ diff --git a/e2e/suites/issues/issues.e2e.js b/e2e/suites/issues/issues.e2e.js index 8c840e0f..99e4a806 100644 --- a/e2e/suites/issues/issues.e2e.js +++ b/e2e/suites/issues/issues.e2e.js @@ -53,9 +53,9 @@ describe('issues list', function() { it('send form', async function() { createIssueLightbox.submit(); - await createIssueLightbox.waitClose(); + let openNotification = await utils.notifications.success.open(); - expect(utils.notifications.success.open()).to.be.eventually.true; + expect(openNotification).to.be.true; await utils.notifications.success.close(); }); @@ -174,6 +174,7 @@ describe('issues list', function() { let htmlChanges = await utils.common.outerHtmlChanges(table); issuesHelper.filtersCats().get(0).$('a').click(); issuesHelper.selectFilter(0); + await htmlChanges(); issuesHelper.backToFilters(); @@ -285,7 +286,9 @@ describe('issues list', function() { await issuesHelper.saveFilter('custom'); - expect(issuesHelper.getCustomFilters().count()).to.be.eventually.equal(1); + let customFilters = await issuesHelper.getCustomFilters().count(); + + expect(customFilters).to.be.equal(1); await issuesHelper.removeFilters(); issuesHelper.backToFilters(); diff --git a/e2e/suites/project-home.e2e.js b/e2e/suites/project-home.e2e.js index dfaf8295..64643e05 100644 --- a/e2e/suites/project-home.e2e.js +++ b/e2e/suites/project-home.e2e.js @@ -53,6 +53,7 @@ describe('project home', function() { }; await reset(); + await browser.waitForAngular(); let link = $('tg-like-project-button a'); let likesCounterOld = parseInt(await link.$('.track-button-counter').getText(), 10); diff --git a/e2e/suites/wiki.e2e.js b/e2e/suites/wiki.e2e.js index d3610580..46abefe4 100644 --- a/e2e/suites/wiki.e2e.js +++ b/e2e/suites/wiki.e2e.js @@ -30,7 +30,7 @@ describe('wiki', function() { it('follow last link', async function() { // the click event is not on the :( - let lastLink = wikiHelper.links().get().last().$('.link-title'); + let lastLink = wikiHelper.links().get().last(); browser .actions() .mouseMove(lastLink) diff --git a/e2e/utils/common.js b/e2e/utils/common.js index 4c981c2e..30eef62b 100644 --- a/e2e/utils/common.js +++ b/e2e/utils/common.js @@ -46,6 +46,16 @@ common.browserSkip = function(browserName, name, fn) { } }; +common.waitHref = async function(el) { + await browser.wait(async function() { + let href = await el.getAttribute('href'); + + return (href.length > 1 && href !== browser.params.glob.host + "#"); + }, 5000); + + return el.getAttribute('href'); +}; + common.link = async function(el) { let oldUrl = await browser.getCurrentUrl(); @@ -68,13 +78,7 @@ common.link = async function(el) { .mouseMove({x: 10, y: 10}) .perform(); - await browser.wait(async function() { - let href = await el.getAttribute('href'); - - return (href.length > 1 && href !== browser.params.glob.host + "#"); - }, 5000); - - + await common.waitHref(el); await browser .actions() @@ -454,9 +458,6 @@ common.createProject = async function(members = []) { await lb.submit(); - await notifications.success.open(); - await notifications.success.close(); - if (members.length) { var adminMembershipsHelper = require('../helpers').adminMemberships; diff --git a/e2e/utils/nav.js b/e2e/utils/nav.js index b5733c56..14bce981 100644 --- a/e2e/utils/nav.js +++ b/e2e/utils/nav.js @@ -14,7 +14,23 @@ var actions = { project = $$('div[tg-dropdown-project-list] li a').get(index); } - await common.link(project); + let oldUrl = await browser.getCurrentUrl(); + + await browser + .actions() + .mouseMove(project) + .perform(); + + let href = await common.waitHref(project); + + // we don't use click because in IE doesn't work + browser.get(href); + + await browser.wait(async function() { + let newUrl = await browser.getCurrentUrl(); + + return oldUrl !== newUrl; + }, 7000); return common.waitLoader(); }, From 0d5976f7c02fddc7dfd0cb3176edb064afa4e7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Tue, 12 Apr 2016 19:47:44 +0200 Subject: [PATCH 13/47] Fix issue #4070: Can't open wiki links in new window --- app/coffee/modules/wiki/main.coffee | 7 +++++++ app/coffee/modules/wiki/nav.coffee | 19 ++++--------------- app/partials/wiki/wiki-nav.jade | 7 ++++++- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/coffee/modules/wiki/main.coffee b/app/coffee/modules/wiki/main.coffee index 88dd33e1..a34db70e 100644 --- a/app/coffee/modules/wiki/main.coffee +++ b/app/coffee/modules/wiki/main.coffee @@ -117,6 +117,13 @@ class WikiDetailController extends mixOf(taiga.Controller, taiga.PageMixin) loadWikiLinks: -> return @rs.wiki.listLinks(@scope.projectId).then (wikiLinks) => @scope.wikiLinks = wikiLinks + + for link in @scope.wikiLinks + link.url = @navUrls.resolve("project-wiki-page", { + project: @scope.projectSlug + slug: link.href + }) + selectedWikiLink = _.find(wikiLinks, {href: @scope.wikiSlug}) @scope.wikiTitle = selectedWikiLink.title if selectedWikiLink? diff --git a/app/coffee/modules/wiki/nav.coffee b/app/coffee/modules/wiki/nav.coffee index 6bf17e14..31ecf4ab 100644 --- a/app/coffee/modules/wiki/nav.coffee +++ b/app/coffee/modules/wiki/nav.coffee @@ -35,7 +35,8 @@ module = angular.module("taigaWiki") ## Wiki Main Directive ############################################################################# -WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $loading, $template, $compile, $translate) -> +WikiNavDirective = ($tgrepo, $log, $location, $confirm, $analytics, $loading, $template, + $compile, $translate) -> template = $template.get("wiki/wiki-nav.html", true) link = ($scope, $el, $attrs) -> $ctrl = $el.controller() @@ -59,18 +60,6 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l $el.off() $el.html(html) - $el.on "click", ".wiki-link .link-title", (event) -> - event.preventDefault() - target = angular.element(event.currentTarget) - linkId = target.parents('.wiki-link').data('id') - linkSlug = $scope.wikiLinks[linkId].href - $scope.$apply -> - ctx = { - project: $scope.projectSlug - slug: linkSlug - } - $location.path($navUrls.resolve("project-wiki-page", ctx)) - $el.on "click", ".add-button", (event) -> event.preventDefault() $el.find(".new").removeClass("hidden") @@ -146,5 +135,5 @@ WikiNavDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $analytics, $l return {link:link} -module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgNavUrls", - "$tgAnalytics", "$tgLoading", "$tgTemplate", "$compile", "$translate", WikiNavDirective]) +module.directive("tgWikiNav", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgAnalytics", + "$tgLoading", "$tgTemplate", "$compile", "$translate", WikiNavDirective]) diff --git a/app/partials/wiki/wiki-nav.jade b/app/partials/wiki/wiki-nav.jade index 6d5c6f34..1971a536 100644 --- a/app/partials/wiki/wiki-nav.jade +++ b/app/partials/wiki/wiki-nav.jade @@ -5,22 +5,27 @@ nav ul <% _.each(wikiLinks, function(link, index) { %> li.wiki-link(data-id!="<%- index %>") - a.link-title(title!="<%- link.title %>") <%- link.title %> + a.link-title(title!="<%- link.title %>", href!="<%- link.url %>") + <%- link.title %> + <% if (deleteWikiLinkPermission) { %> a.js-delete-link.remove-wiki-page(title!="{{'WIKI.DELETE_LINK_TITLE' | translate}}") tg-svg(svg-icon="icon-trash") <% } %> + input.hidden( type="text" placeholder="{{'COMMON.FIELDS.NAME' | translate}}" value!="<%- link.title %>" ) <% }) %> + li.new.hidden input( type="text" placeholder="{{'COMMON.FIELDS.NAME' | translate}}" ) + <% if (addWikiLinkPermission) { %> a( href="" From 3eea4664514caaed0afd0ea14cee7265dd9fbafc Mon Sep 17 00:00:00 2001 From: everblut Date: Fri, 12 Feb 2016 02:03:40 -0600 Subject: [PATCH 14/47] US #3903: Sprint number/title column on search results for user stories --- AUTHORS.rst | 1 + CHANGELOG.md | 1 + app/locales/taiga/locale-en.json | 3 ++- app/locales/taiga/locale-es.json | 2 +- app/partials/includes/modules/search-result-table.jade | 5 +++++ app/styles/modules/search/search-result-table.scss | 6 ++++-- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 31e3c168..6b5963bf 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -21,6 +21,7 @@ answer newbie questions, and generally made Taiga that much better: - Brett Profitt - Chris Wilson - Daniel Koch +- Everardo Medina - Florian Bezagu - Guilhem Got - Jordan Rinke diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af211e8..57d95cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - ... ### Misc +- Add sprint title on search results for user stories (thanks to [@everblut](https://github.com/everblut)) - Lots of small and not so small bugfixes. diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json index dd95fec7..3722b936 100644 --- a/app/locales/taiga/locale-en.json +++ b/app/locales/taiga/locale-en.json @@ -140,7 +140,8 @@ "BLOCKED_NOTE": "blocked note", "IS_BLOCKED": "is blocked", "REF": "Ref", - "VOTES": "Votes" + "VOTES": "Votes", + "SPRINT": "Sprint" }, "ROLES": { "ALL": "All" diff --git a/app/locales/taiga/locale-es.json b/app/locales/taiga/locale-es.json index 3c24f1c6..2e2d9abc 100644 --- a/app/locales/taiga/locale-es.json +++ b/app/locales/taiga/locale-es.json @@ -1572,4 +1572,4 @@ "RESULTS": "Resultados de búsqueda" } } -} \ No newline at end of file +} diff --git a/app/partials/includes/modules/search-result-table.jade b/app/partials/includes/modules/search-result-table.jade index 2394f9da..f6550aa5 100644 --- a/app/partials/includes/modules/search-result-table.jade +++ b/app/partials/includes/modules/search-result-table.jade @@ -28,6 +28,7 @@ script(type="text/ng-template", id="search-userstories") div.row.title div.ref(translate="COMMON.FIELDS.REF") div.user-stories(translate="SEARCH.FILTER_USER_STORIES") + div.sprint(translate="COMMON.FIELDS.SPRINT") div.status(translate="COMMON.FIELDS.STATUS") div.points(translate="COMMON.FIELDS.POINTS") div.search-result-table-body @@ -37,6 +38,10 @@ script(type="text/ng-template", id="search-userstories") div.user-story-name a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref", tg-bo-bind="us.subject") + div.sprint + div.sprint-link + a(href="", tg-nav="project-taskboard:project=project.slug,sprint=us.milestone_slug", + tg-bo-bind="us.milestone_name") div.status(tg-listitem-us-status="us") div.points(tg-bo-bind="us.total_points") diff --git a/app/styles/modules/search/search-result-table.scss b/app/styles/modules/search/search-result-table.scss index e970dfdf..2f4607bc 100644 --- a/app/styles/modules/search/search-result-table.scss +++ b/app/styles/modules/search/search-result-table.scss @@ -17,7 +17,8 @@ flex-shrink: 1; } .status, - .points { + .points, + .sprint { flex-basis: 150px; flex-grow: 0; padding: 0 1rem; @@ -60,7 +61,8 @@ border-bottom: 1px solid $whitish; } .status, - .points { + .points, + .sprint { position: relative; } .avatar { From 4e42484fd81a4426785111433aeeb906cabcc001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Tue, 19 Apr 2016 14:05:17 +0200 Subject: [PATCH 15/47] Open/close eye --- app/coffee/modules/kanban/main.coffee | 6 +++--- app/partials/includes/modules/kanban-table.jade | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee index 94484ba2..6945915e 100644 --- a/app/coffee/modules/kanban/main.coffee +++ b/app/coffee/modules/kanban/main.coffee @@ -329,7 +329,7 @@ KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) -> status = $scope.$eval($attrs.tgKanbanArchivedStatusHeader) hidden = true - $scope.class = "icon-open-eye" + $scope.class = "icon-watch" $scope.title = showArchivedText $el.on "click", (event) -> @@ -337,12 +337,12 @@ KanbanArchivedStatusHeaderDirective = ($rootscope, $translate) -> $scope.$apply -> if hidden - $scope.class = "icon-open-eye" + $scope.class = "icon-watch" $scope.title = showArchivedText $rootscope.$broadcast("kanban:hide-userstories-for-status", status.id) else - $scope.class = "icon-closed-eye" + $scope.class = "icon-unwatch" $scope.title = hideArchivedText $rootscope.$broadcast("kanban:show-userstories-for-status", status.id) diff --git a/app/partials/includes/modules/kanban-table.jade b/app/partials/includes/modules/kanban-table.jade index 4706029f..1f0d150a 100644 --- a/app/partials/includes/modules/kanban-table.jade +++ b/app/partials/includes/modules/kanban-table.jade @@ -60,7 +60,7 @@ div.kanban-table(tg-kanban-squish-column) ng-class="class" ng-if="s.is_archived" tg-kanban-archived-status-header="s") - tg-svg.bulk-action(svg-icon="icon-watch") + tg-svg.bulk-action(svg-icon="{{class}}") div.kanban-table-body div.kanban-table-inner From 4fea795b30212746a18099e00563b14306619111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Mon, 18 Apr 2016 18:14:05 +0200 Subject: [PATCH 16/47] Fix high-contrast styles and ally --- .../home/projects/home-project-list.jade | 24 ++-- app/modules/home/working-on/working-on.jade | 13 +- app/themes/high-contrast/custom.scss | 118 +++++++++++++++--- app/themes/high-contrast/variables.scss | 2 +- 4 files changed, 122 insertions(+), 35 deletions(-) diff --git a/app/modules/home/projects/home-project-list.jade b/app/modules/home/projects/home-project-list.jade index 273f0009..9ed81a65 100644 --- a/app/modules/home/projects/home-project-list.jade +++ b/app/modules/home/projects/home-project-list.jade @@ -11,7 +11,10 @@ section.home-project-list(ng-if="vm.projects.size") title="{{tag.get('name')}}" tg-repeat="tag in project.get('colorized_tags') track by tag.get('name')" ) - .project-card-inner(href="#", tg-nav="project:project=project.get('slug')") + .project-card-inner( + href="#" + tg-nav="project:project=project.get('slug')" + ) .project-card-header a.project-card-logo( href="#" @@ -22,7 +25,7 @@ section.home-project-list(ng-if="vm.projects.size") tg-project-logo-small-src="::project" alt="{{::project.get('name')}}" ) - h2.project-card-name + h3.project-card-name a.project-title( href="#" tg-nav="project:project=project.get('slug')" @@ -85,11 +88,16 @@ section.home-project-list(ng-if="vm.projects.size") section.projects-empty(ng-if="vm.projects != undefined && vm.projects.size === 0") tg-svg(svg-icon="icon-project") p(translate="HOME.EMPTY_PROJECT_LIST") - a.create-project-button.button-green(href="#", ng-click="vm.newProject()", - title="{{'PROJECT.NAVIGATION.TITLE_CREATE_PROJECT' | translate}}", - translate="PROJECT.NAVIGATION.ACTION_CREATE_PROJECT") + a.create-project-button.button-green( + href="#" + ng-click="vm.newProject()" + title="{{'PROJECT.NAVIGATION.TITLE_CREATE_PROJECT' | translate}}" + translate="PROJECT.NAVIGATION.ACTION_CREATE_PROJECT" + ) span(tg-import-project-button) - a.import-project-button.button-blackish(href="#", - title="{{'PROJECT.NAVIGATION.TITLE_IMPORT_PROJECT' | translate}}", - translate="PROJECT.NAVIGATION.ACTION_IMPORT_PROJECT") + a.import-project-button.button-blackish( + href="#" + title="{{'PROJECT.NAVIGATION.TITLE_IMPORT_PROJECT' | translate}}" + translate="PROJECT.NAVIGATION.ACTION_IMPORT_PROJECT" + ) input.import-file.hidden(type="file") diff --git a/app/modules/home/working-on/working-on.jade b/app/modules/home/working-on/working-on.jade index 6b301ba8..e434bfa5 100644 --- a/app/modules/home/working-on/working-on.jade +++ b/app/modules/home/working-on/working-on.jade @@ -1,11 +1,9 @@ +h1 + span.green {{"HOME.DASHBOARD" | translate}} + section.working-on-container - header - h1 - span.green {{"HOME.DASHBOARD" | translate}} - - - .title-bar.working-on-title(translate="HOME.WORKING_ON_SECTION") + h1.title-bar.working-on-title(translate="HOME.WORKING_ON_SECTION") .working-on(ng-if="vm.assignedTo.size") .duty-single( @@ -17,7 +15,8 @@ section.working-on-container include empty.jade section.watching-container - .title-bar.watching-title(translate="HOME.WATCHING_SECTION") + header + h1.title-bar.watching-title(translate="HOME.WATCHING_SECTION") .watching(ng-if="vm.watching.size") .duty-single( diff --git a/app/themes/high-contrast/custom.scss b/app/themes/high-contrast/custom.scss index d4527fc9..92078437 100644 --- a/app/themes/high-contrast/custom.scss +++ b/app/themes/high-contrast/custom.scss @@ -11,7 +11,7 @@ // Default body color and background body { background: $white; // fallback - color: $grayer; + color: $black; } // Main @@ -128,6 +128,11 @@ cite { .summary { background: $grayer; color: $white; + .stats { + svg { + fill: $white; + } + } } @@ -145,7 +150,7 @@ cite { :hover { color: $white; } - svg path { + svg { fill: $white; } } @@ -169,6 +174,89 @@ tg-project-menu { } } +//***************************** +//** HOME +//****************************** + +.home-project-list { + li { + border: 1px solid $black; + } + p { + color: $black; + } +} + +//***************************** +//** WORKING ON +//****************************** +.working-on-container { + .list-itemtype-ticket { + .ticket-status, + .ticket-status, + .ticket-type, + .ticket-project { + color: $black; + } + } +} + + +//***************************** +//** PROJECT PAGE +//****************************** + +.single-project { + .title { + background: $whitish; + color: $black; + } +} + +.watch-options { + a{ + &.active { + color: $primary; + } + } +} + +//***************************** +//** SCRUM +//****************************** + +.summary { + .data { + .number { + color: $white; + } + } +} + +//***************************** +//** WIKI +//****************************** + +.wiki-summary { + .username { + color: $white; + } +} + +.drag-drop-help { + color: $black; +} + +.wiki-content { + &.editable { + &:hover { + .wysiwyg { + background: $white; + border: 1px solid; + } + } + } +} //***************************** //** TASKBOARD @@ -222,11 +310,6 @@ tg-project-menu { color: $black; } - -.points-per-role > li:first-child { - background: $black; -} - //***************************** //** TICKET DETAIL //****************************** @@ -274,6 +357,15 @@ tg-project-menu { } } +.us-story-main-data { + .us-title { + background: $white; + .us-name { + color: $black; + } + } +} + //***************************** //** LOGIN //****************************** @@ -285,18 +377,7 @@ tg-project-menu { } } -//***************************** -//** HOME -//****************************** -.home-project-list { - li { - border: 1px solid $black; - } - p { - color: $black; - } -} //***************************** //** PROFILE @@ -336,7 +417,6 @@ tg-project-menu { } } label { - color: $black; &:hover { color: $white; } diff --git a/app/themes/high-contrast/variables.scss b/app/themes/high-contrast/variables.scss index b2ee93d6..de28f77c 100755 --- a/app/themes/high-contrast/variables.scss +++ b/app/themes/high-contrast/variables.scss @@ -8,7 +8,7 @@ $blackish: #212121; $grayer: #212121; $gray: #757575; $gray-light: #757575; -$whitish: #757575; +$whitish: #c1c1c1; $white: #fff; // Primary colors From 40351d6ce0147cb15c14efafe946dfdd428ff7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Wed, 20 Apr 2016 09:41:36 +0200 Subject: [PATCH 17/47] Remove assigned text button --- app/partials/common/components/assigned-to.jade | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/partials/common/components/assigned-to.jade b/app/partials/common/components/assigned-to.jade index 7642ed6e..7e1b7b18 100644 --- a/app/partials/common/components/assigned-to.jade +++ b/app/partials/common/components/assigned-to.jade @@ -13,6 +13,7 @@ <% }; %> .assigned-to-options + <% if (isEditable) { %> a( href="" title="{{ 'COMMON.ASSIGNED_TO.TITLE_ACTION_EDIT_ASSIGNMENT'|translate }}" @@ -25,7 +26,8 @@ <% if (isEditable && !isUnassigned) { %> tg-svg(svg-icon="icon-arrow-down") <% }; %> - + <% }; %> + <% if (isEditable && isUnassigned) { %> span(translate="COMMON.OR") |   From 5828a0f22badca9dfb28c95f5a9ef8f92e6d47ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Wed, 13 Apr 2016 11:46:41 +0200 Subject: [PATCH 18/47] Update UI for payments --- .../dropdown-user/dropdown-user.jade | 2 -- .../transfer-project.controller.coffee | 21 +++++++------------ ...> transfer-project.controller.spec.coffee} | 0 .../projects/transfer/transfer-project.jade | 2 ++ 4 files changed, 9 insertions(+), 16 deletions(-) rename app/modules/projects/transfer/{transfer-project.controler.spec.coffee => transfer-project.controller.spec.coffee} (100%) diff --git a/app/modules/navigation-bar/dropdown-user/dropdown-user.jade b/app/modules/navigation-bar/dropdown-user/dropdown-user.jade index 535d20ed..9419d1e9 100644 --- a/app/modules/navigation-bar/dropdown-user/dropdown-user.jade +++ b/app/modules/navigation-bar/dropdown-user/dropdown-user.jade @@ -30,8 +30,6 @@ div.navbar-dropdown.dropdown-user ng-class="{active: plugin.slug == currentPlugin.slug}" ) span.title {{ plugin.name }} - span.new(translate="PROJECT.NAVIGATION.NEW_ITEM") - li a( href="#", diff --git a/app/modules/projects/transfer/transfer-project.controller.coffee b/app/modules/projects/transfer/transfer-project.controller.coffee index 39be19ab..715d45b3 100644 --- a/app/modules/projects/transfer/transfer-project.controller.coffee +++ b/app/modules/projects/transfer/transfer-project.controller.coffee @@ -29,10 +29,9 @@ class TransferProject "$tgNavUrls", "$translate", "$tgConfirm" - "$tgLoading" ] - constructor: (@routeParams, @projectService, @location, @authService, @currentUserService, @navUrls, @translate, @confirmService, @loading) -> + constructor: (@routeParams, @projectService, @location, @authService, @currentUserService, @navUrls, @translate, @confirmService) -> initialize: () -> @.projectId = @.project.get("id") @@ -73,31 +72,25 @@ class TransferProject @.validNumberOfMemberships = maxMemberships == null || @.project.get('total_memberships') <= maxMemberships - transferAccept: (token, reason, $event) -> - target = angular.element($event.currentTarget) - currentLoading = @loading() - .target(target) - .start() + transferAccept: (token, reason) -> + @.loadingAccept = true return @projectService.transferAccept(@.project.get("id"), token, reason).then () => newUrl = @navUrls.resolve("project-admin-project-profile-details", { project: @.project.get("slug") }) - currentLoading.finish() + @.loadingAccept = false @location.path(newUrl) @confirmService.notify("success", @translate.instant("ADMIN.PROJECT_TRANSFER.ACCEPTED_PROJECT_OWNERNSHIP"), '', 5000) return - transferReject: (token, reason, $event) -> - target = $($event.target) - currentLoading = @loading() - .target(target) - .start() + transferReject: (token, reason) -> + @.loadingReject = true return @projectService.transferReject(@.project.get("id"), token, reason).then () => newUrl = @navUrls.resolve("home", { project: @project.get("slug") }) - currentLoading.finish() + @.loadingReject = false @location.path(newUrl) @confirmService.notify("success", @translate.instant("ADMIN.PROJECT_TRANSFER.REJECTED_PROJECT_OWNERNSHIP"), '', 5000) diff --git a/app/modules/projects/transfer/transfer-project.controler.spec.coffee b/app/modules/projects/transfer/transfer-project.controller.spec.coffee similarity index 100% rename from app/modules/projects/transfer/transfer-project.controler.spec.coffee rename to app/modules/projects/transfer/transfer-project.controller.spec.coffee diff --git a/app/modules/projects/transfer/transfer-project.jade b/app/modules/projects/transfer/transfer-project.jade index 1524d421..e7f4fbff 100644 --- a/app/modules/projects/transfer/transfer-project.jade +++ b/app/modules/projects/transfer/transfer-project.jade @@ -57,6 +57,7 @@ href="#" title="{{'ADMIN.PROJECT_TRANSFER.REJECT' | translate}}" translate="ADMIN.PROJECT_TRANSFER.REJECT" + tg-loading="vm.loadingReject" ) a.button.button-green( @@ -64,6 +65,7 @@ href="#" title="{{'ADMIN.PROJECT_TRANSFER.ACCEPT' | translate}}" translate="ADMIN.PROJECT_TRANSFER.ACCEPT" + tg-loading="vm.loadingAccept" ) tg-cant-own-project-explanation(ng-if="!vm.canBeOwnedByUser.valid") From 97c7b4a477bec70763bcf29be61218e1d1130913 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Wed, 20 Apr 2016 09:36:34 +0200 Subject: [PATCH 19/47] backlog pagination --- app/coffee/modules/backlog/filters.coffee | 2 ++ app/coffee/modules/backlog/main.coffee | 36 ++++++++++++++++--- .../modules/resources/userstories.coffee | 4 ++- .../includes/modules/backlog-table.jade | 10 +++++- app/styles/modules/backlog/backlog-table.scss | 9 +++++ 5 files changed, 55 insertions(+), 6 deletions(-) diff --git a/app/coffee/modules/backlog/filters.coffee b/app/coffee/modules/backlog/filters.coffee index 685e2619..14b33bf0 100644 --- a/app/coffee/modules/backlog/filters.coffee +++ b/app/coffee/modules/backlog/filters.coffee @@ -97,6 +97,8 @@ BacklogFiltersDirective = ($q, $log, $location, $template, $compile) -> reloadUserstories = () -> currentFiltersType = getFiltersType() + $ctrl.resetBacklogPagination() + $q.all([$ctrl.loadUserstories(), $ctrl.generateFilters()]).then () -> currentFilters = $scope.filters[currentFiltersType] renderFilters(_.reject(currentFilters, "selected")) diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index f56a0b9c..3031fc8f 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -62,6 +62,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @location, @appMetaService, @navUrls, @events, @analytics, @translate, @loading, @rs2) -> bindMethods(@) + @.page = 1 + @.disablePagination = false + @scope.userstories = [] + @scope.sectionName = @translate.instant("BACKLOG.SECTION_NAME") @showTags = false @activeFilters = false @@ -88,8 +92,13 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # On Error promise.then null, @.onInitialDataError.bind(@) + resetBacklogPagination: -> + @.page = 1 + @scope.userstories = [] + initializeEventHandlers: -> @scope.$on "usform:bulk:success", => + @.resetBacklogPagination() @.loadUserstories() @.loadProjectStats() @analytics.trackEvent("userstory", "create", "bulk create userstory on backlog", 1) @@ -100,6 +109,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @analytics.trackEvent("sprint", "create", "create sprint on backlog", 1) @scope.$on "usform:new:success", => + @.resetBacklogPagination() @.loadUserstories() @.loadProjectStats() @@ -110,6 +120,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @.loadProjectStats() @scope.$on "sprintform:remove:success", (event, sprint) => + @.resetBacklogPagination() @.loadSprints() @.loadProjectStats() @.loadUserstories() @@ -119,8 +130,12 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @rootscope.$broadcast("filters:update") - @scope.$on "usform:edit:success", => - @.loadUserstories() + @scope.$on "usform:edit:success", (event, data) => + index = _.findIndex @scope.userstories, (us) -> + return us.id == data.id + + @scope.userstories[index] = data + @rootscope.$broadcast("filters:update") @scope.$on("sprint:us:move", @.moveUs) @@ -249,17 +264,30 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @.loadUserstories() loadUserstories: -> + @.loadingUserstories = true + @.disablePagination = true @scope.httpParams = @.getUrlFilters() @rs.userstories.storeQueryParams(@scope.projectId, @scope.httpParams) + @scope.httpParams.page = @.page + promise = @rs.userstories.listUnassigned(@scope.projectId, @scope.httpParams) - return promise.then (userstories) => + return promise.then (result) => + userstories = result[0] + header = result[1] + # NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files - @scope.userstories = _.sortBy(userstories, "backlog_order") + @scope.userstories = @scope.userstories.concat(_.sortBy(userstories, "backlog_order")) @.setSearchDataFilters() + @.loadingUserstories = false + + if header('x-pagination-next') + @.disablePagination = false + @.page++ + # The broadcast must be executed when the DOM has been fully reloaded. # We can't assure when this exactly happens so we need a defer scopeDefer @scope, => diff --git a/app/coffee/modules/resources/userstories.coffee b/app/coffee/modules/resources/userstories.coffee index ca40da1e..5e98ca72 100644 --- a/app/coffee/modules/resources/userstories.coffee +++ b/app/coffee/modules/resources/userstories.coffee @@ -51,7 +51,9 @@ resourceProvider = ($repo, $http, $urls, $storage) -> params = {"project": projectId, "milestone": "null"} params = _.extend({}, params, filters or {}) service.storeQueryParams(projectId, params) - return $repo.queryMany("userstories", params) + return $repo.queryMany("userstories", params, { + enablePagination: true + }, true) service.listAll = (projectId, filters) -> params = {"project": projectId} diff --git a/app/partials/includes/modules/backlog-table.jade b/app/partials/includes/modules/backlog-table.jade index d59048ee..63c7268c 100644 --- a/app/partials/includes/modules/backlog-table.jade +++ b/app/partials/includes/modules/backlog-table.jade @@ -8,5 +8,13 @@ div.backlog-table-header span.header-points(translate="COMMON.FIELDS.POINTS") tg-svg(svg-icon="icon-arrow-down") -div.backlog-table-body(tg-backlog-sortable, ng-class="{'show-tags': ctrl.showTags, 'active-filters': ctrl.activeFilters}" ) +div.backlog-table-body( + tg-backlog-sortable, + ng-class="{'show-tags': ctrl.showTags, 'active-filters': ctrl.activeFilters}" + infinite-scroll="ctrl.loadUserstories()" + infinite-scroll-disabled="ctrl.disablePagination" + infinite-scroll-immediate-check='false' +) include ../components/backlog-row + + div(tg-loading="ctrl.loadingUserstories") diff --git a/app/styles/modules/backlog/backlog-table.scss b/app/styles/modules/backlog/backlog-table.scss index b3425e3f..aa0146e9 100644 --- a/app/styles/modules/backlog/backlog-table.scss +++ b/app/styles/modules/backlog/backlog-table.scss @@ -286,6 +286,15 @@ display: inline-block; } } + .loading { + margin: 2% auto; + width: 3rem; + img { + @extend %loading-spinner; + max-height: 3rem; + max-width: 3rem; + } + } } .empty-backlog { From e0087ee34e9d0b6bbad6659249249051228af660 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Wed, 20 Apr 2016 11:33:13 +0200 Subject: [PATCH 20/47] assigned to in public projects --- app/partials/common/components/assigned-to.jade | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/partials/common/components/assigned-to.jade b/app/partials/common/components/assigned-to.jade index 7e1b7b18..9157fc4d 100644 --- a/app/partials/common/components/assigned-to.jade +++ b/app/partials/common/components/assigned-to.jade @@ -13,6 +13,11 @@ <% }; %> .assigned-to-options + <% if (!isEditable && fullNameVisible) { %> + span.assigned-name + <%- fullName %> + <% }; %> + <% if (isEditable) { %> a( href="" @@ -23,11 +28,11 @@ <% if (fullNameVisible) { %> <%- fullName %> <% }; %> - <% if (isEditable && !isUnassigned) { %> + <% if (!isUnassigned) { %> tg-svg(svg-icon="icon-arrow-down") <% }; %> <% }; %> - + <% if (isEditable && isUnassigned) { %> span(translate="COMMON.OR") |   From dd0db6cd788ed37a234f942a9ec8f85f5be30b16 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Thu, 11 Feb 2016 10:48:05 +0100 Subject: [PATCH 21/47] Reduce taiga weight - improve uglify - remove jquery ui - add dragula - new autocomplete --- app/coffee/app.coffee | 3 + .../modules/admin/project-values.coffee | 25 +- app/coffee/modules/backlog/main.coffee | 44 +- app/coffee/modules/backlog/sortable.coffee | 232 +- app/coffee/modules/common/tags.coffee | 55 +- app/coffee/modules/kanban/main.coffee | 4 - app/coffee/modules/kanban/sortable.coffee | 40 +- app/coffee/modules/taskboard/main.coffee | 2 - app/coffee/modules/taskboard/sortable.coffee | 43 +- app/js/dom-autoscroller.js | 573 ++ app/js/dragula-drag-multiple.js | 221 + app/js/jquery-ui.drag-multiple-custom.js | 161 - app/js/jquery.ui.git-custom.js | 7033 ----------------- app/js/jquery.ui.touch-punch.min.js | 11 - app/modules/attachments/attachments.scss | 24 +- .../attachments-sortable.directive.coffee | 35 +- .../components/sort-projects.directive.coffee | 28 +- .../projects/listing/styles/project-list.scss | 16 +- .../services/app-meta.service.spec.coffee | 2 + .../services/scope-event.service.coffee | 54 - .../services/scope-event.service.spec.coffee | 102 - .../includes/components/backlog-row.jade | 2 +- .../includes/modules/kanban-table.jade | 3 +- app/partials/includes/modules/sprint.jade | 2 +- .../includes/modules/taskboard-table.jade | 6 +- app/styles/components/kanban-task.scss | 6 +- app/styles/components/taskboard-task.scss | 5 +- app/styles/core/elements.scss | 36 + app/styles/layout/backlog.scss | 22 + app/styles/modules/backlog/backlog-table.scss | 10 +- app/styles/modules/backlog/sprints.scss | 18 +- .../modules/backlog/taskboard-table.scss | 9 +- app/styles/modules/common/colors-table.scss | 9 + app/styles/vendor/jquery.mCustomScrollbar.css | 1272 --- bower.json | 15 +- conf.e2e.js | 6 +- gulp-utils.js | 86 + gulpfile.js | 58 +- package.json | 15 +- 39 files changed, 1303 insertions(+), 8985 deletions(-) create mode 100644 app/js/dom-autoscroller.js create mode 100644 app/js/dragula-drag-multiple.js delete mode 100644 app/js/jquery-ui.drag-multiple-custom.js delete mode 100644 app/js/jquery.ui.git-custom.js delete mode 100644 app/js/jquery.ui.touch-punch.min.js delete mode 100644 app/modules/services/scope-event.service.coffee delete mode 100644 app/modules/services/scope-event.service.spec.coffee delete mode 100644 app/styles/vendor/jquery.mCustomScrollbar.css diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 8d0b88de..ac0d17ed 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -601,6 +601,9 @@ i18nInit = (lang, $translate) -> # i18n - moment.js moment.locale(lang) + if (lang != 'en') # en is the default, the file doesn't exist + ljs.load "/#{window._version}/locales/moment-locales/" + lang + ".js" + # i18n - checksley.js messages = { defaultMessage: $translate.instant("COMMON.FORM_ERRORS.DEFAULT_MESSAGE") diff --git a/app/coffee/modules/admin/project-values.coffee b/app/coffee/modules/admin/project-values.coffee index e4bef2be..da753716 100644 --- a/app/coffee/modules/admin/project-values.coffee +++ b/app/coffee/modules/admin/project-values.coffee @@ -137,22 +137,31 @@ ProjectValuesDirective = ($log, $repo, $confirm, $location, animationFrame, $tra itemEl = null tdom = $el.find(".sortable") - tdom.sortable({ - handle: ".row.table-main.visualization", - dropOnEmpty: true - connectWith: ".project-values-body" - revert: 400 - axis: "y" + drake = dragula([tdom[0]], { + direction: 'vertical', + copySortSource: false, + copy: false, + mirrorContainer: tdom[0], + moves: (item) -> return $(item).is('div[tg-bind-scope]') }) - tdom.on "sortstop", (event, ui) -> - itemEl = ui.item + drake.on 'dragend', (item) -> + itemEl = $(item) itemValue = itemEl.scope().value itemIndex = itemEl.index() $scope.$broadcast("admin:project-values:move", itemValue, itemIndex) + scroll = autoScroll(window, { + margin: 20, + pixels: 30, + scrollWhenOutside: true, + autoScroll: () -> + return this.down && drake.dragging; + }) + $scope.$on "$destroy", -> $el.off() + drake.destroy() ## Value Link diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index 3031fc8f..e74ec6c1 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -139,8 +139,9 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @rootscope.$broadcast("filters:update") @scope.$on("sprint:us:move", @.moveUs) - @scope.$on("sprint:us:moved", @.loadSprints) - @scope.$on("sprint:us:moved", @.loadProjectStats) + @scope.$on "sprint:us:moved", () => + @.loadSprints() + @.loadProjectStats() @scope.$on("backlog:load-closed-sprints", @.loadClosedSprints) @scope.$on("backlog:unload-closed-sprints", @.unloadClosedSprints) @@ -390,8 +391,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # Persist in bulk all affected # userstories with order change @rs.userstories.bulkUpdateBacklogOrder(project, data).then => - for us in usList - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rootscope.$broadcast("sprint:us:moved") # For sprint else @@ -402,8 +402,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # Persist in bulk all affected # userstories with order change @rs.userstories.bulkUpdateSprintOrder(project, data).then => - for us in usList - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rootscope.$broadcast("sprint:us:moved") return promise @@ -430,7 +429,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F items = @.resortUserStories(@scope.userstories, "backlog_order") data = @.prepareBulkUpdateData(items, "backlog_order") return @rs.userstories.bulkUpdateBacklogOrder(us.project, data).then => - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rootscope.$broadcast("sprint:us:moved") if movedFromClosedSprint @rootscope.$broadcast("backlog:load-closed-sprints") @@ -443,17 +442,15 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # From backlog to sprint if oldSprintId == null us.milestone = newSprintId for us in usList + args = [newUsIndex, 0].concat(usList) - @scope.$apply => - args = [newUsIndex, 0].concat(usList) + # Add moving us to sprint user stories list + Array.prototype.splice.apply(newSprint.user_stories, args) - # Add moving us to sprint user stories list - Array.prototype.splice.apply(newSprint.user_stories, args) - - # Remove moving us from backlog userstories lists. - for us, key in usList - r = @scope.userstories.indexOf(us) - @scope.userstories.splice(r, 1) + # Remove moving us from backlog userstories lists. + for us, key in usList + r = @scope.userstories.indexOf(us) + @scope.userstories.splice(r, 1) # From sprint to sprint else @@ -470,21 +467,20 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F r = sprint.user_stories.indexOf(us) sprint.user_stories.splice(r, 1) - # Persist the milestone change of userstory + #Persist the milestone change of userstory promises = _.map usList, (us) => @repo.save(us) - # Rehash userstories order field - # and persist in bulk all changes. + #Rehash userstories order field + #and persist in bulk all changes. promise = @q.all(promises).then => items = @.resortUserStories(newSprint.user_stories, "sprint_order") data = @.prepareBulkUpdateData(items, "sprint_order") @rs.userstories.bulkUpdateSprintOrder(project, data).then (result) => - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rootscope.$broadcast("sprint:us:moved") @rs.userstories.bulkUpdateBacklogOrder(project, data).then => - for us in usList - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rootscope.$broadcast("sprint:us:moved") if movedToClosedSprint || movedFromClosedSprint @scope.$broadcast("backlog:load-closed-sprints") @@ -680,7 +676,7 @@ BacklogDirective = ($repo, $rootscope, $translate) -> return _.map(rowElements, (x) -> angular.element(x)) $scope.$on("userstories:loaded", reloadDoomLine) - $scope.$watch "stats", reloadDoomLine + $scope.$watch("stats", reloadDoomLine) ## Move to current sprint link @@ -835,8 +831,6 @@ BacklogDirective = ($repo, $rootscope, $translate) -> linkFilters($scope, $el, $attrs, $ctrl) linkDoomLine($scope, $el, $attrs, $ctrl) - $el.find(".backlog-table-body").disableSelection() - filters = $ctrl.getUrlFilters() if filters.status || filters.tags || diff --git a/app/coffee/modules/backlog/sortable.coffee b/app/coffee/modules/backlog/sortable.coffee index e674049f..9be36c54 100644 --- a/app/coffee/modules/backlog/sortable.coffee +++ b/app/coffee/modules/backlog/sortable.coffee @@ -38,187 +38,117 @@ module = angular.module("taigaBacklog") ############################################################################# deleteElement = (el) -> - el.scope().$destroy() - el.off() - el.remove() + $(el).scope().$destroy() + $(el).off() + $(el).remove() BacklogSortableDirective = ($repo, $rs, $rootscope, $tgConfirm, $translate) -> - # Notes about jquery bug: - # http://stackoverflow.com/questions/5791886/jquery-draggable-shows- - # helper-in-wrong-place-when-scrolled-down-page - link = ($scope, $el, $attrs) -> - getUsIndex = (us) => - return $(us).index(".backlog-table-body .row") - bindOnce $scope, "project", (project) -> # If the user has not enough permissions we don't enable the sortable if not (project.my_permissions.indexOf("modify_us") > -1) return + initIsBacklog = false + filterError = -> text = $translate.instant("BACKLOG.SORTABLE_FILTER_ERROR") $tgConfirm.notify("error", text) - $el.sortable({ - items: ".us-item-row", - cancel: ".popover" - connectWith: ".sprint" - dropOnEmpty: true - placeholder: "row us-item-row us-item-drag sortable-placeholder" - scroll: true - disableHorizontalScroll: true - # A consequence of length of backlog user story item - # the default tolerance ("intersection") not works properly. - tolerance: "pointer" - # Revert on backlog is disabled bacause it works bad. Something - # on the current taiga backlog structure or style makes jquery ui - # works unexpectly (in some circumstances calculates wrong - # position for revert). - revert: false - start: () -> - $(document.body).addClass("drag-active") - stop: () -> - $(document.body).removeClass("drag-active") + drake = dragula([$el[0], $('.empty-backlog')[0]], { + copySortSource: false, + copy: false, + isContainer: (el) -> return el.classList.contains('sprint-table'), + moves: (item) -> + if !$(item).hasClass('row') + return false - if $el.hasClass("active-filters") - $el.sortable("cancel") + # it doesn't move is the filter is open + parent = $(item).parent() + initIsBacklog = parent.hasClass('backlog-table-body') + + if initIsBacklog && $el.hasClass("active-filters") filterError() + return false + + return true }) - $el.on "multiplesortreceive", (event, ui) -> - if $el.hasClass("active-filters") - ui.source.sortable("cancel") - filterError() + drake.on 'drag', (item, container) -> + parent = $(item).parent() + initIsBacklog = parent.hasClass('backlog-table-body') - return + $(document.body).addClass("drag-active") - itemUs = ui.item.scope().us - itemIndex = getUsIndex(ui.item) + isChecked = $(item).find("input[type='checkbox']").is(":checked") - deleteElement(ui.item) + window.dragMultiple.start(item, container) - $scope.$emit("sprint:us:move", [itemUs], itemIndex, null) - ui.item.find('a').removeClass('noclick') + drake.on 'cloned', (item) -> + $(item).addClass('backlog-us-mirror') - $el.on "multiplesortstop", (event, ui) -> - # When parent not exists, do nothing - if $(ui.items[0]).parent().length == 0 - return + drake.on 'dragend', (item) -> + $('.doom-line').remove() - if $el.hasClass("active-filters") - return + parent = $(item).parent() + isBacklog = parent.hasClass('backlog-table-body') || parent.hasClass('empty-backlog') - items = _.sortBy ui.items, (item) -> - return $(item).index() + sameContainer = (initIsBacklog == isBacklog) - index = _.min _.map items, (item) -> - return getUsIndex(item) + dragMultipleItems = window.dragMultiple.stop() - us = _.map items, (item) -> - item = $(item) - itemUs = item.scope().us + $(document.body).removeClass("drag-active") - # HACK: setTimeout prevents that firefox click - # event fires just after drag ends - setTimeout ( => - item.find('a').removeClass('noclick') - ), 300 + items = $(item).parent().find('.row') - return itemUs + sprint = null - $scope.$emit("sprint:us:move", us, index, null) + firstElement = if dragMultipleItems.length then dragMultipleItems[0] else item - $el.on "sortstart", (event, ui) -> - ui.item.find('a').addClass('noclick') + if isBacklog + index = $(firstElement).index(".backlog-table-body .row") + else + index = $(firstElement).index() + sprint = parent.scope().sprint.id - $scope.$on "$destroy", -> - $el.off() - - return {link: link} - -BacklogEmptySortableDirective = ($repo, $rs, $rootscope) -> - # Notes about jquery bug: - # http://stackoverflow.com/questions/5791886/jquery-draggable-shows- - # helper-in-wrong-place-when-scrolled-down-page - - link = ($scope, $el, $attrs) -> - bindOnce $scope, "project", (project) -> - # If the user has not enough permissions we don't enable the sortable - if project.my_permissions.indexOf("modify_us") > -1 - $el.sortable({ - items: ".us-item-row", - dropOnEmpty: true - }) - - $el.on "sortreceive", (event, ui) -> - itemUs = ui.item.scope().us - itemIndex = ui.item.index() - - deleteElement(ui.item) - $scope.$emit("sprint:us:move", [itemUs], itemIndex, null) - - ui.item.find('a').removeClass('noclick') - - $scope.$on "$destroy", -> - $el.off() - - return {link: link} - - -SprintSortableDirective = ($repo, $rs, $rootscope) -> - link = ($scope, $el, $attrs) -> - bindOnce $scope, "project", (project) -> - # If the user has not enough permissions we don't enable the sortable - if project.my_permissions.indexOf("modify_us") > -1 - $el.sortable({ - scroll: true - dropOnEmpty: true - items: ".sprint-table .milestone-us-item-row" - disableHorizontalScroll: true - connectWith: ".sprint,.backlog-table-body,.empty-backlog" - placeholder: "row us-item-row sortable-placeholder" - forcePlaceholderSize:true - }) - - $el.on "multiplesortreceive", (event, ui) -> - items = _.sortBy ui.items, (item) -> - return $(item).index() - - index = _.min _.map items, (item) -> - return $(item).index() - - us = _.map items, (item) -> - item = $(item) - itemUs = item.scope().us + if !sameContainer + if dragMultipleItems.length + usList = _.map dragMultipleItems, (item) -> + return item = $(item).scope().us + else + usList = [$(item).scope().us] + if (dragMultipleItems.length) + _.each dragMultipleItems, (item) -> + deleteElement(item) + else deleteElement(item) + else + if dragMultipleItems.length + usList = _.map dragMultipleItems, (item) -> + return item = $(item).scope().us + else + usList = _.map items, (item) -> + item = $(item) + itemUs = item.scope().us - return itemUs + return itemUs - $scope.$emit("sprint:us:move", us, index, $scope.sprint.id) + $scope.$emit("sprint:us:move", usList, index, sprint) - $el.on "multiplesortstop", (event, ui) -> - # When parent not exists, do nothing - if ui.item.parent().length == 0 - return + scroll = autoScroll([window], { + margin: 20, + pixels: 30, + scrollWhenOutside: true, + autoScroll: () -> + return this.down && drake.dragging; + }) - itemUs = ui.item.scope().us - itemIndex = ui.item.index() - - # HACK: setTimeout prevents that firefox click - # event fires just after drag ends - setTimeout ( => - ui.item.find('a').removeClass('noclick') - ), 300 - - $scope.$emit("sprint:us:move", [itemUs], itemIndex, $scope.sprint.id) - - $el.on "sortstart", (event, ui) -> - ui.item.find('a').addClass('noclick') - - return {link:link} + $scope.$on "$destroy", -> + $el.off() + drake.destroy() + return {link: link} module.directive("tgBacklogSortable", [ "$tgRepo", @@ -228,17 +158,3 @@ module.directive("tgBacklogSortable", [ "$translate", BacklogSortableDirective ]) - -module.directive("tgBacklogEmptySortable", [ - "$tgRepo", - "$tgResources", - "$rootScope", - BacklogEmptySortableDirective -]) - -module.directive("tgSprintSortable", [ - "$tgRepo", - "$tgResources", - "$rootScope", - SprintSortableDirective -]) diff --git a/app/coffee/modules/common/tags.coffee b/app/coffee/modules/common/tags.coffee index 271d1e54..706fa4a4 100644 --- a/app/coffee/modules/common/tags.coffee +++ b/app/coffee/modules/common/tags.coffee @@ -108,6 +108,8 @@ LbTagLineDirective = ($rs, $template, $compile) -> templateTags = $template.get("common/tag/lb-tag-line-tags.html", true) + autocomplete = null + link = ($scope, $el, $attrs, $model) -> ## Render renderTags = (tags, tagsColors) -> @@ -130,7 +132,7 @@ LbTagLineDirective = ($rs, $template, $compile) -> resetInput = -> $el.find("input").val("") - $el.find("input").autocomplete("close") + autocomplete.close() ## Aux methods addValue = (value) -> @@ -190,22 +192,15 @@ LbTagLineDirective = ($rs, $template, $compile) -> deleteValue(value) bindOnce $scope, "project", (project) -> - positioningFunction = (position, elements) -> - menu = elements.element.element - menu.css("width", elements.target.width) - menu.css("top", position.top) - menu.css("left", position.left) + input = $el.find("input") - $el.find("input").autocomplete({ - source: _.keys(project.tags_colors) - position: { - my: "left top", - using: positioningFunction - } - select: (event, ui) -> - addValue(ui.item.value) - ui.item.value = "" - }) + autocomplete = new Awesomplete(input[0], { + list: _.keys(project.tags_colors) + }); + + input.on "awesomplete-selectcomplete", () -> + addValue(input.val()) + input.val("") $scope.$watch $attrs.ngModel, (tags) -> tagsColors = $scope.project?.tags_colors or [] @@ -235,6 +230,8 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template, $compi templateTags = $template.get("common/tag/tags-line-tags.html", true) link = ($scope, $el, $attrs, $model) -> + autocomplete = null + isEditable = -> if $attrs.requiredPerm? return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1 @@ -268,7 +265,8 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template, $compi hideInput = -> $el.find("input").addClass("hidden").blur() resetInput = -> $el.find("input").val("") - $el.find("input").autocomplete("close") + + autocomplete.close() ## Aux methods addValue = $qqueue.bindAdd (value) -> @@ -366,22 +364,15 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $qqueue, $template, $compi showAddTagButton() - positioningFunction = (position, elements) -> - menu = elements.element.element - menu.css("width", elements.target.width) - menu.css("top", position.top) - menu.css("left", position.left) + input = $el.find("input") - $el.find("input").autocomplete({ - source: _.keys(tags_colors) - position: { - my: "left top", - using: positioningFunction - } - select: (event, ui) -> - addValue(ui.item.value) - ui.item.value = "" - }) + autocomplete = new Awesomplete(input[0], { + list: _.keys(tags_colors) + }); + + input.on "awesomplete-selectcomplete", () -> + addValue(input.val()) + input.val("") $scope.$watch $attrs.ngModel, (model) -> return if not model diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee index 6945915e..c23f4f28 100644 --- a/app/coffee/modules/kanban/main.coffee +++ b/app/coffee/modules/kanban/main.coffee @@ -418,8 +418,6 @@ module.directive("tgKanbanArchivedStatusIntro", ["$translate", KanbanArchivedSta KanbanUserstoryDirective = ($rootscope, $loading, $rs, $rs2) -> link = ($scope, $el, $attrs, $model) -> - $el.disableSelection() - $scope.$watch "us", (us) -> if us.is_blocked and not $el.hasClass("blocked") $el.addClass("blocked") @@ -498,8 +496,6 @@ module.directive("tgKanbanSquishColumn", ["$tgResources", KanbanSquishColumnDire KanbanWipLimitDirective = -> link = ($scope, $el, $attrs) -> - $el.disableSelection() - status = $scope.$eval($attrs.tgKanbanWipLimit) redrawWipLimit = => diff --git a/app/coffee/modules/kanban/sortable.coffee b/app/coffee/modules/kanban/sortable.coffee index 9051b77e..41cbb23d 100644 --- a/app/coffee/modules/kanban/sortable.coffee +++ b/app/coffee/modules/kanban/sortable.coffee @@ -55,16 +55,23 @@ KanbanSortableDirective = ($repo, $rs, $rootscope) -> itemEl.off() itemEl.remove() - tdom.sortable({ - handle: ".kanban-task-inner" - dropOnEmpty: true - connectWith: ".kanban-uses-box" - revert: 400 + containers = _.map $el.find('.task-column'), (item) -> + return item + + drake = dragula(containers, { + copySortSource: false, + copy: false, + mirrorContainer: tdom[0], + moves: (item) -> + return $(item).hasClass('kanban-task') }) - tdom.on "sortstop", (event, ui) -> - parentEl = ui.item.parent() - itemEl = ui.item + drake.on 'drag', (item) -> + oldParentScope = $(item).parent().scope() + + drake.on 'dragend', (item) -> + parentEl = $(item).parent() + itemEl = $(item) itemUs = itemEl.scope().us itemIndex = itemEl.index() newParentScope = parentEl.scope() @@ -78,14 +85,17 @@ KanbanSortableDirective = ($repo, $rs, $rootscope) -> $scope.$apply -> $rootscope.$broadcast("kanban:us:move", itemUs, itemUs.status, newStatusId, itemIndex) - ui.item.find('a').removeClass('noclick') + scroll = autoScroll(containers, { + margin: 20, + pixels: 30, + scrollWhenOutside: true, + autoScroll: () -> + return this.down && drake.dragging; + }) - tdom.on "sortstart", (event, ui) -> - oldParentScope = ui.item.parent().scope() - ui.item.find('a').addClass('noclick') - - $scope.$on "$destroy", -> - $el.off() + $scope.$on "$destroy", -> + $el.off() + drake.destroy() return {link: link} diff --git a/app/coffee/modules/taskboard/main.coffee b/app/coffee/modules/taskboard/main.coffee index 11dc0486..d32b159f 100644 --- a/app/coffee/modules/taskboard/main.coffee +++ b/app/coffee/modules/taskboard/main.coffee @@ -309,8 +309,6 @@ module.directive("tgTaskboard", ["$rootScope", TaskboardDirective]) TaskboardTaskDirective = ($rootscope, $loading, $rs, $rs2) -> link = ($scope, $el, $attrs, $model) -> - $el.disableSelection() - $scope.$watch "task", (task) -> if task.is_blocked and not $el.hasClass("blocked") $el.addClass("blocked") diff --git a/app/coffee/modules/taskboard/sortable.coffee b/app/coffee/modules/taskboard/sortable.coffee index 19775335..c29875ef 100644 --- a/app/coffee/modules/taskboard/sortable.coffee +++ b/app/coffee/modules/taskboard/sortable.coffee @@ -39,9 +39,9 @@ module = angular.module("taigaBacklog") TaskboardSortableDirective = ($repo, $rs, $rootscope) -> link = ($scope, $el, $attrs) -> - bindOnce $scope, "project", (project) -> + bindOnce $scope, "tasks", (xx) -> # If the user has not enough permissions we don't enable the sortable - if not (project.my_permissions.indexOf("modify_us") > -1) + if not ($scope.project.my_permissions.indexOf("modify_us") > -1) return oldParentScope = null @@ -55,16 +55,22 @@ TaskboardSortableDirective = ($repo, $rs, $rootscope) -> itemEl.off() itemEl.remove() - tdom.sortable({ - handle: ".taskboard-task-inner", - dropOnEmpty: true - connectWith: ".taskboard-tasks-box" - revert: 400 + containers = _.map $el.find('.task-column'), (item) -> + return item + + drake = dragula(containers, { + copySortSource: false, + copy: false, + mirrorContainer: $el[0], + moves: (item) -> return $(item).hasClass('taskboard-task') }) - tdom.on "sortstop", (event, ui) -> - parentEl = ui.item.parent() - itemEl = ui.item + drake.on 'drag', (item) -> + oldParentScope = $(item).parent().scope() + + drake.on 'dragend', (item) -> + parentEl = $(item).parent() + itemEl = $(item) itemTask = itemEl.scope().task itemIndex = itemEl.index() newParentScope = parentEl.scope() @@ -80,14 +86,17 @@ TaskboardSortableDirective = ($repo, $rs, $rootscope) -> $scope.$apply -> $rootscope.$broadcast("taskboard:task:move", itemTask, newUsId, newStatusId, itemIndex) - ui.item.find('a').removeClass('noclick') + scroll = autoScroll(containers, { + margin: 20, + pixels: 30, + scrollWhenOutside: true, + autoScroll: () -> + return this.down && drake.dragging; + }) - tdom.on "sortstart", (event, ui) -> - oldParentScope = ui.item.parent().scope() - ui.item.find('a').addClass('noclick') - - $scope.$on "$destroy", -> - $el.off() + $scope.$on "$destroy", -> + $el.off() + drake.destroy() return {link: link} diff --git a/app/js/dom-autoscroller.js b/app/js/dom-autoscroller.js new file mode 100644 index 00000000..08831141 --- /dev/null +++ b/app/js/dom-autoscroller.js @@ -0,0 +1,573 @@ +// The MIT License (MIT) + +// Copyright (c) 2016 Quentin Engles + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +(function() { + // more_events + + function MoreEvents(context){ + this.listeners = {}; + this.__context = context || this; + } + + MoreEvents.prototype = { + constructor: MoreEvents, + on: function(event, listener){ + this.listeners[event] = this.listeners[event] || []; + this.listeners[event].push(listener); + return this; + }, + one: function(event, listener){ + function onceListener(){ + listener.apply(this, arguments); + this.off(event, onceListener); + return this; + } + return this.on(event, onceListener); + }, + emit: function(event){ + if(typeof this.listeners[event] === 'undefined' || !this.listeners[event].length) + return this; + + var args = Array.prototype.slice.call(arguments, 1), + canRun = this.listeners[event].length; + + do{ + this.listeners[event][--canRun].apply(this.__context, args); + }while(canRun); + + return this; + }, + off: function(event, listener){ + if(this.listeners[event] === undefined || !this.listeners[event].length) + return this; + this.listeners[event] = this.listeners[event].filter(function(item){ + return item !== listener; + }); + return this; + }, + dispose: function(){ + for(var n in this){ + this[n] = null; + } + } + }; + + // pointer_point + + var Emitter = MoreEvents; + + if(!Date.now){ Date.now = function(){ return new Date().getTime() } } + + function LocalDimensions(point, rect){ + for(var n in rect) + setProp(this, n, rect[n]); + + setProp(this, 'x', point.x - rect.left+1); + setProp(this, 'y', point.y - rect.top+1); + + setProp(this, 'north', (((rect.bottom - rect.top) / 2)-this.y)); + setProp(this, 'south', ((-(rect.bottom - rect.top) / 2)+this.y)); + setProp(this, 'east', (((rect.right - rect.left) / 2)-this.x)); + setProp(this, 'west', ((-(rect.right - rect.left) / 2)+this.x)); + + + function setProp(self, name, value){ + Object.defineProperty(self, name, { + value: value, + configurable: true, + writable: false + }); + } + } + function Point(elements){ + var self = this, el = []; + + if(typeof elements.length === 'undefined'){ + elements = [elements]; + } + + for(var i=0; i (startY - buf) && self.y < (startY + buf) && + self.x > (startX - buf) && self.x < (startX + buf))){ + //If there is scrolling there was a touch flick. + if(!scrolling){ + //No touch flick so + self.previous = null; + self.origin = null; + e.preventDefault(); + return false; + + } + } + } + + scrolling = false; + self.previous = null; + self.origin = null; + } + + function toPoint(event){ + var dot, eventDoc, doc, body, pageX, pageY; + var target, newTarget = null, leaving = null; + + event = event || window.event; // IE-ism + target = event.target || event.srcElement; + + //Supporting touch + //http://www.creativebloq.com/javascript/make-your-site-work-touch-devices-51411644 + if(event.targetTouches) { + event.pageX = event.targetTouches[0].clientX; + event.pageY = event.targetTouches[0].clientY; + event.clientX = event.targetTouches[0].clientX; + event.clientY = event.targetTouches[0].clientY; + }else + + // If pageX/Y aren't available and clientX/Y are, + // calculate pageX/Y - logic taken from jQuery. + // (This is to support old IE) + if (event.pageX === null && event.clientX !== null) { + eventDoc = (event.target && event.target.ownerDocument) || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = event.clientX + + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - + (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + + (doc && doc.scrollTop || body && body.scrollTop || 0) - + (doc && doc.clientTop || body && body.clientTop || 0 ); + } + + if(self.x && self.y){ + if(event.pageX < self.x) + direction.h = 'left'; + else if(event.pageX > self.x) + direction.h = 'right'; + if(event.pageY < self.y) + direction.v = 'up'; + else if(event.pageY > self.y) + direction.v = 'down'; + + lastmousex = self.x; + lastmousey = self.y; + } + + pos = {}; + //Prefer the viewport with clientX, and clientY. + //pageX, and pageY change too often. + pos.x = event.clientX;//event.pageX; + pos.y = event.clientY;//event.pageY; + + if(self.current === null || self.outside(self.current)){ + for(var i=0; i downTime + (special.hold[i].data || 2000)){ + special.hold[i].callback.call(this, el, rect); + } + } + } + downTime = 0; + }); + + function removeSpecial(event, cb){ + for(var i=0; i rect.top && this.y < rect.bottom && + this.x > rect.left && this.x < rect.right); + }, + outside: function(el){ + if(!el) throw new TypeError('Cannot be outside '+el); + return !this.inside(el); + } + }; + + function elementFromPoint(x, y){ + if(document.getElementFromPoint) + return document.getElementFromPoint(x, y); + else + return document.elementFromPoint(x, y); + return null; + } + + function safeObject(src){ + var obj = {}; + for(var n in src) + obj[n] = src[n]; + return obj; + } + + function getRect(el){ + if(el === window){ + return { + top: 0, + left: 0, + right: window.innerWidth, + bottom: window.innerHeight, + width: window.innerWidth, + height: window.innerHeight + }; + + }else{ + return el.getBoundingClientRect(); + } + } + + var pointer = function(element){ + return new Point(element); + }; + + + + // Autscroller + + function AutoScrollerFactory(element, options){ + return new AutoScroller(element, options); + } + + function AutoScroller(elements, options){ + var self = this, pixels = 2; + options = options || {}; + + this.margin = options.margin || -1; + this.scrolling = false; + this.scrollWhenOutside = options.scrollWhenOutside || false; + + this.point = pointer(elements); + + if(!isNaN(options.pixels)){ + pixels = options.pixels; + } + + if(typeof options.autoScroll === 'boolean'){ + this.autoScroll = options.autoScroll ? function(){return true;} : function(){return false;}; + }else if(typeof options.autoScroll === 'undefined'){ + this.autoScroll = function(){return false;}; + }else if(typeof options.autoScroll === 'function'){ + this.autoScroll = options.autoScroll; + } + + this.destroy = function() { + this.point.destroy(); + }; + + Object.defineProperties(this, { + down: { + get: function(){ return self.point.down; } + }, + interval: { + get: function(){ return 1/pixels * 1000; } + }, + pixels: { + set: function(i){ pixels = i; }, + get: function(){ return pixels; } + } + }); + + this.point.on('move', function(el, rect){ + + if(!el) return; + if(!self.autoScroll()) return; + if(!self.scrollWhenOutside && this.outside(el)) return; + + if(self.point.y < rect.top + self.margin){ + autoScrollV(el, -1, rect); + }else if(self.point.y > rect.bottom - self.margin){ + autoScrollV(el, 1, rect); + } + + if(self.point.x < rect.left + self.margin){ + autoScrollH(el, -1, rect); + }else if(self.point.x > rect.right - self.margin){ + autoScrollH(el, 1, rect); + } + }); + + function autoScrollV(el, amount, rect){ + //if(!self.down) return; + if(!self.autoScroll()) return; + if(!self.scrollWhenOutside && self.point.outside(el)) return; + if(el === window){ + window.scrollTo(el.pageXOffset, el.pageYOffset + amount); + }else{ + el.scrollTop = el.scrollTop + amount; + } + + setTimeout(function(){ + if(self.point.y < rect.top + self.margin){ + autoScrollV(el, amount, rect); + }else if(self.point.y > rect.bottom - self.margin){ + autoScrollV(el, amount, rect); + } + }, self.interval); + } + + function autoScrollH(el, amount, rect){ + //if(!self.down) return; + if(!self.autoScroll()) return; + if(!self.scrollWhenOutside && self.point.outside(el)) return; + if(el === window){ + window.scrollTo(el.pageXOffset + amount, el.pageYOffset); + }else{ + el.scrollLeft = el.scrollLeft + amount; + } + + setTimeout(function(){ + if(self.point.x < rect.left + self.margin){ + autoScrollH(el, amount, rect); + }else if(self.point.x > rect.right - self.margin){ + autoScrollH(el, amount, rect); + } + }, self.interval); + } + + } + + window.autoScroll = AutoScrollerFactory; +}()); diff --git a/app/js/dragula-drag-multiple.js b/app/js/dragula-drag-multiple.js new file mode 100644 index 00000000..1f7c521a --- /dev/null +++ b/app/js/dragula-drag-multiple.js @@ -0,0 +1,221 @@ +(function() { + var multipleSortableClass = 'ui-multisortable-multiple'; + var mainClass = 'main-drag-item'; + var inProgress = false; + + var reset = function(elm) { + $(elm) + .removeAttr('style') + .removeClass('tg-backlog-us-mirror') + .removeClass('backlog-us-mirror') + .data('dragMultipleIndex', null) + .data('dragMultipleActive', false); + }; + + var sort = function(positions) { + var current = dragMultiple.items.elm; + + positions.after.reverse(); + + $.each(positions.after, function () { + reset(this); + current.after(this); + }); + + $.each(positions.before, function () { + reset(this); + current.before(this); + }); + }; + + var drag = function() { + var current = dragMultiple.items.elm; + var container = dragMultiple.items.container; + + var shadow = dragMultiple.items.shadow; + + // following the drag element + var currentLeft = shadow.position().left; + var currentTop = shadow.position().top; + var height = shadow.outerHeight(); + + _.forEach(dragMultiple.items.draggingItems, function(elm, index) { + var elmIndex = parseInt(elm.data('dragMultipleIndex'), 10); + var top = currentTop + (elmIndex * height); + + elm + .css({ + top: top, + left: currentLeft + }); + }); + }; + + var stop = function() { + inProgress = false; + + refreshOriginal(); + + var current = dragMultiple.items.elm; + var container = dragMultiple.items.container; + + $(window).off('mousemove.dragmultiple'); + + // reset + dragMultiple.items = {}; + + $('.' + mainClass).removeClass(mainClass); + $('.tg-backlog-us-mirror').remove(); + $('.backlog-us-mirror').removeClass('backlog-us-mirror'); + + $('.tg-backlog-us-dragging') + .removeClass('tg-backlog-us-dragging') + .show(); + + return $('.' + multipleSortableClass); + }; + + var refreshOriginal = function() { + var index = parseInt(dragMultiple.items.elm.data('dragMultipleIndex'), 10); + + var after = []; + var before = []; + + _.forEach(dragMultiple.items.draggedItemsOriginal, function(item) { + if (parseInt($(item).data('dragMultipleIndex'), 10) > index) { + after.push(item); + } else { + before.push(item); + } + }); + + after.reverse(); + + _.forEach(after, function(item) { + $(item).insertAfter(dragMultiple.items.elm); + }); + + _.forEach(before, function(item) { + $(item).insertBefore(dragMultiple.items.elm); + }); + }; + + + var isMultiple = function(elm, container) { + var items = $(container).find('.' + multipleSortableClass); + + if (!$(elm).hasClass(multipleSortableClass) || !(items.length > 1)) { + return false; + } + + return true; + }; + + var setIndex = function(items) { + var before = []; + var after = []; + var mainFound = false; + _.forEach(items, function(item, index) { + if ($(item).data('dragMultipleIndex') === 0) { + mainFound = true; + return; + } + + if (mainFound) { + after.push(item); + } else { + before.push(item); + } + }); + + before.reverse(); + + _.forEach(after, function(item, index) { + $(item).data('dragMultipleIndex', index + 1); + }); + + _.forEach(before, function(item, index) { + $(item).data('dragMultipleIndex', -index - 1); + }); + }; + + var dragMultiple = {}; + + dragMultiple.prepare = function(elm, container) { + inProgress = true; + + var items = $(container).find('.' + multipleSortableClass); + + $(elm) + .data('dragmultiple:originalPosition', $(elm).position()) + .data('dragMultipleActive', true); + + dragMultiple.items = {}; + + dragMultiple.items.elm = $(elm); + dragMultiple.items.container = $(container); + + dragMultiple.items.elm.data('dragMultipleIndex', 0); + + setIndex(items); + + dragMultiple.items.shadow = $('.gu-mirror'); + + dragMultiple.items.elm.addClass(mainClass); + + items = _.filter(items, function(item) { + return !$(item).hasClass(mainClass); + }); + + dragMultiple.items.draggedItemsOriginal = items; + + var itemsCloned = _.map(items, function (item) { + clone = $(item).clone(true); + + clone + .addClass('backlog-us-mirror') + .addClass('tg-backlog-us-mirror') + .data('dragmultiple:originalPosition', $(item).position()) + .data('dragMultipleActive', true) + .css({ + zIndex: '9999', + opacity: '0.8', + position: 'fixed', + width: dragMultiple.items.elm.outerWidth(), + height: dragMultiple.items.elm.outerHeight() + }); + + $(item) + .hide() + .addClass('tg-backlog-us-dragging'); + + return clone; + }); + + dragMultiple.items.draggingItems = itemsCloned; + + $(document.body).append(itemsCloned); + }; + + dragMultiple.start = function(item, container) { + if (isMultiple(item, container)) { + $(window).on('mousemove.dragmultiple', function() { + if (!inProgress) { + dragMultiple.prepare(item, container); + } + + drag(); + }); + } + }; + + dragMultiple.stop = function() { + if (inProgress) { + return stop(); + } else { + return []; + } + }; + + window.dragMultiple = dragMultiple; +}()); diff --git a/app/js/jquery-ui.drag-multiple-custom.js b/app/js/jquery-ui.drag-multiple-custom.js deleted file mode 100644 index 15f449ff..00000000 --- a/app/js/jquery-ui.drag-multiple-custom.js +++ /dev/null @@ -1,161 +0,0 @@ -(function($) { - var multipleSortableClass = 'ui-multisortable-multiple'; - var dragStarted = false; - - var multiSort = {}; - - multiSort.isBelow = function(elm, compare) { - var elmOriginalPosition = elm.data('dragmultiple:originalPosition'); - var compareOriginalPosition = compare.data('dragmultiple:originalPosition'); - - return elmOriginalPosition.top > compareOriginalPosition.top; - }; - - multiSort.reset = function(elm) { - $(elm) - .removeClass("ui-sortable-helper") - .removeAttr('style') - .data('dragMultipleActive', false); - }; - - multiSort.sort = function(current, positions) { - positions.after.reverse(); - - $.each(positions.after, function () { - multiSort.reset(this); - current.after(this); - }); - - $.each(positions.before, function () { - multiSort.reset(this); - current.before(this); - }); - }; - - multiSort.sortPositions = function(elm, current) { - //saved if the elements are after or before the current - var insertAfter = []; - var insertBefore = []; - - $(elm).find('.' + multipleSortableClass).each(function () { - var elm = $(this); - - if (elm[0] === current[0] || !current.hasClass(multipleSortableClass)) return; - - if (multiSort.isBelow(elm, current)) { - insertAfter.push(elm); - } else { - insertBefore.push(elm); - } - }); - - return {'after': insertAfter, 'before': insertBefore}; - }; - - $.widget( "ui.sortable", $.ui.sortable, { - _mouseStart: function() { - dragStarted = false; - - this._superApply( arguments ); - }, - _createHelper: function () { - var helper = this._superApply( arguments ); - - if ($(helper).hasClass(multipleSortableClass)) { - $(this.element).find('.' + multipleSortableClass).each(function () { - $(this) - .data('dragmultiple:originalPosition', $(this).position()) - .data('dragMultipleActive', true); - }); - } - - return helper; - }, - _mouseStop: function (event, ui) { - var current = this.helper; - var elms = []; - - if (current.hasClass(multipleSortableClass)) { - elms = $(this.element).find('.' + multipleSortableClass); - } - - if (!elms.length) { - elms = [current]; - } - - //save the order of the elements relative to the main - var positions = multiSort.sortPositions(this.element, current); - - this._superApply( arguments ); - - if (this.element !== this.currentContainer.element) { - // change to another sortable list - multiSort.sort(current, positions); - - $(this.currentContainer.element).trigger('multiplesortreceive', { - 'item': current, - 'items': elms, - 'source': this.element - }); - } else if (current.hasClass(multipleSortableClass)) { - // sort in the same list - multiSort.sort(current, positions); - } - - $(this.element).trigger('multiplesortstop', { - 'item': current, - 'items': elms - }); - }, - _mouseDrag: function(key, value) { - this._super(key, value); - - var current = this.helper; - - if (!current.hasClass(multipleSortableClass)) return; - - // following the drag element - var currentLeft = current.position().left; - var currentTop = current.position().top; - var currentZIndex = current.css('z-index'); - var currentPosition = current.css('position'); - - var positions = multiSort.sortPositions(this.element, current); - - positions.before.reverse(); - - [{'positions': positions.after, type: 'after'}, - {'positions': positions.before, type: 'before'}] - .forEach(function (item) { - $.each(item.positions, function (index, elm) { - var top; - - if (item.type === 'after') { - top = currentTop + ((index + 1) * current.outerHeight()); - } else { - top = currentTop - ((index + 1) * current.outerHeight()); - } - - elm - .addClass("ui-sortable-helper") - .css({ - width: elm.outerWidth(), - height: elm.outerHeight(), - position: currentPosition, - zIndex: currentZIndex, - top: top, - left: currentLeft - }); - }); - }); - - // it only refresh position the first time because - // jquery-ui has saved the old positions of the draggable elements - // and with this will remove all elements with dragMultipleActive - if (!dragStarted) { - dragStarted = true; - this.refreshPositions(); - } - } - }); -}(jQuery)) diff --git a/app/js/jquery.ui.git-custom.js b/app/js/jquery.ui.git-custom.js deleted file mode 100644 index 855907fe..00000000 --- a/app/js/jquery.ui.git-custom.js +++ /dev/null @@ -1,7033 +0,0 @@ -/*! jQuery UI - v1.11.4 - 2015-05-19 -* http://jqueryui.com -* Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, autocomplete.js, menu.js -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define([ "jquery" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -}(function( $ ) { -/*! - * jQuery UI Core 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/category/ui-core/ - */ - - -// $.ui might exist from components with no dependencies, e.g., $.ui.position -$.ui = $.ui || {}; - -$.extend( $.ui, { - version: "1.11.4", - - keyCode: { - BACKSPACE: 8, - COMMA: 188, - DELETE: 46, - DOWN: 40, - END: 35, - ENTER: 13, - ESCAPE: 27, - HOME: 36, - LEFT: 37, - PAGE_DOWN: 34, - PAGE_UP: 33, - PERIOD: 190, - RIGHT: 39, - SPACE: 32, - TAB: 9, - UP: 38 - } -}); - -// plugins -$.fn.extend({ - scrollParent: function( includeHidden ) { - var position = this.css( "position" ), - excludeStaticParent = position === "absolute", - overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, - scrollParent = this.parents().filter( function() { - var parent = $( this ); - if ( excludeStaticParent && parent.css( "position" ) === "static" ) { - return false; - } - return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) ); - }).eq( 0 ); - - return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; - }, - - uniqueId: (function() { - var uuid = 0; - - return function() { - return this.each(function() { - if ( !this.id ) { - this.id = "ui-id-" + ( ++uuid ); - } - }); - }; - })(), - - removeUniqueId: function() { - return this.each(function() { - if ( /^ui-id-\d+$/.test( this.id ) ) { - $( this ).removeAttr( "id" ); - } - }); - } -}); - -// selectors -function focusable( element, isTabIndexNotNaN ) { - var map, mapName, img, - nodeName = element.nodeName.toLowerCase(); - if ( "area" === nodeName ) { - map = element.parentNode; - mapName = map.name; - if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { - return false; - } - img = $( "img[usemap='#" + mapName + "']" )[ 0 ]; - return !!img && visible( img ); - } - return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ? - !element.disabled : - "a" === nodeName ? - element.href || isTabIndexNotNaN : - isTabIndexNotNaN) && - // the element and all of its ancestors must be visible - visible( element ); -} - -function visible( element ) { - return $.expr.filters.visible( element ) && - !$( element ).parents().addBack().filter(function() { - return $.css( this, "visibility" ) === "hidden"; - }).length; -} - -$.extend( $.expr[ ":" ], { - data: $.expr.createPseudo ? - $.expr.createPseudo(function( dataName ) { - return function( elem ) { - return !!$.data( elem, dataName ); - }; - }) : - // support: jQuery <1.8 - function( elem, i, match ) { - return !!$.data( elem, match[ 3 ] ); - }, - - focusable: function( element ) { - return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); - }, - - tabbable: function( element ) { - var tabIndex = $.attr( element, "tabindex" ), - isTabIndexNaN = isNaN( tabIndex ); - return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); - } -}); - -// support: jQuery <1.8 -if ( !$( "" ).outerWidth( 1 ).jquery ) { - $.each( [ "Width", "Height" ], function( i, name ) { - var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], - type = name.toLowerCase(), - orig = { - innerWidth: $.fn.innerWidth, - innerHeight: $.fn.innerHeight, - outerWidth: $.fn.outerWidth, - outerHeight: $.fn.outerHeight - }; - - function reduce( elem, size, border, margin ) { - $.each( side, function() { - size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; - if ( border ) { - size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; - } - if ( margin ) { - size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; - } - }); - return size; - } - - $.fn[ "inner" + name ] = function( size ) { - if ( size === undefined ) { - return orig[ "inner" + name ].call( this ); - } - - return this.each(function() { - $( this ).css( type, reduce( this, size ) + "px" ); - }); - }; - - $.fn[ "outer" + name] = function( size, margin ) { - if ( typeof size !== "number" ) { - return orig[ "outer" + name ].call( this, size ); - } - - return this.each(function() { - $( this).css( type, reduce( this, size, true, margin ) + "px" ); - }); - }; - }); -} - -// support: jQuery <1.8 -if ( !$.fn.addBack ) { - $.fn.addBack = function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - }; -} - -// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) -if ( $( "" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { - $.fn.removeData = (function( removeData ) { - return function( key ) { - if ( arguments.length ) { - return removeData.call( this, $.camelCase( key ) ); - } else { - return removeData.call( this ); - } - }; - })( $.fn.removeData ); -} - -// deprecated -$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); - -$.fn.extend({ - focus: (function( orig ) { - return function( delay, fn ) { - return typeof delay === "number" ? - this.each(function() { - var elem = this; - setTimeout(function() { - $( elem ).focus(); - if ( fn ) { - fn.call( elem ); - } - }, delay ); - }) : - orig.apply( this, arguments ); - }; - })( $.fn.focus ), - - disableSelection: (function() { - var eventType = "onselectstart" in document.createElement( "div" ) ? - "selectstart" : - "mousedown"; - - return function() { - return this.bind( eventType + ".ui-disableSelection", function( event ) { - event.preventDefault(); - }); - }; - })(), - - enableSelection: function() { - return this.unbind( ".ui-disableSelection" ); - }, - - zIndex: function( zIndex ) { - if ( zIndex !== undefined ) { - return this.css( "zIndex", zIndex ); - } - - if ( this.length ) { - var elem = $( this[ 0 ] ), position, value; - while ( elem.length && elem[ 0 ] !== document ) { - // Ignore z-index if position is set to a value where z-index is ignored by the browser - // This makes behavior of this function consistent across browsers - // WebKit always returns auto if the element is positioned - position = elem.css( "position" ); - if ( position === "absolute" || position === "relative" || position === "fixed" ) { - // IE returns 0 when zIndex is not specified - // other browsers return a string - // we ignore the case of nested elements with an explicit value of 0 - //
- value = parseInt( elem.css( "zIndex" ), 10 ); - if ( !isNaN( value ) && value !== 0 ) { - return value; - } - } - elem = elem.parent(); - } - } - - return 0; - } -}); - -// $.ui.plugin is deprecated. Use $.widget() extensions instead. -$.ui.plugin = { - add: function( module, option, set ) { - var i, - proto = $.ui[ module ].prototype; - for ( i in set ) { - proto.plugins[ i ] = proto.plugins[ i ] || []; - proto.plugins[ i ].push( [ option, set[ i ] ] ); - } - }, - call: function( instance, name, args, allowDisconnected ) { - var i, - set = instance.plugins[ name ]; - - if ( !set ) { - return; - } - - if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { - return; - } - - for ( i = 0; i < set.length; i++ ) { - if ( instance.options[ set[ i ][ 0 ] ] ) { - set[ i ][ 1 ].apply( instance.element, args ); - } - } - } -}; - - -/*! - * jQuery UI Widget 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/jQuery.widget/ - */ - - -var widget_uuid = 0, - widget_slice = Array.prototype.slice; - -$.cleanData = (function( orig ) { - return function( elems ) { - var events, elem, i; - for ( i = 0; (elem = elems[i]) != null; i++ ) { - try { - - // Only trigger remove when necessary to save time - events = $._data( elem, "events" ); - if ( events && events.remove ) { - $( elem ).triggerHandler( "remove" ); - } - - // http://bugs.jquery.com/ticket/8235 - } catch ( e ) {} - } - orig( elems ); - }; -})( $.cleanData ); - -$.widget = function( name, base, prototype ) { - var fullName, existingConstructor, constructor, basePrototype, - // proxiedPrototype allows the provided prototype to remain unmodified - // so that it can be used as a mixin for multiple widgets (#8876) - proxiedPrototype = {}, - namespace = name.split( "." )[ 0 ]; - - name = name.split( "." )[ 1 ]; - fullName = namespace + "-" + name; - - if ( !prototype ) { - prototype = base; - base = $.Widget; - } - - // create selector for plugin - $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { - return !!$.data( elem, fullName ); - }; - - $[ namespace ] = $[ namespace ] || {}; - existingConstructor = $[ namespace ][ name ]; - constructor = $[ namespace ][ name ] = function( options, element ) { - // allow instantiation without "new" keyword - if ( !this._createWidget ) { - return new constructor( options, element ); - } - - // allow instantiation without initializing for simple inheritance - // must use "new" keyword (the code above always passes args) - if ( arguments.length ) { - this._createWidget( options, element ); - } - }; - // extend with the existing constructor to carry over any static properties - $.extend( constructor, existingConstructor, { - version: prototype.version, - // copy the object used to create the prototype in case we need to - // redefine the widget later - _proto: $.extend( {}, prototype ), - // track widgets that inherit from this widget in case this widget is - // redefined after a widget inherits from it - _childConstructors: [] - }); - - basePrototype = new base(); - // we need to make the options hash a property directly on the new instance - // otherwise we'll modify the options hash on the prototype that we're - // inheriting from - basePrototype.options = $.widget.extend( {}, basePrototype.options ); - $.each( prototype, function( prop, value ) { - if ( !$.isFunction( value ) ) { - proxiedPrototype[ prop ] = value; - return; - } - proxiedPrototype[ prop ] = (function() { - var _super = function() { - return base.prototype[ prop ].apply( this, arguments ); - }, - _superApply = function( args ) { - return base.prototype[ prop ].apply( this, args ); - }; - return function() { - var __super = this._super, - __superApply = this._superApply, - returnValue; - - this._super = _super; - this._superApply = _superApply; - - returnValue = value.apply( this, arguments ); - - this._super = __super; - this._superApply = __superApply; - - return returnValue; - }; - })(); - }); - constructor.prototype = $.widget.extend( basePrototype, { - // TODO: remove support for widgetEventPrefix - // always use the name + a colon as the prefix, e.g., draggable:start - // don't prefix for widgets that aren't DOM-based - widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name - }, proxiedPrototype, { - constructor: constructor, - namespace: namespace, - widgetName: name, - widgetFullName: fullName - }); - - // If this widget is being redefined then we need to find all widgets that - // are inheriting from it and redefine all of them so that they inherit from - // the new version of this widget. We're essentially trying to replace one - // level in the prototype chain. - if ( existingConstructor ) { - $.each( existingConstructor._childConstructors, function( i, child ) { - var childPrototype = child.prototype; - - // redefine the child widget using the same prototype that was - // originally used, but inherit from the new version of the base - $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); - }); - // remove the list of existing child constructors from the old constructor - // so the old child constructors can be garbage collected - delete existingConstructor._childConstructors; - } else { - base._childConstructors.push( constructor ); - } - - $.widget.bridge( name, constructor ); - - return constructor; -}; - -$.widget.extend = function( target ) { - var input = widget_slice.call( arguments, 1 ), - inputIndex = 0, - inputLength = input.length, - key, - value; - for ( ; inputIndex < inputLength; inputIndex++ ) { - for ( key in input[ inputIndex ] ) { - value = input[ inputIndex ][ key ]; - if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { - // Clone objects - if ( $.isPlainObject( value ) ) { - target[ key ] = $.isPlainObject( target[ key ] ) ? - $.widget.extend( {}, target[ key ], value ) : - // Don't extend strings, arrays, etc. with objects - $.widget.extend( {}, value ); - // Copy everything else by reference - } else { - target[ key ] = value; - } - } - } - } - return target; -}; - -$.widget.bridge = function( name, object ) { - var fullName = object.prototype.widgetFullName || name; - $.fn[ name ] = function( options ) { - var isMethodCall = typeof options === "string", - args = widget_slice.call( arguments, 1 ), - returnValue = this; - - if ( isMethodCall ) { - this.each(function() { - var methodValue, - instance = $.data( this, fullName ); - if ( options === "instance" ) { - returnValue = instance; - return false; - } - if ( !instance ) { - return $.error( "cannot call methods on " + name + " prior to initialization; " + - "attempted to call method '" + options + "'" ); - } - if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { - return $.error( "no such method '" + options + "' for " + name + " widget instance" ); - } - methodValue = instance[ options ].apply( instance, args ); - if ( methodValue !== instance && methodValue !== undefined ) { - returnValue = methodValue && methodValue.jquery ? - returnValue.pushStack( methodValue.get() ) : - methodValue; - return false; - } - }); - } else { - - // Allow multiple hashes to be passed on init - if ( args.length ) { - options = $.widget.extend.apply( null, [ options ].concat(args) ); - } - - this.each(function() { - var instance = $.data( this, fullName ); - if ( instance ) { - instance.option( options || {} ); - if ( instance._init ) { - instance._init(); - } - } else { - $.data( this, fullName, new object( options, this ) ); - } - }); - } - - return returnValue; - }; -}; - -$.Widget = function( /* options, element */ ) {}; -$.Widget._childConstructors = []; - -$.Widget.prototype = { - widgetName: "widget", - widgetEventPrefix: "", - defaultElement: "
", - options: { - disabled: false, - - // callbacks - create: null - }, - _createWidget: function( options, element ) { - element = $( element || this.defaultElement || this )[ 0 ]; - this.element = $( element ); - this.uuid = widget_uuid++; - this.eventNamespace = "." + this.widgetName + this.uuid; - - this.bindings = $(); - this.hoverable = $(); - this.focusable = $(); - - if ( element !== this ) { - $.data( element, this.widgetFullName, this ); - this._on( true, this.element, { - remove: function( event ) { - if ( event.target === element ) { - this.destroy(); - } - } - }); - this.document = $( element.style ? - // element within the document - element.ownerDocument : - // element is window or document - element.document || element ); - this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); - } - - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); - - this._create(); - this._trigger( "create", null, this._getCreateEventData() ); - this._init(); - }, - _getCreateOptions: $.noop, - _getCreateEventData: $.noop, - _create: $.noop, - _init: $.noop, - - destroy: function() { - this._destroy(); - // we can probably remove the unbind calls in 2.0 - // all event bindings should go through this._on() - this.element - .unbind( this.eventNamespace ) - .removeData( this.widgetFullName ) - // support: jquery <1.6.3 - // http://bugs.jquery.com/ticket/9413 - .removeData( $.camelCase( this.widgetFullName ) ); - this.widget() - .unbind( this.eventNamespace ) - .removeAttr( "aria-disabled" ) - .removeClass( - this.widgetFullName + "-disabled " + - "ui-state-disabled" ); - - // clean up events and states - this.bindings.unbind( this.eventNamespace ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - }, - _destroy: $.noop, - - widget: function() { - return this.element; - }, - - option: function( key, value ) { - var options = key, - parts, - curOption, - i; - - if ( arguments.length === 0 ) { - // don't return a reference to the internal hash - return $.widget.extend( {}, this.options ); - } - - if ( typeof key === "string" ) { - // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } - options = {}; - parts = key.split( "." ); - key = parts.shift(); - if ( parts.length ) { - curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); - for ( i = 0; i < parts.length - 1; i++ ) { - curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; - curOption = curOption[ parts[ i ] ]; - } - key = parts.pop(); - if ( arguments.length === 1 ) { - return curOption[ key ] === undefined ? null : curOption[ key ]; - } - curOption[ key ] = value; - } else { - if ( arguments.length === 1 ) { - return this.options[ key ] === undefined ? null : this.options[ key ]; - } - options[ key ] = value; - } - } - - this._setOptions( options ); - - return this; - }, - _setOptions: function( options ) { - var key; - - for ( key in options ) { - this._setOption( key, options[ key ] ); - } - - return this; - }, - _setOption: function( key, value ) { - this.options[ key ] = value; - - if ( key === "disabled" ) { - this.widget() - .toggleClass( this.widgetFullName + "-disabled", !!value ); - - // If the widget is becoming disabled, then nothing is interactive - if ( value ) { - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); - } - } - - return this; - }, - - enable: function() { - return this._setOptions({ disabled: false }); - }, - disable: function() { - return this._setOptions({ disabled: true }); - }, - - _on: function( suppressDisabledCheck, element, handlers ) { - var delegateElement, - instance = this; - - // no suppressDisabledCheck flag, shuffle arguments - if ( typeof suppressDisabledCheck !== "boolean" ) { - handlers = element; - element = suppressDisabledCheck; - suppressDisabledCheck = false; - } - - // no element argument, shuffle and use this.element - if ( !handlers ) { - handlers = element; - element = this.element; - delegateElement = this.widget(); - } else { - element = delegateElement = $( element ); - this.bindings = this.bindings.add( element ); - } - - $.each( handlers, function( event, handler ) { - function handlerProxy() { - // allow widgets to customize the disabled handling - // - disabled as an array instead of boolean - // - disabled class as method for disabling individual parts - if ( !suppressDisabledCheck && - ( instance.options.disabled === true || - $( this ).hasClass( "ui-state-disabled" ) ) ) { - return; - } - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - - // copy the guid so direct unbinding works - if ( typeof handler !== "string" ) { - handlerProxy.guid = handler.guid = - handler.guid || handlerProxy.guid || $.guid++; - } - - var match = event.match( /^([\w:-]*)\s*(.*)$/ ), - eventName = match[1] + instance.eventNamespace, - selector = match[2]; - if ( selector ) { - delegateElement.delegate( selector, eventName, handlerProxy ); - } else { - element.bind( eventName, handlerProxy ); - } - }); - }, - - _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + - this.eventNamespace; - element.unbind( eventName ).undelegate( eventName ); - - // Clear the stack to avoid memory leaks (#10056) - this.bindings = $( this.bindings.not( element ).get() ); - this.focusable = $( this.focusable.not( element ).get() ); - this.hoverable = $( this.hoverable.not( element ).get() ); - }, - - _delay: function( handler, delay ) { - function handlerProxy() { - return ( typeof handler === "string" ? instance[ handler ] : handler ) - .apply( instance, arguments ); - } - var instance = this; - return setTimeout( handlerProxy, delay || 0 ); - }, - - _hoverable: function( element ) { - this.hoverable = this.hoverable.add( element ); - this._on( element, { - mouseenter: function( event ) { - $( event.currentTarget ).addClass( "ui-state-hover" ); - }, - mouseleave: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-hover" ); - } - }); - }, - - _focusable: function( element ) { - this.focusable = this.focusable.add( element ); - this._on( element, { - focusin: function( event ) { - $( event.currentTarget ).addClass( "ui-state-focus" ); - }, - focusout: function( event ) { - $( event.currentTarget ).removeClass( "ui-state-focus" ); - } - }); - }, - - _trigger: function( type, event, data ) { - var prop, orig, - callback = this.options[ type ]; - - data = data || {}; - event = $.Event( event ); - event.type = ( type === this.widgetEventPrefix ? - type : - this.widgetEventPrefix + type ).toLowerCase(); - // the original event may come from any element - // so we need to reset the target on the new event - event.target = this.element[ 0 ]; - - // copy original event properties over to the new event - orig = event.originalEvent; - if ( orig ) { - for ( prop in orig ) { - if ( !( prop in event ) ) { - event[ prop ] = orig[ prop ]; - } - } - } - - this.element.trigger( event, data ); - return !( $.isFunction( callback ) && - callback.apply( this.element[0], [ event ].concat( data ) ) === false || - event.isDefaultPrevented() ); - } -}; - -$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { - $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { - if ( typeof options === "string" ) { - options = { effect: options }; - } - var hasOptions, - effectName = !options ? - method : - options === true || typeof options === "number" ? - defaultEffect : - options.effect || defaultEffect; - options = options || {}; - if ( typeof options === "number" ) { - options = { duration: options }; - } - hasOptions = !$.isEmptyObject( options ); - options.complete = callback; - if ( options.delay ) { - element.delay( options.delay ); - } - if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { - element[ method ]( options ); - } else if ( effectName !== method && element[ effectName ] ) { - element[ effectName ]( options.duration, options.easing, callback ); - } else { - element.queue(function( next ) { - $( this )[ method ](); - if ( callback ) { - callback.call( element[ 0 ] ); - } - next(); - }); - } - }; -}); - -var widget = $.widget; - - -/*! - * jQuery UI Mouse 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/mouse/ - */ - - -var mouseHandled = false; -$( document ).mouseup( function() { - mouseHandled = false; -}); - -var mouse = $.widget("ui.mouse", { - version: "1.11.4", - options: { - cancel: "input,textarea,button,select,option", - distance: 1, - delay: 0 - }, - _mouseInit: function() { - var that = this; - - this.element - .bind("mousedown." + this.widgetName, function(event) { - return that._mouseDown(event); - }) - .bind("click." + this.widgetName, function(event) { - if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { - $.removeData(event.target, that.widgetName + ".preventClickEvent"); - event.stopImmediatePropagation(); - return false; - } - }); - - this.started = false; - }, - - // TODO: make sure destroying one instance of mouse doesn't mess with - // other instances of mouse - _mouseDestroy: function() { - this.element.unbind("." + this.widgetName); - if ( this._mouseMoveDelegate ) { - this.document - .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate) - .unbind("mouseup." + this.widgetName, this._mouseUpDelegate); - } - }, - - _mouseDown: function(event) { - // don't let more than one widget handle mouseStart - if ( mouseHandled ) { - return; - } - - this._mouseMoved = false; - - // we may have missed mouseup (out of window) - (this._mouseStarted && this._mouseUp(event)); - - this._mouseDownEvent = event; - - var that = this, - btnIsLeft = (event.which === 1), - // event.target.nodeName works around a bug in IE 8 with - // disabled inputs (#7620) - elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); - if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { - return true; - } - - this.mouseDelayMet = !this.options.delay; - if (!this.mouseDelayMet) { - this._mouseDelayTimer = setTimeout(function() { - that.mouseDelayMet = true; - }, this.options.delay); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = (this._mouseStart(event) !== false); - if (!this._mouseStarted) { - event.preventDefault(); - return true; - } - } - - // Click event may never have fired (Gecko & Opera) - if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { - $.removeData(event.target, this.widgetName + ".preventClickEvent"); - } - - // these delegates are required to keep context - this._mouseMoveDelegate = function(event) { - return that._mouseMove(event); - }; - this._mouseUpDelegate = function(event) { - return that._mouseUp(event); - }; - - this.document - .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) - .bind( "mouseup." + this.widgetName, this._mouseUpDelegate ); - - event.preventDefault(); - - mouseHandled = true; - return true; - }, - - _mouseMove: function(event) { - // Only check for mouseups outside the document if you've moved inside the document - // at least once. This prevents the firing of mouseup in the case of IE<9, which will - // fire a mousemove event if content is placed under the cursor. See #7778 - // Support: IE <9 - if ( this._mouseMoved ) { - // IE mouseup check - mouseup happened when mouse was out of window - if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { - return this._mouseUp(event); - - // Iframe mouseup check - mouseup occurred in another document - } else if ( !event.which ) { - return this._mouseUp( event ); - } - } - - if ( event.which || event.button ) { - this._mouseMoved = true; - } - - if (this._mouseStarted) { - this._mouseDrag(event); - return event.preventDefault(); - } - - if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { - this._mouseStarted = - (this._mouseStart(this._mouseDownEvent, event) !== false); - (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); - } - - return !this._mouseStarted; - }, - - _mouseUp: function(event) { - this.document - .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) - .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate ); - - if (this._mouseStarted) { - this._mouseStarted = false; - - if (event.target === this._mouseDownEvent.target) { - $.data(event.target, this.widgetName + ".preventClickEvent", true); - } - - this._mouseStop(event); - } - - mouseHandled = false; - return false; - }, - - _mouseDistanceMet: function(event) { - return (Math.max( - Math.abs(this._mouseDownEvent.pageX - event.pageX), - Math.abs(this._mouseDownEvent.pageY - event.pageY) - ) >= this.options.distance - ); - }, - - _mouseDelayMet: function(/* event */) { - return this.mouseDelayMet; - }, - - // These are placeholder methods, to be overriden by extending plugin - _mouseStart: function(/* event */) {}, - _mouseDrag: function(/* event */) {}, - _mouseStop: function(/* event */) {}, - _mouseCapture: function(/* event */) { return true; } -}); - - -/*! - * jQuery UI Position 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/position/ - */ - -(function() { - -$.ui = $.ui || {}; - -var cachedScrollbarWidth, supportsOffsetFractions, - max = Math.max, - abs = Math.abs, - round = Math.round, - rhorizontal = /left|center|right/, - rvertical = /top|center|bottom/, - roffset = /[\+\-]\d+(\.[\d]+)?%?/, - rposition = /^\w+/, - rpercent = /%$/, - _position = $.fn.position; - -function getOffsets( offsets, width, height ) { - return [ - parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), - parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) - ]; -} - -function parseCss( element, property ) { - return parseInt( $.css( element, property ), 10 ) || 0; -} - -function getDimensions( elem ) { - var raw = elem[0]; - if ( raw.nodeType === 9 ) { - return { - width: elem.width(), - height: elem.height(), - offset: { top: 0, left: 0 } - }; - } - if ( $.isWindow( raw ) ) { - return { - width: elem.width(), - height: elem.height(), - offset: { top: elem.scrollTop(), left: elem.scrollLeft() } - }; - } - if ( raw.preventDefault ) { - return { - width: 0, - height: 0, - offset: { top: raw.pageY, left: raw.pageX } - }; - } - return { - width: elem.outerWidth(), - height: elem.outerHeight(), - offset: elem.offset() - }; -} - -$.position = { - scrollbarWidth: function() { - if ( cachedScrollbarWidth !== undefined ) { - return cachedScrollbarWidth; - } - var w1, w2, - div = $( "
" ), - innerDiv = div.children()[0]; - - $( "body" ).append( div ); - w1 = innerDiv.offsetWidth; - div.css( "overflow", "scroll" ); - - w2 = innerDiv.offsetWidth; - - if ( w1 === w2 ) { - w2 = div[0].clientWidth; - } - - div.remove(); - - return (cachedScrollbarWidth = w1 - w2); - }, - getScrollInfo: function( within ) { - var overflowX = within.isWindow || within.isDocument ? "" : - within.element.css( "overflow-x" ), - overflowY = within.isWindow || within.isDocument ? "" : - within.element.css( "overflow-y" ), - hasOverflowX = overflowX === "scroll" || - ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), - hasOverflowY = overflowY === "scroll" || - ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); - return { - width: hasOverflowY ? $.position.scrollbarWidth() : 0, - height: hasOverflowX ? $.position.scrollbarWidth() : 0 - }; - }, - getWithinInfo: function( element ) { - var withinElement = $( element || window ), - isWindow = $.isWindow( withinElement[0] ), - isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; - return { - element: withinElement, - isWindow: isWindow, - isDocument: isDocument, - offset: withinElement.offset() || { left: 0, top: 0 }, - scrollLeft: withinElement.scrollLeft(), - scrollTop: withinElement.scrollTop(), - - // support: jQuery 1.6.x - // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows - width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(), - height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight() - }; - } -}; - -$.fn.position = function( options ) { - if ( !options || !options.of ) { - return _position.apply( this, arguments ); - } - - // make a copy, we don't want to modify arguments - options = $.extend( {}, options ); - - var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, - target = $( options.of ), - within = $.position.getWithinInfo( options.within ), - scrollInfo = $.position.getScrollInfo( within ), - collision = ( options.collision || "flip" ).split( " " ), - offsets = {}; - - dimensions = getDimensions( target ); - if ( target[0].preventDefault ) { - // force left top to allow flipping - options.at = "left top"; - } - targetWidth = dimensions.width; - targetHeight = dimensions.height; - targetOffset = dimensions.offset; - // clone to reuse original targetOffset later - basePosition = $.extend( {}, targetOffset ); - - // force my and at to have valid horizontal and vertical positions - // if a value is missing or invalid, it will be converted to center - $.each( [ "my", "at" ], function() { - var pos = ( options[ this ] || "" ).split( " " ), - horizontalOffset, - verticalOffset; - - if ( pos.length === 1) { - pos = rhorizontal.test( pos[ 0 ] ) ? - pos.concat( [ "center" ] ) : - rvertical.test( pos[ 0 ] ) ? - [ "center" ].concat( pos ) : - [ "center", "center" ]; - } - pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; - pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; - - // calculate offsets - horizontalOffset = roffset.exec( pos[ 0 ] ); - verticalOffset = roffset.exec( pos[ 1 ] ); - offsets[ this ] = [ - horizontalOffset ? horizontalOffset[ 0 ] : 0, - verticalOffset ? verticalOffset[ 0 ] : 0 - ]; - - // reduce to just the positions without the offsets - options[ this ] = [ - rposition.exec( pos[ 0 ] )[ 0 ], - rposition.exec( pos[ 1 ] )[ 0 ] - ]; - }); - - // normalize collision option - if ( collision.length === 1 ) { - collision[ 1 ] = collision[ 0 ]; - } - - if ( options.at[ 0 ] === "right" ) { - basePosition.left += targetWidth; - } else if ( options.at[ 0 ] === "center" ) { - basePosition.left += targetWidth / 2; - } - - if ( options.at[ 1 ] === "bottom" ) { - basePosition.top += targetHeight; - } else if ( options.at[ 1 ] === "center" ) { - basePosition.top += targetHeight / 2; - } - - atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); - basePosition.left += atOffset[ 0 ]; - basePosition.top += atOffset[ 1 ]; - - return this.each(function() { - var collisionPosition, using, - elem = $( this ), - elemWidth = elem.outerWidth(), - elemHeight = elem.outerHeight(), - marginLeft = parseCss( this, "marginLeft" ), - marginTop = parseCss( this, "marginTop" ), - collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, - collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, - position = $.extend( {}, basePosition ), - myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); - - if ( options.my[ 0 ] === "right" ) { - position.left -= elemWidth; - } else if ( options.my[ 0 ] === "center" ) { - position.left -= elemWidth / 2; - } - - if ( options.my[ 1 ] === "bottom" ) { - position.top -= elemHeight; - } else if ( options.my[ 1 ] === "center" ) { - position.top -= elemHeight / 2; - } - - position.left += myOffset[ 0 ]; - position.top += myOffset[ 1 ]; - - // if the browser doesn't support fractions, then round for consistent results - if ( !supportsOffsetFractions ) { - position.left = round( position.left ); - position.top = round( position.top ); - } - - collisionPosition = { - marginLeft: marginLeft, - marginTop: marginTop - }; - - $.each( [ "left", "top" ], function( i, dir ) { - if ( $.ui.position[ collision[ i ] ] ) { - $.ui.position[ collision[ i ] ][ dir ]( position, { - targetWidth: targetWidth, - targetHeight: targetHeight, - elemWidth: elemWidth, - elemHeight: elemHeight, - collisionPosition: collisionPosition, - collisionWidth: collisionWidth, - collisionHeight: collisionHeight, - offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], - my: options.my, - at: options.at, - within: within, - elem: elem - }); - } - }); - - if ( options.using ) { - // adds feedback as second argument to using callback, if present - using = function( props ) { - var left = targetOffset.left - position.left, - right = left + targetWidth - elemWidth, - top = targetOffset.top - position.top, - bottom = top + targetHeight - elemHeight, - feedback = { - target: { - element: target, - left: targetOffset.left, - top: targetOffset.top, - width: targetWidth, - height: targetHeight - }, - element: { - element: elem, - left: position.left, - top: position.top, - width: elemWidth, - height: elemHeight - }, - horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", - vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" - }; - if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { - feedback.horizontal = "center"; - } - if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { - feedback.vertical = "middle"; - } - if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { - feedback.important = "horizontal"; - } else { - feedback.important = "vertical"; - } - options.using.call( this, props, feedback ); - }; - } - - elem.offset( $.extend( position, { using: using } ) ); - }); -}; - -$.ui.position = { - fit: { - left: function( position, data ) { - var within = data.within, - withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, - outerWidth = within.width, - collisionPosLeft = position.left - data.collisionPosition.marginLeft, - overLeft = withinOffset - collisionPosLeft, - overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, - newOverRight; - - // element is wider than within - if ( data.collisionWidth > outerWidth ) { - // element is initially over the left side of within - if ( overLeft > 0 && overRight <= 0 ) { - newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; - position.left += overLeft - newOverRight; - // element is initially over right side of within - } else if ( overRight > 0 && overLeft <= 0 ) { - position.left = withinOffset; - // element is initially over both left and right sides of within - } else { - if ( overLeft > overRight ) { - position.left = withinOffset + outerWidth - data.collisionWidth; - } else { - position.left = withinOffset; - } - } - // too far left -> align with left edge - } else if ( overLeft > 0 ) { - position.left += overLeft; - // too far right -> align with right edge - } else if ( overRight > 0 ) { - position.left -= overRight; - // adjust based on position and margin - } else { - position.left = max( position.left - collisionPosLeft, position.left ); - } - }, - top: function( position, data ) { - var within = data.within, - withinOffset = within.isWindow ? within.scrollTop : within.offset.top, - outerHeight = data.within.height, - collisionPosTop = position.top - data.collisionPosition.marginTop, - overTop = withinOffset - collisionPosTop, - overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, - newOverBottom; - - // element is taller than within - if ( data.collisionHeight > outerHeight ) { - // element is initially over the top of within - if ( overTop > 0 && overBottom <= 0 ) { - newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; - position.top += overTop - newOverBottom; - // element is initially over bottom of within - } else if ( overBottom > 0 && overTop <= 0 ) { - position.top = withinOffset; - // element is initially over both top and bottom of within - } else { - if ( overTop > overBottom ) { - position.top = withinOffset + outerHeight - data.collisionHeight; - } else { - position.top = withinOffset; - } - } - // too far up -> align with top - } else if ( overTop > 0 ) { - position.top += overTop; - // too far down -> align with bottom edge - } else if ( overBottom > 0 ) { - position.top -= overBottom; - // adjust based on position and margin - } else { - position.top = max( position.top - collisionPosTop, position.top ); - } - } - }, - flip: { - left: function( position, data ) { - var within = data.within, - withinOffset = within.offset.left + within.scrollLeft, - outerWidth = within.width, - offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, - collisionPosLeft = position.left - data.collisionPosition.marginLeft, - overLeft = collisionPosLeft - offsetLeft, - overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, - myOffset = data.my[ 0 ] === "left" ? - -data.elemWidth : - data.my[ 0 ] === "right" ? - data.elemWidth : - 0, - atOffset = data.at[ 0 ] === "left" ? - data.targetWidth : - data.at[ 0 ] === "right" ? - -data.targetWidth : - 0, - offset = -2 * data.offset[ 0 ], - newOverRight, - newOverLeft; - - if ( overLeft < 0 ) { - newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; - if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { - position.left += myOffset + atOffset + offset; - } - } else if ( overRight > 0 ) { - newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; - if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { - position.left += myOffset + atOffset + offset; - } - } - }, - top: function( position, data ) { - var within = data.within, - withinOffset = within.offset.top + within.scrollTop, - outerHeight = within.height, - offsetTop = within.isWindow ? within.scrollTop : within.offset.top, - collisionPosTop = position.top - data.collisionPosition.marginTop, - overTop = collisionPosTop - offsetTop, - overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, - top = data.my[ 1 ] === "top", - myOffset = top ? - -data.elemHeight : - data.my[ 1 ] === "bottom" ? - data.elemHeight : - 0, - atOffset = data.at[ 1 ] === "top" ? - data.targetHeight : - data.at[ 1 ] === "bottom" ? - -data.targetHeight : - 0, - offset = -2 * data.offset[ 1 ], - newOverTop, - newOverBottom; - if ( overTop < 0 ) { - newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; - if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { - position.top += myOffset + atOffset + offset; - } - } else if ( overBottom > 0 ) { - newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; - if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { - position.top += myOffset + atOffset + offset; - } - } - } - }, - flipfit: { - left: function() { - $.ui.position.flip.left.apply( this, arguments ); - $.ui.position.fit.left.apply( this, arguments ); - }, - top: function() { - $.ui.position.flip.top.apply( this, arguments ); - $.ui.position.fit.top.apply( this, arguments ); - } - } -}; - -// fraction support test -(function() { - var testElement, testElementParent, testElementStyle, offsetLeft, i, - body = document.getElementsByTagName( "body" )[ 0 ], - div = document.createElement( "div" ); - - //Create a "fake body" for testing based on method used in jQuery.support - testElement = document.createElement( body ? "div" : "body" ); - testElementStyle = { - visibility: "hidden", - width: 0, - height: 0, - border: 0, - margin: 0, - background: "none" - }; - if ( body ) { - $.extend( testElementStyle, { - position: "absolute", - left: "-1000px", - top: "-1000px" - }); - } - for ( i in testElementStyle ) { - testElement.style[ i ] = testElementStyle[ i ]; - } - testElement.appendChild( div ); - testElementParent = body || document.documentElement; - testElementParent.insertBefore( testElement, testElementParent.firstChild ); - - div.style.cssText = "position: absolute; left: 10.7432222px;"; - - offsetLeft = $( div ).offset().left; - supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11; - - testElement.innerHTML = ""; - testElementParent.removeChild( testElement ); -})(); - -})(); - -var position = $.ui.position; - - -/*! - * jQuery UI Draggable 1.11.4 - * http://jqueryui.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - * - * http://api.jqueryui.com/draggable/ - */ - - -$.widget("ui.draggable", $.ui.mouse, { - version: "1.11.4", - widgetEventPrefix: "drag", - options: { - addClasses: true, - appendTo: "parent", - axis: false, - connectToSortable: false, - containment: false, - cursor: "auto", - cursorAt: false, - grid: false, - handle: false, - helper: "original", - iframeFix: false, - opacity: false, - refreshPositions: false, - revert: false, - revertDuration: 500, - scope: "default", - scroll: true, - scrollSensitivity: 20, - scrollSpeed: 20, - snap: false, - snapMode: "both", - snapTolerance: 20, - stack: false, - zIndex: false, - - // callbacks - drag: null, - start: null, - stop: null - }, - _create: function() { - - if ( this.options.helper === "original" ) { - this._setPositionRelative(); - } - if (this.options.addClasses){ - this.element.addClass("ui-draggable"); - } - if (this.options.disabled){ - this.element.addClass("ui-draggable-disabled"); - } - this._setHandleClassName(); - - this._mouseInit(); - }, - - _setOption: function( key, value ) { - this._super( key, value ); - if ( key === "handle" ) { - this._removeHandleClassName(); - this._setHandleClassName(); - } - }, - - _destroy: function() { - if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { - this.destroyOnClear = true; - return; - } - this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); - this._removeHandleClassName(); - this._mouseDestroy(); - }, - - _mouseCapture: function(event) { - var o = this.options; - - this._blurActiveElement( event ); - - // among others, prevent a drag on a resizable-handle - if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { - return false; - } - - //Quit if we're not on a valid handle - this.handle = this._getHandle(event); - if (!this.handle) { - return false; - } - - this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); - - return true; - - }, - - _blockFrames: function( selector ) { - this.iframeBlocks = this.document.find( selector ).map(function() { - var iframe = $( this ); - - return $( "
" ) - .css( "position", "absolute" ) - .appendTo( iframe.parent() ) - .outerWidth( iframe.outerWidth() ) - .outerHeight( iframe.outerHeight() ) - .offset( iframe.offset() )[ 0 ]; - }); - }, - - _unblockFrames: function() { - if ( this.iframeBlocks ) { - this.iframeBlocks.remove(); - delete this.iframeBlocks; - } - }, - - _blurActiveElement: function( event ) { - var document = this.document[ 0 ]; - - // Only need to blur if the event occurred on the draggable itself, see #10527 - if ( !this.handleElement.is( event.target ) ) { - return; - } - - // support: IE9 - // IE9 throws an "Unspecified error" accessing document.activeElement from an