From fb60cf0cddd82da45a17b9962d9011fb377118e2 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Mon, 1 Dec 2014 17:45:44 +0100 Subject: [PATCH 1/4] Adding front for gitlab and bitbucket --- app/coffee/app.coffee | 4 + app/coffee/modules/admin/third-parties.coffee | 181 ++++++++++++++++++ app/coffee/modules/base.coffee | 2 + .../admin-third-parties-bitbucket.jade | 36 ++++ app/partials/admin-third-parties-gitlab.jade | 35 ++++ .../modules/admin-submenu-third-parties.jade | 8 + 6 files changed, 266 insertions(+) create mode 100644 app/partials/admin-third-parties-bitbucket.jade create mode 100644 app/partials/admin-third-parties-gitlab.jade diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 1a5794c5..51dd695d 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -100,6 +100,10 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven {templateUrl: "/partials/admin-roles.html"}) $routeProvider.when("/project/:pslug/admin/third-parties/github", {templateUrl: "/partials/admin-third-parties-github.html"}) + $routeProvider.when("/project/:pslug/admin/third-parties/gitlab", + {templateUrl: "/partials/admin-third-parties-gitlab.html"}) + $routeProvider.when("/project/:pslug/admin/third-parties/bitbucket", + {templateUrl: "/partials/admin-third-parties-bitbucket.html"}) # User settings $routeProvider.when("/project/:pslug/user-settings/user-profile", diff --git a/app/coffee/modules/admin/third-parties.coffee b/app/coffee/modules/admin/third-parties.coffee index 842652e8..a341721a 100644 --- a/app/coffee/modules/admin/third-parties.coffee +++ b/app/coffee/modules/admin/third-parties.coffee @@ -78,6 +78,114 @@ class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi module.controller("GithubController", GithubController) + +############################################################################# +## Gitlab Controller +############################################################################# + +class GitlabController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin) + @.$inject = [ + "$scope", + "$tgRepo", + "$tgResources", + "$routeParams", + "$appTitle" + ] + + constructor: (@scope, @repo, @rs, @params, @appTitle) -> + bindMethods(@) + + @scope.sectionName = "Gitlab" #i18n + @scope.project = {} + @scope.anyComputableRole = true + + promise = @.loadInitialData() + + promise.then () => + @appTitle.set("Gitlab - " + @scope.project.name) + + promise.then null, @.onInitialDataError.bind(@) + + @scope.$on "project:modules:reload", => + @.loadModules() + + loadModules: -> + return @rs.modules.list(@scope.projectId, "gitlab").then (gitlab) => + @scope.gitlab = gitlab + + loadProject: -> + return @rs.projects.get(@scope.projectId).then (project) => + @scope.project = project + @scope.$emit('project:loaded', project) + @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) + + return project + + loadInitialData: -> + promise = @repo.resolve({pslug: @params.pslug}).then (data) => + @scope.projectId = data.project + return data + + return promise.then(=> @.loadProject()) + .then(=> @.loadModules()) + + +module.controller("GitlabController", GitlabController) + + +############################################################################# +## Bitbucket Controller +############################################################################# + +class BitbucketController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin) + @.$inject = [ + "$scope", + "$tgRepo", + "$tgResources", + "$routeParams", + "$appTitle" + ] + + constructor: (@scope, @repo, @rs, @params, @appTitle) -> + bindMethods(@) + + @scope.sectionName = "Bitbucket" #i18n + @scope.project = {} + @scope.anyComputableRole = true + + promise = @.loadInitialData() + + promise.then () => + @appTitle.set("Bitbucket - " + @scope.project.name) + + promise.then null, @.onInitialDataError.bind(@) + + @scope.$on "project:modules:reload", => + @.loadModules() + + loadModules: -> + return @rs.modules.list(@scope.projectId, "bitbucket").then (bitbucket) => + @scope.bitbucket = bitbucket + + loadProject: -> + return @rs.projects.get(@scope.projectId).then (project) => + @scope.project = project + @scope.$emit('project:loaded', project) + @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) + + return project + + loadInitialData: -> + promise = @repo.resolve({pslug: @params.pslug}).then (data) => + @scope.projectId = data.project + return data + + return promise.then(=> @.loadProject()) + .then(=> @.loadModules()) + +module.controller("BitbucketController", BitbucketController) + + SelectInputText = -> link = ($scope, $el, $attrs) -> $el.on "click", ".select-input-content", () -> @@ -88,6 +196,7 @@ SelectInputText = -> module.directive("tgSelectInputText", SelectInputText) + ############################################################################# ## GithubWebhooks Directive ############################################################################# @@ -121,3 +230,75 @@ GithubWebhooksDirective = ($repo, $confirm, $loading) -> return {link:link} module.directive("tgGithubWebhooks", ["$tgRepo", "$tgConfirm", "$tgLoading", GithubWebhooksDirective]) + + +############################################################################# +## GitlabWebhooks Directive +############################################################################# + +GitlabWebhooksDirective = ($repo, $confirm, $loading) -> + link = ($scope, $el, $attrs) -> + form = $el.find("form").checksley({"onlyOneErrorElement": true}) + submit = debounce 2000, (event) => + event.preventDefault() + + return if not form.validate() + + $loading.start(submitButton) + + promise = $repo.saveAttribute($scope.gitlab, "gitlab") + promise.then -> + $loading.finish(submitButton) + $confirm.notify("success") + $scope.$emit("project:modules:reload") + + promise.then null, (data) -> + $loading.finish(submitButton) + form.setErrors(data) + if data._error_message + $confirm.notify("error", data._error_message) + + submitButton = $el.find(".submit-button") + + $el.on "submit", "form", submit + $el.on "click", ".submit-button", submit + + return {link:link} + +module.directive("tgGitlabWebhooks", ["$tgRepo", "$tgConfirm", "$tgLoading", GitlabWebhooksDirective]) + + +############################################################################# +## BitbucketWebhooks Directive +############################################################################# + +BitbucketWebhooksDirective = ($repo, $confirm, $loading) -> + link = ($scope, $el, $attrs) -> + form = $el.find("form").checksley({"onlyOneErrorElement": true}) + submit = debounce 2000, (event) => + event.preventDefault() + + return if not form.validate() + + $loading.start(submitButton) + + promise = $repo.saveAttribute($scope.bitbucket, "bitbucket") + promise.then -> + $loading.finish(submitButton) + $confirm.notify("success") + $scope.$emit("project:modules:reload") + + promise.then null, (data) -> + $loading.finish(submitButton) + form.setErrors(data) + if data._error_message + $confirm.notify("error", data._error_message) + + submitButton = $el.find(".submit-button") + + $el.on "submit", "form", submit + $el.on "click", ".submit-button", submit + + return {link:link} + +module.directive("tgBitbucketWebhooks", ["$tgRepo", "$tgConfirm", "$tgLoading", BitbucketWebhooksDirective]) diff --git a/app/coffee/modules/base.coffee b/app/coffee/modules/base.coffee index 877bc907..a3d8c812 100644 --- a/app/coffee/modules/base.coffee +++ b/app/coffee/modules/base.coffee @@ -93,6 +93,8 @@ urls = { "project-admin-memberships": "/project/:project/admin/memberships" "project-admin-roles": "/project/:project/admin/roles" "project-admin-third-parties-github": "/project/:project/admin/third-parties/github" + "project-admin-third-parties-gitlab": "/project/:project/admin/third-parties/gitlab" + "project-admin-third-parties-bitbucket": "/project/:project/admin/third-parties/bitbucket" # User settings "user-settings-user-profile": "/project/:project/user-settings/user-profile" diff --git a/app/partials/admin-third-parties-bitbucket.jade b/app/partials/admin-third-parties-bitbucket.jade new file mode 100644 index 00000000..4bb006ee --- /dev/null +++ b/app/partials/admin-third-parties-bitbucket.jade @@ -0,0 +1,36 @@ +block head + title Taiga Your agile, free, and open source project management tool + +block content + div.wrapper.roles(tg-bitbucket-webhooks, ng-controller="BitbucketController as ctrl", + ng-init="section='admin'") + sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties") + include views/modules/admin-menu + sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-bitbucket") + include views/modules/admin-submenu-third-parties + + section.main.admin-common.admin-third-parties + include views/components/mainTitle + + form + fieldset + label(for="secret-key") Secret key + input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="Secret key", id="secret-key") + + fieldset + .select-input-text(tg-select-input-text) + div + label(for="payload-url") Payload URL + .field-with-option + input(type="text", ng-model="bitbucket.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url") + .option-wrapper.select-input-content + .icon.icon-copy + .help-copy Copy to clipboard: Ctrl+C + + button(type="submit", class="hidden") + a.button.button-green.submit-button(href="", title="Save") Save + + + a.help-button(href="https://taiga.io/support/bitbucket-integration/", target="_blank") + span.icon.icon-help + span Do you need help? Check out our support page! diff --git a/app/partials/admin-third-parties-gitlab.jade b/app/partials/admin-third-parties-gitlab.jade new file mode 100644 index 00000000..1aa9e78e --- /dev/null +++ b/app/partials/admin-third-parties-gitlab.jade @@ -0,0 +1,35 @@ +block head + title Taiga Your agile, free, and open source project management tool + +block content + div.wrapper.roles(tg-gitlab-webhooks, ng-controller="GitlabController as ctrl", + ng-init="section='admin'") + sidebar.menu-secondary.sidebar(tg-admin-navigation="third-parties") + include views/modules/admin-menu + sidebar.menu-tertiary.sidebar(tg-admin-navigation="third-parties-gitlab") + include views/modules/admin-submenu-third-parties + + section.main.admin-common.admin-third-parties + include views/components/mainTitle + + form + fieldset + label(for="secret-key") Secret key + input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="Secret key", id="secret-key") + + fieldset + .select-input-text(tg-select-input-text) + div + label(for="payload-url") Payload URL + .field-with-option + input(type="text", ng-model="gitlab.webhooks_url", name="payload-url", readonly="readonly", placeholder="Payload URL", id="payload-url") + .option-wrapper.select-input-content + .icon.icon-copy + .help-copy Copy to clipboard: Ctrl+C + + button(type="submit", class="hidden") + a.button.button-green.submit-button(href="", title="Save") Save + + a.help-button(href="https://taiga.io/support/gitlab-integration/", target="_blank") + span.icon.icon-help + span Do you need help? Check out our support page! diff --git a/app/partials/views/modules/admin-submenu-third-parties.jade b/app/partials/views/modules/admin-submenu-third-parties.jade index 95746408..f491ebb1 100644 --- a/app/partials/views/modules/admin-submenu-third-parties.jade +++ b/app/partials/views/modules/admin-submenu-third-parties.jade @@ -8,3 +8,11 @@ section.admin-submenu a(href="", tg-nav="project-admin-third-parties-github:project=project.slug") span.title Github span.icon.icon-arrow-right + li#adminmenu-third-parties-gitlab + a(href="", tg-nav="project-admin-third-parties-gitlab:project=project.slug") + span.title Gitlab + span.icon.icon-arrow-right + li#adminmenu-third-parties-bitbucket + a(href="", tg-nav="project-admin-third-parties-bitbucket:project=project.slug") + span.title Bitbucket + span.icon.icon-arrow-right From e3b223878dd967c64130ec779adc81b85be0c7e9 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 2 Dec 2014 14:21:15 +0100 Subject: [PATCH 2/4] Adding valid origin ip directive and data --- app/coffee/modules/admin/third-parties.coffee | 21 +++++++++++++++++++ .../admin-third-parties-bitbucket.jade | 4 ++++ app/partials/admin-third-parties-gitlab.jade | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/app/coffee/modules/admin/third-parties.coffee b/app/coffee/modules/admin/third-parties.coffee index a341721a..a515acec 100644 --- a/app/coffee/modules/admin/third-parties.coffee +++ b/app/coffee/modules/admin/third-parties.coffee @@ -302,3 +302,24 @@ BitbucketWebhooksDirective = ($repo, $confirm, $loading) -> return {link:link} module.directive("tgBitbucketWebhooks", ["$tgRepo", "$tgConfirm", "$tgLoading", BitbucketWebhooksDirective]) + + +############################################################################# +## Valid Origin IP's Directive +############################################################################# +ValidOriginIpsDirective = -> + link = ($scope, $el, $attrs, $ngModel) -> + $ngModel.$parsers.push (value) -> + value = $.trim(value) + if value == "" + return [] + + return value.split(",") + + return { + link: link + restrict: "EA" + require: "ngModel" + } + +module.directive("tgValidOriginIps", ValidOriginIpsDirective) diff --git a/app/partials/admin-third-parties-bitbucket.jade b/app/partials/admin-third-parties-bitbucket.jade index 4bb006ee..dfde8acb 100644 --- a/app/partials/admin-third-parties-bitbucket.jade +++ b/app/partials/admin-third-parties-bitbucket.jade @@ -13,6 +13,10 @@ block content include views/components/mainTitle form + fieldset + label(for="valid-origin-ips") Valid origin ips (separated by ,)
Bitbucket requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation. + input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="bitbucket.valid_origin_ips", placeholder="Valid origin ips", id="valid-origin-ips") + fieldset label(for="secret-key") Secret key input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="Secret key", id="secret-key") diff --git a/app/partials/admin-third-parties-gitlab.jade b/app/partials/admin-third-parties-gitlab.jade index 1aa9e78e..1e0af9cf 100644 --- a/app/partials/admin-third-parties-gitlab.jade +++ b/app/partials/admin-third-parties-gitlab.jade @@ -13,6 +13,10 @@ block content include views/components/mainTitle form + fieldset + label(for="valid-origin-ips") Valid origin ips (separated by ,)
Gitlab requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation. + input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="gitlab.valid_origin_ips", placeholder="Valid origin ips", id="valid-origin-ips") + fieldset label(for="secret-key") Secret key input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="Secret key", id="secret-key") From 0fb087e8c7719cea750d5d50faa0e04eb329b75e Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 2 Dec 2014 14:22:29 +0100 Subject: [PATCH 3/4] Removing unnecesary anyComputableRole --- app/coffee/modules/admin/third-parties.coffee | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/coffee/modules/admin/third-parties.coffee b/app/coffee/modules/admin/third-parties.coffee index a515acec..fc7abc4c 100644 --- a/app/coffee/modules/admin/third-parties.coffee +++ b/app/coffee/modules/admin/third-parties.coffee @@ -46,7 +46,6 @@ class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @scope.sectionName = "Github" #i18n @scope.project = {} - @scope.anyComputableRole = true promise = @.loadInitialData() @@ -63,8 +62,6 @@ class GithubController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.$emit('project:loaded', project) - @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) - return project loadInitialData: -> @@ -97,8 +94,6 @@ class GitlabController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @scope.sectionName = "Gitlab" #i18n @scope.project = {} - @scope.anyComputableRole = true - promise = @.loadInitialData() promise.then () => @@ -117,8 +112,6 @@ class GitlabController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.$emit('project:loaded', project) - @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) - return project loadInitialData: -> @@ -151,8 +144,6 @@ class BitbucketController extends mixOf(taiga.Controller, taiga.PageMixin, taiga @scope.sectionName = "Bitbucket" #i18n @scope.project = {} - @scope.anyComputableRole = true - promise = @.loadInitialData() promise.then () => @@ -171,8 +162,6 @@ class BitbucketController extends mixOf(taiga.Controller, taiga.PageMixin, taiga return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.$emit('project:loaded', project) - @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) - return project loadInitialData: -> From aa71dcc231cdda6291a22ad145b9bb9647af920e Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 2 Dec 2014 14:57:49 +0100 Subject: [PATCH 4/4] Changing field order --- app/partials/admin-third-parties-bitbucket.jade | 8 ++++---- app/partials/admin-third-parties-gitlab.jade | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/partials/admin-third-parties-bitbucket.jade b/app/partials/admin-third-parties-bitbucket.jade index dfde8acb..7e3ca8f8 100644 --- a/app/partials/admin-third-parties-bitbucket.jade +++ b/app/partials/admin-third-parties-bitbucket.jade @@ -13,10 +13,6 @@ block content include views/components/mainTitle form - fieldset - label(for="valid-origin-ips") Valid origin ips (separated by ,)
Bitbucket requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation. - input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="bitbucket.valid_origin_ips", placeholder="Valid origin ips", id="valid-origin-ips") - fieldset label(for="secret-key") Secret key input(type="text", name="secret-key", ng-model="bitbucket.secret", placeholder="Secret key", id="secret-key") @@ -30,6 +26,10 @@ block content .option-wrapper.select-input-content .icon.icon-copy .help-copy Copy to clipboard: Ctrl+C + + fieldset + label(for="valid-origin-ips") Valid origin ips (separated by ,) + input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="bitbucket.valid_origin_ips", placeholder="Bitbucket requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation.", id="valid-origin-ips") button(type="submit", class="hidden") a.button.button-green.submit-button(href="", title="Save") Save diff --git a/app/partials/admin-third-parties-gitlab.jade b/app/partials/admin-third-parties-gitlab.jade index 1e0af9cf..c85b2165 100644 --- a/app/partials/admin-third-parties-gitlab.jade +++ b/app/partials/admin-third-parties-gitlab.jade @@ -13,10 +13,6 @@ block content include views/components/mainTitle form - fieldset - label(for="valid-origin-ips") Valid origin ips (separated by ,)
Gitlab requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation. - input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="gitlab.valid_origin_ips", placeholder="Valid origin ips", id="valid-origin-ips") - fieldset label(for="secret-key") Secret key input(type="text", name="secret-key", ng-model="gitlab.secret", placeholder="Secret key", id="secret-key") @@ -31,6 +27,10 @@ block content .icon.icon-copy .help-copy Copy to clipboard: Ctrl+C + fieldset + label(for="valid-origin-ips") Valid origin ips (separated by ,) + input(type="text", name="valid-origin-ips", tg-valid-origin-ips, ng-model="gitlab.valid_origin_ips", placeholder="Gitlab requests are not signed so the best way of verifying the origin is by IP. If the field is empty there will be no IP validation.", id="valid-origin-ips") + button(type="submit", class="hidden") a.button.button-green.submit-button(href="", title="Save") Save