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 = {
...
@@ -306,6 +306,12 @@ export const GO_TO_PROJECT_WIKI = {
defaultKeys
:
[
'
g w
'
],
// eslint-disable-line @gitlab/require-i18n-strings
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
=
{
export
const
PROJECT_FILES_MOVE_SELECTION_UP
=
{
id
:
'
projectFiles.moveSelectionUp
'
,
id
:
'
projectFiles.moveSelectionUp
'
,
description
:
__
(
'
Move selection up
'
),
description
:
__
(
'
Move selection up
'
),
...
@@ -549,6 +555,7 @@ export const PROJECT_SHORTCUTS_GROUP = {
...
@@ -549,6 +555,7 @@ export const PROJECT_SHORTCUTS_GROUP = {
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_SNIPPETS
,
GO_TO_PROJECT_SNIPPETS
,
GO_TO_PROJECT_WIKI
,
GO_TO_PROJECT_WIKI
,
GO_TO_PROJECT_WEBIDE
,
],
],
};
};
...
...
app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js
View file @
c3b1b2a3
import
Mousetrap
from
'
mousetrap
'
;
import
Mousetrap
from
'
mousetrap
'
;
import
{
visitUrl
,
constructWebIDEPath
}
from
'
~/lib/utils/url_utility
'
;
import
findAndFollowLink
from
'
../../lib/utils/navigation_utility
'
;
import
findAndFollowLink
from
'
../../lib/utils/navigation_utility
'
;
import
{
import
{
keysFor
,
keysFor
,
...
@@ -18,6 +19,7 @@ import {
...
@@ -18,6 +19,7 @@ import {
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_KUBERNETES
,
GO_TO_PROJECT_ENVIRONMENTS
,
GO_TO_PROJECT_ENVIRONMENTS
,
GO_TO_PROJECT_METRICS
,
GO_TO_PROJECT_METRICS
,
GO_TO_PROJECT_WEBIDE
,
NEW_ISSUE
,
NEW_ISSUE
,
}
from
'
./keybindings
'
;
}
from
'
./keybindings
'
;
import
Shortcuts
from
'
./shortcuts
'
;
import
Shortcuts
from
'
./shortcuts
'
;
...
@@ -58,6 +60,18 @@ export default class ShortcutsNavigation extends Shortcuts {
...
@@ -58,6 +60,18 @@ export default class ShortcutsNavigation extends Shortcuts {
findAndFollowLink
(
'
.shortcuts-environments
'
),
findAndFollowLink
(
'
.shortcuts-environments
'
),
);
);
Mousetrap
.
bind
(
keysFor
(
GO_TO_PROJECT_METRICS
),
()
=>
findAndFollowLink
(
'
.shortcuts-metrics
'
));
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
'
));
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) {
...
@@ -590,3 +590,30 @@ export function isSameOriginUrl(url) {
return
false
;
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
{
escapeRegExp
}
from
'
lodash
'
;
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
VueRouter
from
'
vue-router
'
;
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
BlobPage
from
'
./pages/blob.vue
'
;
import
IndexPage
from
'
./pages/index.vue
'
;
import
IndexPage
from
'
./pages/index.vue
'
;
import
TreePage
from
'
./pages/tree.vue
'
;
import
TreePage
from
'
./pages/tree.vue
'
;
...
@@ -24,7 +24,7 @@ export default function createRouter(base, baseRef) {
...
@@ -24,7 +24,7 @@ export default function createRouter(base, baseRef) {
}),
}),
};
};
return
new
VueRouter
({
const
router
=
new
VueRouter
({
mode
:
'
history
'
,
mode
:
'
history
'
,
base
:
joinPaths
(
gon
.
relative_url_root
||
''
,
base
),
base
:
joinPaths
(
gon
.
relative_url_root
||
''
,
base
),
routes
:
[
routes
:
[
...
@@ -59,4 +59,21 @@ export default function createRouter(base, baseRef) {
...
@@ -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 {
...
@@ -10,7 +10,7 @@ import {
GlSafeHtmlDirective
as
SafeHtml
,
GlSafeHtmlDirective
as
SafeHtml
,
GlSprintf
,
GlSprintf
,
}
from
'
@gitlab/ui
'
;
}
from
'
@gitlab/ui
'
;
import
{
mergeUrlParams
,
webIDEUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
constructWebIDEPath
}
from
'
~/lib/utils/url_utility
'
;
import
{
s__
}
from
'
~/locale
'
;
import
{
s__
}
from
'
~/locale
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
clipboardButton
from
'
~/vue_shared/components/clipboard_button.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
...
@@ -58,15 +58,7 @@ export default {
...
@@ -58,15 +58,7 @@ export default {
});
});
},
},
webIdePath
()
{
webIdePath
()
{
return
mergeUrlParams
(
return
constructWebIDEPath
(
this
.
mr
);
{
target_project
:
this
.
mr
.
sourceProjectFullPath
!==
this
.
mr
.
targetProjectFullPath
?
this
.
mr
.
targetProjectFullPath
:
''
,
},
webIDEUrl
(
`/
${
this
.
mr
.
sourceProjectFullPath
}
/merge_requests/
${
this
.
mr
.
iid
}
`
),
);
},
},
isFork
()
{
isFork
()
{
return
this
.
mr
.
sourceProjectFullPath
!==
this
.
mr
.
targetProjectFullPath
;
return
this
.
mr
.
sourceProjectFullPath
!==
this
.
mr
.
targetProjectFullPath
;
...
...
app/views/projects/blob/show.html.haml
View file @
c3b1b2a3
...
@@ -18,3 +18,4 @@
...
@@ -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
'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
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 @@
...
@@ -99,3 +99,4 @@
=
render
'projects/invite_members_modal'
,
project:
@project
=
render
'projects/invite_members_modal'
,
project:
@project
-
if
Gitlab
::
CurrentSettings
.
gitpod_enabled
&&
!
current_user
&
.
gitpod_enabled
-
if
Gitlab
::
CurrentSettings
.
gitpod_enabled
&&
!
current_user
&
.
gitpod_enabled
=
render
'shared/gitpod/enable_gitpod_modal'
=
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 @@
...
@@ -11,3 +11,4 @@
=
render
'projects/last_push'
=
render
'projects/last_push'
=
render
'projects/files'
,
commit:
@last_commit
,
project:
@project
,
ref:
@ref
,
content_url:
project_tree_path
(
@project
,
@id
)
=
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 ""
...
@@ -23912,6 +23912,9 @@ msgstr ""
msgid "Open errors"
msgid "Open errors"
msgstr ""
msgstr ""
msgid "Open in Web IDE"
msgstr ""
msgid "Open in file view"
msgid "Open in file view"
msgstr ""
msgstr ""
...
...
spec/frontend/lib/utils/url_utility_spec.js
View file @
c3b1b2a3
...
@@ -1004,4 +1004,39 @@ describe('URL utility', () => {
...
@@ -1004,4 +1004,39 @@ describe('URL utility', () => {
expect
(
urlUtils
.
isSameOriginUrl
(
url
)).
toBe
(
expected
);
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', () => {
...
@@ -24,4 +24,32 @@ describe('Repository router spec', () => {
expect
(
componentsForRoute
).
toContain
(
component
);
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