Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
c3b1b2a3
Commit
c3b1b2a3
authored
Oct 11, 2021
by
Denys Mishunov
Committed by
Jacques Erasmus
Oct 11, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Resolve "Add a keyboard shortcut to quickly open the Web IDE from any repo view"
parent
afc46c74
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
142 additions
and
12 deletions
+142
-12
app/assets/javascripts/behaviors/shortcuts/keybindings.js
app/assets/javascripts/behaviors/shortcuts/keybindings.js
+7
-0
app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
...s/javascripts/behaviors/shortcuts/shortcuts_navigation.js
+14
-0
app/assets/javascripts/lib/utils/url_utility.js
app/assets/javascripts/lib/utils/url_utility.js
+27
-0
app/assets/javascripts/repository/router.js
app/assets/javascripts/repository/router.js
+19
-2
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
.../vue_merge_request_widget/components/mr_widget_header.vue
+2
-10
app/views/projects/blob/show.html.haml
app/views/projects/blob/show.html.haml
+1
-0
app/views/projects/merge_requests/show.html.haml
app/views/projects/merge_requests/show.html.haml
+1
-0
app/views/projects/tree/show.html.haml
app/views/projects/tree/show.html.haml
+1
-0
app/views/shared/_web_ide_path.html.haml
app/views/shared/_web_ide_path.html.haml
+4
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/lib/utils/url_utility_spec.js
spec/frontend/lib/utils/url_utility_spec.js
+35
-0
spec/frontend/repository/router_spec.js
spec/frontend/repository/router_spec.js
+28
-0
No files found.
app/assets/javascripts/behaviors/shortcuts/keybindings.js
View file @
c3b1b2a3
...
...
@@ -306,6 +306,12 @@ export const GO_TO_PROJECT_WIKI = {
defaultKeys
:
[
'
g w
'
],
// eslint-disable-line @gitlab/require-i18n-strings
};
export
const
GO_TO_PROJECT_WEBIDE
=
{
id
:
'
project.goToWebIDE
'
,
description
:
__
(
'
Open in Web IDE
'
),
defaultKeys
:
[
'
.
'
],
};
export
const
PROJECT_FILES_MOVE_SELECTION_UP
=
{
id
:
'
projectFiles.moveSelectionUp
'
,
description
:
__
(
'
Move selection up
'
),
...
...
@@ -549,6 +555,7 @@ export const PROJECT_SHORTCUTS_GROUP = {
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_SNIPPETS
,
GO_TO_PROJECT_WIKI
,
GO_TO_PROJECT_WEBIDE
,
],
};
...
...
app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
View file @
c3b1b2a3
import
Mousetrap
from
'
mousetrap
'
;
import
{
visitUrl
,
constructWebIDEPath
}
from
'
~/lib/utils/url_utility
'
;
import
findAndFollowLink
from
'
../../lib/utils/navigation_utility
'
;
import
{
keysFor
,
...
...
@@ -18,6 +19,7 @@ import {
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_ENVIRONMENTS
,
GO_TO_PROJECT_METRICS
,
GO_TO_PROJECT_WEBIDE
,
NEW_ISSUE
,
}
from
'
./keybindings
'
;
import
Shortcuts
from
'
./shortcuts
'
;
...
...
@@ -58,6 +60,18 @@ export default class ShortcutsNavigation extends Shortcuts {
findAndFollowLink
(
'
.shortcuts-environments
'
),
);
Mousetrap
.
bind
(
keysFor
(
GO_TO_PROJECT_METRICS
),
()
=>
findAndFollowLink
(
'
.shortcuts-metrics
'
));
Mousetrap
.
bind
(
keysFor
(
GO_TO_PROJECT_WEBIDE
),
ShortcutsNavigation
.
navigateToWebIDE
);
Mousetrap
.
bind
(
keysFor
(
NEW_ISSUE
),
()
=>
findAndFollowLink
(
'
.shortcuts-new-issue
'
));
}
static
navigateToWebIDE
()
{
const
path
=
constructWebIDEPath
({
sourceProjectFullPath
:
window
.
gl
.
mrWidgetData
?.
source_project_full_path
,
targetProjectFullPath
:
window
.
gl
.
mrWidgetData
?.
target_project_full_path
,
iid
:
window
.
gl
.
mrWidgetData
?.
iid
,
});
if
(
path
)
{
visitUrl
(
path
);
}
}
}
app/assets/javascripts/lib/utils/url_utility.js
View file @
c3b1b2a3
...
...
@@ -590,3 +590,30 @@ export function isSameOriginUrl(url) {
return
false
;
}
}
/**
* Returns a URL to WebIDE considering the current user's position in
* repository's tree. If not MR `iid` has been passed, the URL is fetched
* from the global `gl.webIDEPath`.
*
* @param sourceProjectFullPath Source project's full path. Used in MRs
* @param targetProjectFullPath Target project's full path. Used in MRs
* @param iid MR iid
* @returns {string}
*/
export
function
constructWebIDEPath
({
sourceProjectFullPath
,
targetProjectFullPath
=
''
,
iid
,
}
=
{})
{
if
(
!
iid
||
!
sourceProjectFullPath
)
{
return
window
.
gl
?.
webIDEPath
;
}
return
mergeUrlParams
(
{
target_project
:
sourceProjectFullPath
!==
targetProjectFullPath
?
targetProjectFullPath
:
''
,
},
webIDEUrl
(
`/
${
sourceProjectFullPath
}
/merge_requests/
${
iid
}
`
),
);
}
app/assets/javascripts/repository/router.js
View file @
c3b1b2a3
import
{
escapeRegExp
}
from
'
lodash
'
;
import
Vue
from
'
vue
'
;
import
VueRouter
from
'
vue-router
'
;
import
{
joinPaths
}
from
'
..
/lib/utils/url_utility
'
;
import
{
joinPaths
,
webIDEUrl
}
from
'
~
/lib/utils/url_utility
'
;
import
BlobPage
from
'
./pages/blob.vue
'
;
import
IndexPage
from
'
./pages/index.vue
'
;
import
TreePage
from
'
./pages/tree.vue
'
;
...
...
@@ -24,7 +24,7 @@ export default function createRouter(base, baseRef) {
}),
};
return
new
VueRouter
({
const
router
=
new
VueRouter
({
mode
:
'
history
'
,
base
:
joinPaths
(
gon
.
relative_url_root
||
''
,
base
),
routes
:
[
...
...
@@ -59,4 +59,21 @@ export default function createRouter(base, baseRef) {
},
],
});
router
.
afterEach
((
to
)
=>
{
const
needsClosingSlash
=
!
to
.
name
.
includes
(
'
blobPath
'
);
window
.
gl
.
webIDEPath
=
webIDEUrl
(
joinPaths
(
'
/
'
,
base
,
'
edit
'
,
decodeURI
(
baseRef
),
'
-
'
,
to
.
params
.
path
||
''
,
needsClosingSlash
&&
'
/
'
,
),
);
});
return
router
;
}
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
View file @
c3b1b2a3
...
...
@@ -10,7 +10,7 @@ import {
GlSafeHtmlDirective
as
SafeHtml
,
GlSprintf
,
}
from
'
@gitlab/ui
'
;
import
{
mergeUrlParams
,
webIDEUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
constructWebIDEPath
}
from
'
~/lib/utils/url_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
...
...
@@ -58,15 +58,7 @@ export default {
});
},
webIdePath
()
{
return
mergeUrlParams
(
{
target_project
:
this
.
mr
.
sourceProjectFullPath
!==
this
.
mr
.
targetProjectFullPath
?
this
.
mr
.
targetProjectFullPath
:
''
,
},
webIDEUrl
(
`/
${
this
.
mr
.
sourceProjectFullPath
}
/merge_requests/
${
this
.
mr
.
iid
}
`
),
);
return
constructWebIDEPath
(
this
.
mr
);
},
isFork
()
{
return
this
.
mr
.
sourceProjectFullPath
!==
this
.
mr
.
targetProjectFullPath
;
...
...
app/views/projects/blob/show.html.haml
View file @
c3b1b2a3
...
...
@@ -18,3 +18,4 @@
=
render
'projects/blob/upload'
,
title:
title
,
placeholder:
title
,
button_title:
'Replace file'
,
form_path:
project_update_blob_path
(
@project
,
@id
),
method: :put
=
render
partial:
'pipeline_tour_success'
if
show_suggest_pipeline_creation_celebration?
=
render
'shared/web_ide_path'
app/views/projects/merge_requests/show.html.haml
View file @
c3b1b2a3
...
...
@@ -99,3 +99,4 @@
=
render
'projects/invite_members_modal'
,
project:
@project
-
if
Gitlab
::
CurrentSettings
.
gitpod_enabled
&&
!
current_user
&
.
gitpod_enabled
=
render
'shared/gitpod/enable_gitpod_modal'
=
render
'shared/web_ide_path'
app/views/projects/tree/show.html.haml
View file @
c3b1b2a3
...
...
@@ -11,3 +11,4 @@
=
render
'projects/last_push'
=
render
'projects/files'
,
commit:
@last_commit
,
project:
@project
,
ref:
@ref
,
content_url:
project_tree_path
(
@project
,
@id
)
=
render
'shared/web_ide_path'
app/views/shared/_web_ide_path.html.haml
0 → 100644
View file @
c3b1b2a3
=
javascript_tag
do
:plain
window.gl = window.gl || {};
window.gl.webIDEPath = '
#{
web_ide_url
}
'
locale/gitlab.pot
View file @
c3b1b2a3
...
...
@@ -23912,6 +23912,9 @@ msgstr ""
msgid "Open errors"
msgstr ""
msgid "Open in Web IDE"
msgstr ""
msgid "Open in file view"
msgstr ""
...
...
spec/frontend/lib/utils/url_utility_spec.js
View file @
c3b1b2a3
...
...
@@ -1004,4 +1004,39 @@ describe('URL utility', () => {
expect
(
urlUtils
.
isSameOriginUrl
(
url
)).
toBe
(
expected
);
});
});
describe
(
'
constructWebIDEPath
'
,
()
=>
{
let
originalGl
;
const
projectIDEPath
=
'
/foo/bar
'
;
const
sourceProj
=
'
my_-fancy-proj/boo
'
;
const
targetProj
=
'
boo/another-fancy-proj
'
;
const
mrIid
=
'
7
'
;
beforeEach
(()
=>
{
originalGl
=
window
.
gl
;
window
.
gl
=
{
webIDEPath
:
projectIDEPath
};
});
afterEach
(()
=>
{
window
.
gl
=
originalGl
;
});
it
.
each
`
sourceProjectFullPath | targetProjectFullPath | iid | expectedPath
${
undefined
}
|
${
undefined
}
|
${
undefined
}
|
${
projectIDEPath
}
${
undefined
}
|
${
undefined
}
|
${
mrIid
}
|
${
projectIDEPath
}
${
undefined
}
|
${
targetProj
}
|
${
undefined
}
|
${
projectIDEPath
}
${
undefined
}
|
${
targetProj
}
|
${
mrIid
}
|
${
projectIDEPath
}
${
sourceProj
}
|
${
undefined
}
|
${
undefined
}
|
${
projectIDEPath
}
${
sourceProj
}
|
${
targetProj
}
|
${
undefined
}
|
${
projectIDEPath
}
${
sourceProj
}
|
${
undefined
}
|
${
mrIid
}
|
${
`/-/ide/project/
${
sourceProj
}
/merge_requests/
${
mrIid
}
?target_project=`
}
${
sourceProj
}
|
${
sourceProj
}
|
${
mrIid
}
|
${
`/-/ide/project/
${
sourceProj
}
/merge_requests/
${
mrIid
}
?target_project=`
}
${
sourceProj
}
|
${
targetProj
}
|
${
mrIid
}
|
${
`/-/ide/project/
${
sourceProj
}
/merge_requests/
${
mrIid
}
?target_project=
${
encodeURIComponent
(
targetProj
)}
`
}
`
(
'
returns $expectedPath for "$sourceProjectFullPath + $targetProjectFullPath + $iid"
'
,
({
expectedPath
,
...
args
}
=
{})
=>
{
expect
(
urlUtils
.
constructWebIDEPath
(
args
)).
toBe
(
expectedPath
);
},
);
});
});
spec/frontend/repository/router_spec.js
View file @
c3b1b2a3
...
...
@@ -24,4 +24,32 @@ describe('Repository router spec', () => {
expect
(
componentsForRoute
).
toContain
(
component
);
}
});
describe
(
'
Storing Web IDE path globally
'
,
()
=>
{
const
proj
=
'
foo-bar-group/foo-bar-proj
'
;
let
originalGl
;
beforeEach
(()
=>
{
originalGl
=
window
.
gl
;
});
afterEach
(()
=>
{
window
.
gl
=
originalGl
;
});
it
.
each
`
path | branch | expectedPath
${
'
/
'
}
|
${
'
main
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/main/-/`
}
${
'
/tree/main
'
}
|
${
'
main
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/main/-/`
}
${
'
/tree/feat(test)
'
}
|
${
'
feat(test)
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/feat(test)/-/`
}
${
'
/-/tree/main
'
}
|
${
'
main
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/main/-/`
}
${
'
/-/tree/main/app/assets
'
}
|
${
'
main
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/main/-/app/assets/`
}
${
'
/-/blob/main/file.md
'
}
|
${
'
main
'
}
|
${
`/-/ide/project/
${
proj
}
/edit/main/-/file.md`
}
`
(
'
generates the correct Web IDE url for $path
'
,
({
path
,
branch
,
expectedPath
}
=
{})
=>
{
const
router
=
createRouter
(
proj
,
branch
);
router
.
push
(
path
);
expect
(
window
.
gl
.
webIDEPath
).
toBe
(
expectedPath
);
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment