* Let GitHub integration show changes in a separate tab
* added new github integration icons to icon font
* add tab content: working tab-header and copy-menu
* modernise github_integrations ruby code
* refactored some code to be more modern ruby (if wrote most of it 7
years ago and couldn't look at some parts without squinting too much)
* make some intended-to-be-private module methods actually private
* fixed all rubocop errors in the /modules/github_integration
* re-organized tests a little
* gave our rubocop.yml some RSpec-related defaults -- happy to discuss
these, but I think we can live with these as a good starting point
👆 all without actually (intentionally) changing the behaviour
* removed dead angular template code
* codeclimate found more things than rubocop :)
* removed create-pr-button since we decided against implementing that feature
* added missing translations
* properly cache the github related part of the wp api
* lower case pull requests in translations
* fix specs
pull/9151/head
parent
ebbe5ec584
commit
a46de71009
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 148 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,51 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 the OpenProject GmbH |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See docs/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
en: |
||||||
|
js: |
||||||
|
github_integration: |
||||||
|
work_packages: |
||||||
|
tab_name: "GitHub" |
||||||
|
tab_header: |
||||||
|
title: "Pull Requests" |
||||||
|
copy_menu: |
||||||
|
label: Git |
||||||
|
description: Copy important git content to clipboard |
||||||
|
git_actions: |
||||||
|
branch: Branch |
||||||
|
branch_help: Copy the default branch name. |
||||||
|
message: Message |
||||||
|
message_help: Copy the default commit message. |
||||||
|
cmd: Command |
||||||
|
cmd_help: Copy a shell command which creates a new branch and an empty commit using the default branch name and commit message. |
||||||
|
title: Copy to Clipboard |
||||||
|
copy_button_help: Copy to clipboard |
||||||
|
copy_success: ✅ Copied! |
||||||
|
copy_error: ❌ Copy failed! |
||||||
|
tab_prs: |
||||||
|
empty: There are no pull requests linked yet. Link an existing PR by using the code <code>OP#%{wp_id}</code> in the PR description or create a new PR. |
@ -0,0 +1,120 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import copy from 'copy-text-to-clipboard'; |
||||||
|
import {Component, Inject, Input} from '@angular/core'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import {I18nService} from 'core-app/modules/common/i18n/i18n.service'; |
||||||
|
import { GitActionsService} from '../git-actions/git-actions.service'; |
||||||
|
import { OPContextMenuComponent } from 'core-app/components/op-context-menu/op-context-menu.component'; |
||||||
|
import { OpContextMenuLocalsMap, OpContextMenuLocalsToken } from 'core-app/components/op-context-menu/op-context-menu.types'; |
||||||
|
|
||||||
|
interface Tab { |
||||||
|
label:string, |
||||||
|
help:string, |
||||||
|
selected:boolean, |
||||||
|
lines:number, |
||||||
|
textToCopy: ()=>string |
||||||
|
} |
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: 'git-actions-menu', |
||||||
|
templateUrl: './git-actions-menu.template.html', |
||||||
|
styleUrls: [ |
||||||
|
'./styles/git-actions-menu.sass' |
||||||
|
] |
||||||
|
}) |
||||||
|
export class GitActionsMenuComponent extends OPContextMenuComponent { |
||||||
|
@Input() public workPackage:WorkPackageResource; |
||||||
|
|
||||||
|
public text = { |
||||||
|
title: this.I18n.t('js.github_integration.tab_header.git_actions.title'), |
||||||
|
copyButtonHelpText: this.I18n.t('js.github_integration.tab_header.git_actions.copy_button_help'), |
||||||
|
copyResult: { |
||||||
|
success: this.I18n.t('js.github_integration.tab_header.git_actions.copy_success'), |
||||||
|
error: this.I18n.t('js.github_integration.tab_header.git_actions.copy_error') |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public lastCopyResult:string = this.text.copyResult.success; |
||||||
|
public showCopyResult:boolean = false; |
||||||
|
|
||||||
|
public tabs:Tab[] = [ |
||||||
|
{ |
||||||
|
label: this.I18n.t('js.github_integration.tab_header.git_actions.branch'), |
||||||
|
help: this.I18n.t('js.github_integration.tab_header.git_actions.branch_help'), |
||||||
|
selected: true, |
||||||
|
lines: 1, |
||||||
|
textToCopy: () => this.gitActions.branchName(this.workPackage) |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: this.I18n.t('js.github_integration.tab_header.git_actions.message'), |
||||||
|
help: this.I18n.t('js.github_integration.tab_header.git_actions.message_help'), |
||||||
|
selected: false, |
||||||
|
lines: 6, |
||||||
|
textToCopy: () => this.gitActions.commitMessage(this.workPackage) |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: this.I18n.t('js.github_integration.tab_header.git_actions.cmd'), |
||||||
|
help: this.I18n.t('js.github_integration.tab_header.git_actions.cmd_help'), |
||||||
|
selected: false, |
||||||
|
lines: 6, |
||||||
|
textToCopy: () => this.gitActions.gitCommand(this.workPackage) |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
constructor(@Inject(OpContextMenuLocalsToken) |
||||||
|
public locals:OpContextMenuLocalsMap, |
||||||
|
readonly I18n:I18nService, |
||||||
|
readonly gitActions:GitActionsService) { |
||||||
|
super(locals); |
||||||
|
this.workPackage = this.locals.workPackage; |
||||||
|
} |
||||||
|
|
||||||
|
public selectedTab():Tab { |
||||||
|
const selectedTabs = this.tabs.filter((tab)=>tab.selected); |
||||||
|
return(selectedTabs[0] || this.tabs[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public selectTab(tab:Tab) { |
||||||
|
this.tabs.forEach(tab => tab.selected = false); |
||||||
|
tab.selected = true; |
||||||
|
} |
||||||
|
|
||||||
|
public onCopyButtonClick() { |
||||||
|
const success = copy(this.selectedTab().textToCopy()) |
||||||
|
|
||||||
|
if (success) { |
||||||
|
this.lastCopyResult = this.text.copyResult.success; |
||||||
|
} else { |
||||||
|
this.lastCopyResult = this.text.copyResult.error; |
||||||
|
} |
||||||
|
this.showCopyResult = true; |
||||||
|
window.setTimeout(() => { this.showCopyResult = false;}, 2000); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import {OpContextMenuItem} from 'core-components/op-context-menu/op-context-menu.types'; |
||||||
|
import {OPContextMenuService} from 'core-components/op-context-menu/op-context-menu.service'; |
||||||
|
import {Directive, ElementRef, Input} from '@angular/core'; |
||||||
|
import {OpContextMenuTrigger} from 'core-components/op-context-menu/handlers/op-context-menu-trigger.directive'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import {GitActionsMenuComponent} from './git-actions-menu.component'; |
||||||
|
|
||||||
|
@Directive({ |
||||||
|
selector: '[gitActionsCopyDropdown]' |
||||||
|
}) |
||||||
|
export class GitActionsMenuDirective extends OpContextMenuTrigger { |
||||||
|
@Input('gitActionsCopyDropdown-workPackage') public workPackage:WorkPackageResource; |
||||||
|
|
||||||
|
constructor(readonly elementRef:ElementRef, |
||||||
|
readonly opContextMenu:OPContextMenuService) { |
||||||
|
super(elementRef, opContextMenu); |
||||||
|
} |
||||||
|
|
||||||
|
protected open(evt:JQuery.TriggeredEvent) { |
||||||
|
this.opContextMenu.show(this, evt, GitActionsMenuComponent); |
||||||
|
} |
||||||
|
|
||||||
|
public get locals():{ showAnchorRight?:boolean, contextMenuId?:string, items:OpContextMenuItem[], workPackage:WorkPackageResource } { |
||||||
|
return { |
||||||
|
workPackage: this.workPackage, |
||||||
|
contextMenuId: 'github-integration-git-actions-menu', |
||||||
|
items: [] |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,24 @@ |
|||||||
|
<div class="git-actions-menu dropdown-relative dropdown -overflow-in-view dropdown-anchor-right"> |
||||||
|
<h3 class="title"> |
||||||
|
<op-icon icon-classes="button--icon icon-console-light"></op-icon> |
||||||
|
{{text.title}} |
||||||
|
</h3> |
||||||
|
<ul class="tabrow"> |
||||||
|
<!-- The hrefs with empty URLs are necessary for IE10 to focus these links |
||||||
|
properly. Thus, don't remove the hrefs or the empty URLs! --> |
||||||
|
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.selected]="tab.selected"> |
||||||
|
<a href="" [textContent]="tab.label"></a> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div class="copy-wrapper"> |
||||||
|
<textarea class="copy-content" [textContent]="selectedTab().textToCopy()" [style.height.em]="selectedTab().lines" readonly="true"></textarea> |
||||||
|
<button class="button copy-button" |
||||||
|
type="button" |
||||||
|
[attr.aria-label]="text.copyButtonHelpText" |
||||||
|
(click)="onCopyButtonClick()"> |
||||||
|
<op-icon icon-classes="button--icon icon-copy"></op-icon> |
||||||
|
</button> |
||||||
|
<div class="copy-result-message" *ngIf="showCopyResult" [textContent]="lastCopyResult"></div> |
||||||
|
</div> |
||||||
|
<div class="help-text" [textContent]="selectedTab().help"></div> |
||||||
|
</div> |
@ -0,0 +1,68 @@ |
|||||||
|
.git-actions-menu |
||||||
|
background-color: var(--body-background) |
||||||
|
border: var(--content-default-border-width) solid var(--content-default-border-color) |
||||||
|
padding: 1rem |
||||||
|
min-width: 25rem |
||||||
|
box-shadow: .1em .1em .4em rgba(0,0,0,0.1) |
||||||
|
|
||||||
|
.tabrow |
||||||
|
margin-bottom: 0.5rem |
||||||
|
|
||||||
|
.copy-wrapper |
||||||
|
width: 100% |
||||||
|
position: relative |
||||||
|
margin-bottom: 1rem |
||||||
|
|
||||||
|
.copy-content |
||||||
|
width: calc(100% - 2.2em) |
||||||
|
// the min-height should be the size of the copy-icon, which is the sum of: |
||||||
|
// 2 * button padding (0.65em) |
||||||
|
// font-size of the icon (0.9em) |
||||||
|
// 1px where I don't know where it comes from |
||||||
|
min-height: calc(2 * 0.65em + 0.9em + 1px) |
||||||
|
border-radius: 2px 0 0 2px |
||||||
|
padding: 0.65em |
||||||
|
color: var(--gray-dark) |
||||||
|
white-space: pre |
||||||
|
resize: none |
||||||
|
font-size: 1rem |
||||||
|
display: inline-block |
||||||
|
|
||||||
|
.copy-button |
||||||
|
margin: 0 |
||||||
|
border: 1px solid #ccc |
||||||
|
border-radius: 0 2px 2px 0 |
||||||
|
vertical-align: top |
||||||
|
left: -1px |
||||||
|
position: relative |
||||||
|
|
||||||
|
&:hover |
||||||
|
border-color: #999 |
||||||
|
|
||||||
|
.copy-result-message |
||||||
|
background-color: var(--main-menu-bg-color) |
||||||
|
display: inline-block |
||||||
|
padding: 0.5em |
||||||
|
border-radius: 5px |
||||||
|
color: var(--main-menu-font-color) |
||||||
|
position: absolute |
||||||
|
right: 0 |
||||||
|
top: calc(2 * 0.65em + 0.9em + 1px + 9px) |
||||||
|
box-shadow: 1px 1px 4px var(--gray-dark) |
||||||
|
|
||||||
|
&:before |
||||||
|
content: "" |
||||||
|
border-bottom: 0.6em solid var(--main-menu-bg-color) |
||||||
|
height: 0 |
||||||
|
width: 0 |
||||||
|
position: absolute |
||||||
|
top: -9px |
||||||
|
right: 10px |
||||||
|
border-left: 0.3em solid transparent |
||||||
|
border-right: 0.3em solid transparent |
||||||
|
|
||||||
|
.help-text |
||||||
|
color: var(--gray-dark) |
||||||
|
margin-bottom: 1rem |
||||||
|
display: inline-block |
||||||
|
max-width: 20em |
@ -0,0 +1,97 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
/*jshint expr: true*/ |
||||||
|
|
||||||
|
import { GitActionsService } from './git-actions.service'; |
||||||
|
import { WorkPackageResource } from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import { PathHelperService } from 'core-app/modules/common/path-helper/path-helper.service'; |
||||||
|
import { TestBed, waitForAsync } from '@angular/core/testing'; |
||||||
|
|
||||||
|
describe('GitActionsService', function() { |
||||||
|
let service:GitActionsService; |
||||||
|
|
||||||
|
const createWorkPackage = (overrides = {}) => { |
||||||
|
const defaults = { |
||||||
|
id: '42', |
||||||
|
subject: 'Find the question', |
||||||
|
description: { |
||||||
|
raw: 'I recently found the answer is 42. We need to compute the correct question.' |
||||||
|
}, |
||||||
|
type: { name: 'User Story' }, |
||||||
|
pathHelper: new PathHelperService() |
||||||
|
}; |
||||||
|
const workPackage = { ...defaults, ...overrides }; |
||||||
|
return(workPackage as WorkPackageResource); |
||||||
|
}; |
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => { |
||||||
|
TestBed.configureTestingModule({ |
||||||
|
providers: [ |
||||||
|
GitActionsService |
||||||
|
] |
||||||
|
}).compileComponents() |
||||||
|
.then(() => { |
||||||
|
service = TestBed.inject(GitActionsService); |
||||||
|
}); |
||||||
|
})); |
||||||
|
|
||||||
|
beforeEach(() => { |
||||||
|
service = new GitActionsService(); |
||||||
|
}); |
||||||
|
|
||||||
|
|
||||||
|
it('it produces a branch name, commit message, and a git command', () => { |
||||||
|
const wp = createWorkPackage(); |
||||||
|
expect(service.branchName(wp)).toEqual('user-story/42-find-the-question'); |
||||||
|
expect(service.commitMessage(wp)).toEqual(`[#42] Find the question
|
||||||
|
|
||||||
|
I recently found the answer is 42. We need to compute the correct |
||||||
|
question. |
||||||
|
|
||||||
|
http://localhost:9876/work_packages/42
|
||||||
|
`);
|
||||||
|
expect(service.gitCommand(wp)).toEqual(`git checkout -b 'user-story/42-find-the-question' && git commit --allow-empty -m '[#42] Find the question
|
||||||
|
|
||||||
|
I recently found the answer is 42. We need to compute the correct |
||||||
|
question. |
||||||
|
|
||||||
|
http://localhost:9876/work_packages/42
|
||||||
|
'`);
|
||||||
|
}); |
||||||
|
|
||||||
|
it('shell-escapes output for the git-command', () => { |
||||||
|
const wp = createWorkPackage({description: { raw: "' && rm -rf / #"}}); |
||||||
|
expect(service.gitCommand(wp)).toEqual(`git checkout -b 'user-story/42-find-the-question' && git commit --allow-empty -m '[#42] Find the question
|
||||||
|
|
||||||
|
'\\'' && rm -rf / # |
||||||
|
|
||||||
|
http://localhost:9876/work_packages/42
|
||||||
|
'`);
|
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,63 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import {Injectable} from '@angular/core'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import formatter from 'tickety-tick-formatter'; |
||||||
|
|
||||||
|
// probably not providable in root when we want to cache the formatter and set custom templates
|
||||||
|
@Injectable({ |
||||||
|
providedIn: 'root', |
||||||
|
}) |
||||||
|
export class GitActionsService { |
||||||
|
private formatter = formatter(); |
||||||
|
|
||||||
|
public branchName(workPackage:WorkPackageResource):string { |
||||||
|
return(this.formatter.branch(this.formattingInput(workPackage))); |
||||||
|
} |
||||||
|
|
||||||
|
public commitMessage(workPackage:WorkPackageResource):string { |
||||||
|
return(this.formatter.commit(this.formattingInput(workPackage))); |
||||||
|
} |
||||||
|
|
||||||
|
public gitCommand(workPackage:WorkPackageResource):string { |
||||||
|
return(this.formatter.command(this.formattingInput(workPackage))); |
||||||
|
} |
||||||
|
|
||||||
|
private formattingInput(workPackage: WorkPackageResource) { |
||||||
|
const type = workPackage.type.name || ''; |
||||||
|
const id = workPackage.id || ''; |
||||||
|
const title = workPackage.subject; |
||||||
|
const url = window.location.origin + workPackage.pathHelper.workPackagePath(id); |
||||||
|
const description = workPackage.description.raw || ''; |
||||||
|
|
||||||
|
return({ |
||||||
|
id, type, title, url, description |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import {Component, Input, OnInit} from '@angular/core'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service'; |
||||||
|
import {I18nService} from 'core-app/modules/common/i18n/i18n.service'; |
||||||
|
import { TabComponent } from 'core-app/components/wp-tabs/components/wp-tab-wrapper/tab'; |
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: 'github-tab', |
||||||
|
templateUrl: './github-tab.template.html' |
||||||
|
}) |
||||||
|
export class GitHubTabComponent implements OnInit, TabComponent { |
||||||
|
@Input() public workPackage:WorkPackageResource; |
||||||
|
|
||||||
|
public pullRequests = []; |
||||||
|
|
||||||
|
constructor(readonly PathHelper:PathHelperService, |
||||||
|
readonly I18n:I18nService) { |
||||||
|
} |
||||||
|
|
||||||
|
ngOnInit() { |
||||||
|
this.pullRequests = []; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
<tab-header [workPackage]="workPackage"></tab-header> |
||||||
|
<tab-prs [workPackage]="workPackage" |
||||||
|
[pullRequests]="pullRequests" |
||||||
|
></tab-prs> |
@ -0,0 +1,82 @@ |
|||||||
|
// -- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
|
||||||
|
import {Injector, NgModule} from '@angular/core'; |
||||||
|
|
||||||
|
import {HookService} from 'core-app/modules/plugins/hook-service'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import { Tab } from 'core-app/components/wp-tabs/components/wp-tab-wrapper/tab'; |
||||||
|
import {OpenprojectCommonModule} from 'core-app/modules/common/openproject-common.module'; |
||||||
|
|
||||||
|
import {GitHubTabComponent} from './github-tab/github-tab.component'; |
||||||
|
import {TabHeaderComponent} from './tab-header/tab-header.component'; |
||||||
|
import {TabPrsComponent} from './tab-prs/tab-prs.component'; |
||||||
|
import {GitActionsMenuDirective} from './git-actions-menu/git-actions-menu.directive'; |
||||||
|
import {GitActionsMenuComponent} from './git-actions-menu/git-actions-menu.component'; |
||||||
|
|
||||||
|
function displayable(work_package: WorkPackageResource): boolean { |
||||||
|
return(!!work_package.github); |
||||||
|
} |
||||||
|
|
||||||
|
export function initializeGithubIntegrationPlugin(injector:Injector) { |
||||||
|
const hooks = injector.get<HookService>(HookService); |
||||||
|
hooks.registerWorkPackageTab( |
||||||
|
new Tab( |
||||||
|
GitHubTabComponent, |
||||||
|
I18n.t('js.github_integration.work_packages.tab_name'), |
||||||
|
'github', |
||||||
|
displayable |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@NgModule({ |
||||||
|
imports: [ |
||||||
|
OpenprojectCommonModule |
||||||
|
], |
||||||
|
providers: [ |
||||||
|
], |
||||||
|
declarations: [ |
||||||
|
GitHubTabComponent, |
||||||
|
TabHeaderComponent, |
||||||
|
TabPrsComponent, |
||||||
|
GitActionsMenuDirective, |
||||||
|
GitActionsMenuComponent, |
||||||
|
], |
||||||
|
exports: [ |
||||||
|
GitHubTabComponent, |
||||||
|
TabHeaderComponent, |
||||||
|
TabPrsComponent, |
||||||
|
GitActionsMenuDirective, |
||||||
|
GitActionsMenuComponent, |
||||||
|
] |
||||||
|
}) |
||||||
|
export class PluginModule { |
||||||
|
constructor(injector:Injector) { |
||||||
|
initializeGithubIntegrationPlugin(injector); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/*-- copyright |
||||||
|
* OpenProject is an open source project management software. |
||||||
|
* Copyright (C) 2012-2021 the OpenProject GmbH |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License version 3. |
||||||
|
* |
||||||
|
* OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
* Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
* Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU General Public License |
||||||
|
* as published by the Free Software Foundation; either version 2 |
||||||
|
* of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
* |
||||||
|
* See docs/COPYRIGHT.rdoc for more details. |
||||||
|
*/ |
||||||
|
|
||||||
|
.github-pr-header |
||||||
|
display: flex |
||||||
|
flex-wrap: wrap-reverse |
||||||
|
justify-content: flex-end |
||||||
|
|
||||||
|
border-bottom: 1px solid #ddd |
||||||
|
|
||||||
|
margin: 1.5rem 0 0.8rem 0 |
||||||
|
padding: 0 0 0.5rem 0 |
||||||
|
|
||||||
|
.title |
||||||
|
flex: 1 1 auto |
||||||
|
border-bottom: 0 |
||||||
|
margin: 0 |
||||||
|
padding: 0 |
@ -0,0 +1,55 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import {Component, Input} from '@angular/core'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service'; |
||||||
|
import {I18nService} from 'core-app/modules/common/i18n/i18n.service'; |
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: 'tab-header', |
||||||
|
templateUrl: './tab-header.template.html', |
||||||
|
styleUrls: [ |
||||||
|
'./styles/tab-header.sass' |
||||||
|
] |
||||||
|
}) |
||||||
|
export class TabHeaderComponent { |
||||||
|
@Input() public workPackage:WorkPackageResource; |
||||||
|
|
||||||
|
public text = { |
||||||
|
title: this.I18n.t('js.github_integration.tab_header.title'), |
||||||
|
createPrButtonLabel: this.I18n.t('js.github_integration.tab_header.create_pr.label'), |
||||||
|
createPrButtonDescription: this.I18n.t('js.github_integration.tab_header.create_pr.description'), |
||||||
|
gitMenuLabel: this.I18n.t('js.github_integration.tab_header.copy_menu.label'), |
||||||
|
gitMenuDescription: this.I18n.t('js.github_integration.tab_header.copy_menu.description'), |
||||||
|
}; |
||||||
|
|
||||||
|
constructor(readonly PathHelper:PathHelperService, |
||||||
|
readonly I18n:I18nService) { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
<div class="github-pr-header"> |
||||||
|
<h3 class="title"> |
||||||
|
<op-icon icon-classes="button--icon icon-merge-branch"></op-icon> |
||||||
|
{{text.title}} |
||||||
|
</h3> |
||||||
|
<ul class="toolbar-items hide-when-print"> |
||||||
|
<li class="toolbar-item"> |
||||||
|
<button class="button github-git-copy" |
||||||
|
type="button" |
||||||
|
[attr.aria-label]="text.gitMenuDescription" |
||||||
|
gitActionsCopyDropdown |
||||||
|
[gitActionsCopyDropdown-workPackage]="workPackage"> |
||||||
|
<op-icon icon-classes="button--icon icon-console-light"></op-icon> |
||||||
|
<span class="button--text" |
||||||
|
[textContent]="text.gitMenuLabel" |
||||||
|
aria-hidden="true"></span> |
||||||
|
<op-icon icon-classes="button--icon icon-small icon-pulldown hidden-for-mobile"></op-icon> |
||||||
|
</button> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
@ -0,0 +1,50 @@ |
|||||||
|
//-- copyright
|
||||||
|
// OpenProject is an open source project management software.
|
||||||
|
// Copyright (C) 2012-2021 the OpenProject GmbH
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License version 3.
|
||||||
|
//
|
||||||
|
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||||
|
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
|
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 2
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
//
|
||||||
|
// See docs/COPYRIGHT.rdoc for more details.
|
||||||
|
//++
|
||||||
|
|
||||||
|
import {Component, Input} from '@angular/core'; |
||||||
|
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource'; |
||||||
|
import {PathHelperService} from 'core-app/modules/common/path-helper/path-helper.service'; |
||||||
|
import {I18nService} from 'core-app/modules/common/i18n/i18n.service'; |
||||||
|
|
||||||
|
|
||||||
|
@Component({ |
||||||
|
selector: 'tab-prs', |
||||||
|
templateUrl: './tab-prs.template.html' |
||||||
|
}) |
||||||
|
export class TabPrsComponent { |
||||||
|
@Input() public workPackage:WorkPackageResource; |
||||||
|
@Input() public pullRequests:WorkPackageResource[]; |
||||||
|
|
||||||
|
constructor(readonly PathHelper:PathHelperService, |
||||||
|
readonly I18n:I18nService) { |
||||||
|
} |
||||||
|
|
||||||
|
public getEmptyText() { |
||||||
|
return this.I18n.t('js.github_integration.tab_prs.empty',{ wp_id: this.workPackage.id }); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<ng-container *ngIf="pullRequests.length === 0"> |
||||||
|
<p [innerHTML]="getEmptyText()"></p> |
||||||
|
</ng-container> |
@ -0,0 +1,21 @@ |
|||||||
|
module OpenProject::GithubIntegration |
||||||
|
module Patches |
||||||
|
module API |
||||||
|
module WorkPackageRepresenter |
||||||
|
module_function |
||||||
|
|
||||||
|
def extension |
||||||
|
->(*) do |
||||||
|
link :github, |
||||||
|
cache_if: -> { current_user.allowed_to?(:show_github_content, represented.project) } do |
||||||
|
{ |
||||||
|
href: "#{work_package_path(id: represented.id)}/tabs/github", |
||||||
|
title: "github" |
||||||
|
} |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,115 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 the OpenProject GmbH |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See docs/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'spec_helper' |
||||||
|
require_relative '../support/pages/work_package_github_tab' |
||||||
|
|
||||||
|
describe 'Open the GitHub tab', type: :feature, js: true do |
||||||
|
let(:user) do |
||||||
|
FactoryBot.create(:user, |
||||||
|
member_in_project: project, |
||||||
|
member_through_role: role) |
||||||
|
end |
||||||
|
let(:role) do |
||||||
|
FactoryBot.create(:role, |
||||||
|
permissions: %i(view_work_packages |
||||||
|
add_work_package_notes |
||||||
|
show_github_content)) |
||||||
|
end |
||||||
|
let(:project) { FactoryBot.create :project } |
||||||
|
let(:work_package) { FactoryBot.create(:work_package, project: project) } |
||||||
|
let(:github_tab) { Pages::GitHubTab.new(work_package.id) } |
||||||
|
|
||||||
|
shared_examples_for "a github tab" do |
||||||
|
before do |
||||||
|
login_as(user) |
||||||
|
work_package |
||||||
|
end |
||||||
|
|
||||||
|
# compares the clipboard content by drafting a new comment, pressing ctrl+v and |
||||||
|
# comparing the pasted content against the provided text |
||||||
|
def expect_clipboard_content(text) |
||||||
|
work_package_page.switch_to_tab(tab: 'activity') |
||||||
|
|
||||||
|
work_package_page.trigger_edit_comment |
||||||
|
work_package_page.update_comment(' ') # ensure the comment editor is fully loaded |
||||||
|
github_tab.paste_clipboard_content |
||||||
|
expect(work_package_page.add_comment_container).to have_content(text) |
||||||
|
|
||||||
|
work_package_page.switch_to_tab(tab: 'github') |
||||||
|
end |
||||||
|
|
||||||
|
it 'show the github tab when the user is allowed to see it' do |
||||||
|
work_package_page.visit! |
||||||
|
work_package_page.switch_to_tab(tab: 'github') |
||||||
|
expect(page).to have_content('There are no pull requests') |
||||||
|
expect(page).to have_content("Link an existing PR by using the code OP##{work_package.id}") |
||||||
|
|
||||||
|
github_tab.git_actions_menu_button.click |
||||||
|
github_tab.git_actions_copy_button.click |
||||||
|
expect(page).to have_text('Copied!') |
||||||
|
expect_clipboard_content("#{work_package.type.name.downcase}/#{work_package.id}-workpackage-no-#{work_package.id}") |
||||||
|
end |
||||||
|
|
||||||
|
describe 'when the user does not have the permissions to see the github tab' do |
||||||
|
let(:role) do |
||||||
|
FactoryBot.create(:role, |
||||||
|
permissions: %i(view_work_packages |
||||||
|
add_work_package_notes)) |
||||||
|
end |
||||||
|
|
||||||
|
it 'does not show the github tab' do |
||||||
|
work_package_page.visit! |
||||||
|
|
||||||
|
github_tab.expect_tab_not_present |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'when the github integration is not enabled for the project' do |
||||||
|
let(:project) { FactoryBot.create(:project, disable_modules: 'github') } |
||||||
|
|
||||||
|
it 'does not show the github tab' do |
||||||
|
work_package_page.visit! |
||||||
|
|
||||||
|
github_tab.expect_tab_not_present |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe 'work package full view' do |
||||||
|
let(:work_package_page) { Pages::FullWorkPackage.new(work_package) } |
||||||
|
|
||||||
|
it_behaves_like 'a github tab' |
||||||
|
end |
||||||
|
|
||||||
|
describe 'work package split view' do |
||||||
|
let(:work_package_page) { Pages::SplitWorkPackage.new(work_package) } |
||||||
|
|
||||||
|
it_behaves_like 'a github tab' |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,68 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 the OpenProject GmbH |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License version 3. |
||||||
|
# |
||||||
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||||
|
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||||
|
# Copyright (C) 2010-2013 the ChiliProject Team |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or |
||||||
|
# modify it under the terms of the GNU General Public License |
||||||
|
# as published by the Free Software Foundation; either version 2 |
||||||
|
# of the License, or (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
# GNU General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||||
|
# |
||||||
|
# See docs/COPYRIGHT.rdoc for more details. |
||||||
|
#++ |
||||||
|
|
||||||
|
require 'rbconfig' |
||||||
|
require 'support/pages/page' |
||||||
|
|
||||||
|
module Pages |
||||||
|
class GitHubTab < Page |
||||||
|
attr_reader :work_package_id |
||||||
|
|
||||||
|
def initialize(work_package_id) |
||||||
|
super() |
||||||
|
@work_package_id = work_package_id |
||||||
|
end |
||||||
|
|
||||||
|
def path |
||||||
|
"/work_packages/#{work_package_id}/tabs/github" |
||||||
|
end |
||||||
|
|
||||||
|
def git_actions_menu_button |
||||||
|
find('.github-git-copy:not([disabled])', text: 'Git') |
||||||
|
end |
||||||
|
|
||||||
|
def git_actions_copy_button |
||||||
|
find('.git-actions-menu .copy-button:not([disabled])') |
||||||
|
end |
||||||
|
|
||||||
|
def paste_clipboard_content |
||||||
|
meta_key = osx? ? :command : :control |
||||||
|
page.send_keys(meta_key, 'v') |
||||||
|
end |
||||||
|
|
||||||
|
def expect_tab_not_present |
||||||
|
expect(page).not_to have_selector('.tabrow li', text: 'GITHUB') |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def osx? |
||||||
|
RbConfig::CONFIG['host_os'] =~ /darwin/ |
||||||
|
end |
||||||
|
end |
||||||
|
end |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in new issue