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
0
Merge Requests
0
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
Léo-Paul Géneau
gitlab-ce
Commits
db739548
Commit
db739548
authored
Aug 07, 2018
by
Paul Slaughter
Committed by
Phil Hughes
Aug 07, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Web IDE context header redesign
parent
379083be
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
227 additions
and
219 deletions
+227
-219
app/assets/javascripts/ide/components/activity_bar.vue
app/assets/javascripts/ide/components/activity_bar.vue
+1
-20
app/assets/javascripts/ide/components/ide_project_header.vue
app/assets/javascripts/ide/components/ide_project_header.vue
+37
-0
app/assets/javascripts/ide/components/ide_side_bar.vue
app/assets/javascripts/ide/components/ide_side_bar.vue
+21
-142
app/assets/javascripts/ide/components/ide_tree.vue
app/assets/javascripts/ide/components/ide_tree.vue
+0
-1
app/assets/javascripts/ide/components/ide_tree_list.vue
app/assets/javascripts/ide/components/ide_tree_list.vue
+10
-6
app/assets/javascripts/vue_shared/components/project_avatar/default.vue
...ascripts/vue_shared/components/project_avatar/default.vue
+47
-0
app/assets/stylesheets/framework/avatar.scss
app/assets/stylesheets/framework/avatar.scss
+1
-0
app/assets/stylesheets/framework/contextual_sidebar.scss
app/assets/stylesheets/framework/contextual_sidebar.scss
+5
-0
app/assets/stylesheets/page_bundles/ide.scss
app/assets/stylesheets/page_bundles/ide.scss
+41
-29
changelogs/unreleased/47768-web-ide-redesign-header.yml
changelogs/unreleased/47768-web-ide-redesign-header.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+1
-1
spec/javascripts/ide/components/activity_bar_spec.js
spec/javascripts/ide/components/activity_bar_spec.js
+0
-20
spec/javascripts/vue_shared/components/project_avatar/default_spec.js
...ipts/vue_shared/components/project_avatar/default_spec.js
+58
-0
No files found.
app/assets/javascripts/ide/components/activity_bar.vue
View file @
db739548
...
...
@@ -13,11 +13,8 @@ export default {
tooltip
,
},
computed
:
{
...
mapGetters
([
'
currentProject
'
,
'
hasChanges
'
]),
...
mapGetters
([
'
hasChanges
'
]),
...
mapState
([
'
currentActivityView
'
]),
goBackUrl
()
{
return
document
.
referrer
||
this
.
currentProject
.
web_url
;
},
},
methods
:
{
...
mapActions
([
'
updateActivityBarView
'
]),
...
...
@@ -36,22 +33,6 @@ export default {
<
template
>
<nav
class=
"ide-activity-bar"
>
<ul
class=
"list-unstyled"
>
<li
v-once
>
<a
v-tooltip
:href=
"goBackUrl"
:title=
"s__('IDE|Go back')"
:aria-label=
"s__('IDE|Go back')"
data-container=
"body"
data-placement=
"right"
class=
"ide-sidebar-link"
>
<icon
:size=
"16"
name=
"go-back"
/>
</a>
</li>
<li>
<button
v-tooltip
...
...
app/assets/javascripts/ide/components/ide_project_header.vue
0 → 100644
View file @
db739548
<
script
>
import
ProjectAvatarDefault
from
'
~/vue_shared/components/project_avatar/default.vue
'
;
export
default
{
components
:
{
ProjectAvatarDefault
,
},
props
:
{
project
:
{
type
:
Object
,
required
:
true
,
},
},
};
</
script
>
<
template
>
<div
class=
"context-header ide-context-header"
>
<a
:href=
"project.web_url"
:title=
"s__('IDE|Go to project')"
>
<project-avatar-default
:project=
"project"
:size=
"48"
/>
<span
class=
"ide-sidebar-project-title"
>
<span
class=
"sidebar-context-title"
>
{{
project
.
name
}}
</span>
<span
class=
"sidebar-context-title text-secondary"
>
{{
project
.
path_with_namespace
}}
</span>
</span>
</a>
</div>
</
template
>
app/assets/javascripts/ide/components/ide_side_bar.vue
View file @
db739548
<
script
>
import
$
from
'
jquery
'
;
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
ProjectAvatarImage
from
'
~/vue_shared/components/project_avatar/image.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
PanelResizer
from
'
~/vue_shared/components/panel_resizer.vue
'
;
import
SkeletonLoadingContainer
from
'
~/vue_shared/components/skeleton_loading_container.vue
'
;
import
Identicon
from
'
../../vue_shared/components/identicon.vue
'
;
import
IdeTree
from
'
./ide_tree.vue
'
;
import
ResizablePanel
from
'
./resizable_panel.vue
'
;
import
ActivityBar
from
'
./activity_bar.vue
'
;
...
...
@@ -14,43 +8,28 @@ import CommitSection from './repo_commit_section.vue';
import
CommitForm
from
'
./commit_sidebar/form.vue
'
;
import
IdeReview
from
'
./ide_review.vue
'
;
import
SuccessMessage
from
'
./commit_sidebar/success_message.vue
'
;
import
MergeRequestDropdown
from
'
./merge_requests/dropdown
.vue
'
;
import
IdeProjectHeader
from
'
./ide_project_header
.vue
'
;
import
{
activityBarViews
}
from
'
../constants
'
;
export
default
{
directives
:
{
tooltip
,
},
components
:
{
Icon
,
PanelResizer
,
SkeletonLoadingContainer
,
ResizablePanel
,
ActivityBar
,
ProjectAvatarImage
,
Identicon
,
CommitSection
,
IdeTree
,
CommitForm
,
IdeReview
,
SuccessMessage
,
MergeRequestDropdown
,
},
data
()
{
return
{
showTooltip
:
false
,
showMergeRequestsDropdown
:
false
,
};
IdeProjectHeader
,
},
computed
:
{
...
mapState
([
'
loading
'
,
'
currentBranchId
'
,
'
currentActivityView
'
,
'
changedFiles
'
,
'
stagedFiles
'
,
'
lastCommitMsg
'
,
'
currentMergeRequestId
'
,
]),
...
mapGetters
([
'
currentProject
'
,
'
someUncommitedChanges
'
]),
showSuccessMessage
()
{
...
...
@@ -59,46 +38,6 @@ export default {
(
this
.
lastCommitMsg
&&
!
this
.
someUncommitedChanges
)
);
},
branchTooltipTitle
()
{
return
this
.
showTooltip
?
this
.
currentBranchId
:
undefined
;
},
},
watch
:
{
currentBranchId
()
{
this
.
$nextTick
(()
=>
{
if
(
!
this
.
$refs
.
branchId
)
return
;
this
.
showTooltip
=
this
.
$refs
.
branchId
.
scrollWidth
>
this
.
$refs
.
branchId
.
offsetWidth
;
});
},
loading
()
{
this
.
$nextTick
(()
=>
{
this
.
addDropdownListeners
();
});
},
},
mounted
()
{
this
.
addDropdownListeners
();
},
beforeDestroy
()
{
$
(
this
.
$refs
.
mergeRequestDropdown
)
.
off
(
'
show.bs.dropdown
'
)
.
off
(
'
hide.bs.dropdown
'
);
},
methods
:
{
addDropdownListeners
()
{
if
(
!
this
.
$refs
.
mergeRequestDropdown
)
return
;
$
(
this
.
$refs
.
mergeRequestDropdown
)
.
on
(
'
show.bs.dropdown
'
,
()
=>
{
this
.
toggleMergeRequestDropdown
();
}).
on
(
'
hide.bs.dropdown
'
,
()
=>
{
this
.
toggleMergeRequestDropdown
();
});
},
toggleMergeRequestDropdown
()
{
this
.
showMergeRequestsDropdown
=
!
this
.
showMergeRequestsDropdown
;
},
},
};
</
script
>
...
...
@@ -108,12 +47,10 @@ export default {
:collapsible=
"false"
:initial-width=
"340"
side=
"left"
class=
"flex-column"
>
<activity-bar
v-if=
"!loading"
/>
<div
class=
"multi-file-commit-panel-inner"
>
<template
v-if=
"loading"
>
<template
v-if=
"loading"
>
<div
class=
"multi-file-commit-panel-inner"
>
<div
v-for=
"n in 3"
:key=
"n"
...
...
@@ -121,81 +58,23 @@ export default {
>
<skeleton-loading-container
/>
</div>
</
template
>
<
template
v-else
>
<div
ref=
"mergeRequestDropdown"
class=
"context-header ide-context-header dropdown"
>
<button
type=
"button"
data-toggle=
"dropdown"
>
<div
v-if=
"currentProject.avatar_url"
class=
"avatar-container s40 project-avatar"
>
<project-avatar-image
:link-href=
"currentProject.path"
:img-src=
"currentProject.avatar_url"
:img-alt=
"currentProject.name"
:img-size=
"40"
class=
"avatar-container project-avatar"
/>
</div>
<identicon
v-else
:entity-id=
"currentProject.id"
:entity-name=
"currentProject.name"
size-class=
"s40"
</div>
</
template
>
<
template
v-else
>
<ide-project-header
:project=
"currentProject"
/>
<div
class=
"ide-context-body d-flex flex-fill"
>
<activity-bar
/>
<div
class=
"multi-file-commit-panel-inner"
>
<div
class=
"multi-file-commit-panel-inner-content"
>
<component
:is=
"currentActivityView"
/>
<div
class=
"ide-sidebar-project-title"
>
<div
class=
"sidebar-context-title"
>
{{
currentProject
.
name
}}
</div>
<div
class=
"d-flex"
>
<div
v-tooltip
v-if=
"currentBranchId"
ref=
"branchId"
:title=
"branchTooltipTitle"
class=
"sidebar-context-title ide-sidebar-branch-title"
>
<icon
name=
"branch"
css-classes=
"append-right-5"
/>
{{
currentBranchId
}}
</div>
<div
v-if=
"currentMergeRequestId"
:class=
"
{
'prepend-left-8': currentBranchId
}"
class="sidebar-context-title ide-sidebar-branch-title"
>
<icon
name=
"git-merge"
css-classes=
"append-right-5"
/>
!
{{
currentMergeRequestId
}}
</div>
</div>
</div>
<icon
class=
"ml-auto"
name=
"chevron-down"
/>
</button>
<merge-request-dropdown
:show=
"showMergeRequestsDropdown"
/>
</div>
<div
class=
"multi-file-commit-panel-inner-scroll"
>
<component
:is=
"currentActivityView"
/>
</div>
<commit-form
/>
</div>
<commit-form
/>
</
template
>
</div>
</div>
</
template
>
</resizable-panel>
</template>
app/assets/javascripts/ide/components/ide_tree.vue
View file @
db739548
...
...
@@ -35,7 +35,6 @@ export default {
<
template
>
<ide-tree-list
header-class=
"d-flex w-100"
viewer-type=
"editor"
>
<template
...
...
app/assets/javascripts/ide/components/ide_tree_list.vue
View file @
db739548
...
...
@@ -59,12 +59,16 @@ export default {
>
<slot
name=
"header"
></slot>
</header>
<repo-file
v-for=
"file in currentTree.tree"
:key=
"file.key"
:file=
"file"
:level=
"0"
/>
<div
class=
"ide-tree-body"
>
<repo-file
v-for=
"file in currentTree.tree"
:key=
"file.key"
:file=
"file"
:level=
"0"
/>
</div>
</
template
>
</div>
</template>
app/assets/javascripts/vue_shared/components/project_avatar/default.vue
0 → 100644
View file @
db739548
<
script
>
import
Identicon
from
'
../identicon.vue
'
;
import
ProjectAvatarImage
from
'
./image.vue
'
;
export
default
{
components
:
{
Identicon
,
ProjectAvatarImage
,
},
props
:
{
project
:
{
type
:
Object
,
required
:
true
,
},
size
:
{
type
:
Number
,
default
:
40
,
},
},
computed
:
{
sizeClass
()
{
return
`s
${
this
.
size
}
`
;
},
},
};
</
script
>
<
template
>
<span
:class=
"sizeClass"
class=
"avatar-container project-avatar"
>
<project-avatar-image
v-if=
"project.avatar_url"
:link-href=
"project.path"
:img-src=
"project.avatar_url"
:img-alt=
"project.name"
:img-size=
"size"
/>
<identicon
v-else
:entity-id=
"project.id"
:entity-name=
"project.name"
:size-class=
"sizeClass"
/>
</span>
</
template
>
app/assets/stylesheets/framework/avatar.scss
View file @
db739548
...
...
@@ -78,6 +78,7 @@
&
.s26
{
font-size
:
20px
;
line-height
:
1
.33
;
}
&
.s32
{
font-size
:
20px
;
line-height
:
30px
;
}
&
.s40
{
font-size
:
16px
;
line-height
:
38px
;
}
&
.s48
{
font-size
:
20px
;
line-height
:
46px
;
}
&
.s60
{
font-size
:
32px
;
line-height
:
58px
;
}
&
.s70
{
font-size
:
34px
;
line-height
:
70px
;
}
&
.s90
{
font-size
:
36px
;
line-height
:
88px
;
}
...
...
app/assets/stylesheets/framework/contextual_sidebar.scss
View file @
db739548
...
...
@@ -55,6 +55,11 @@
.sidebar-context-title
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
&
.text-secondary
{
font-weight
:
normal
;
font-size
:
0
.8em
;
}
}
}
...
...
app/assets/stylesheets/page_bundles/ide.scss
View file @
db739548
@import
'framework/variables'
;
@import
'framework/mixins'
;
$ide-activity-bar-width
:
60px
;
$ide-context-header-padding
:
10px
;
$ide-project-avatar-end
:
$ide-context-header-padding
+
48px
;
$ide-tree-padding
:
$gl-padding
;
$ide-tree-text-start
:
$ide-activity-bar-width
+
$ide-tree-padding
;
.project-refs-form
,
.project-refs-target-form
{
display
:
inline-block
;
...
...
@@ -24,7 +30,6 @@
display
:
flex
;
height
:
calc
(
100vh
-
#{
$header-height
}
);
margin-top
:
0
;
border-top
:
1px
solid
$white-dark
;
padding-bottom
:
$ide-statusbar-height
;
color
:
$gl-text-color
;
...
...
@@ -41,10 +46,10 @@
}
.ide-file-list
{
display
:
flex
;
flex-direction
:
column
;
flex
:
1
;
padding-left
:
$gl-padding
;
padding-right
:
$gl-padding
;
padding-bottom
:
$grid-size
;
overflow
:
hidden
;
.file
{
height
:
32px
;
...
...
@@ -517,17 +522,12 @@
>
a
,
>
button
{
height
:
60px
;
text-decoration
:
none
;
padding-top
:
$gl-padding-8
;
padding-bottom
:
$gl-padding-8
;
}
}
.projects-sidebar
{
min-height
:
0
;
display
:
flex
;
flex-direction
:
column
;
flex
:
1
;
}
.multi-file-commit-panel-inner
{
position
:
relative
;
display
:
flex
;
...
...
@@ -537,11 +537,11 @@
width
:
100%
;
}
.multi-file-commit-panel-inner-
scroll
{
.multi-file-commit-panel-inner-
content
{
display
:
flex
;
flex
:
1
;
flex-direction
:
column
;
overflow
:
auto
;
overflow
:
hidden
;
background-color
:
$white-light
;
border-left
:
1px
solid
$white-dark
;
border-top
:
1px
solid
$white-dark
;
...
...
@@ -803,12 +803,6 @@
height
:
calc
(
100vh
-
#{
$header-height
+
$flash-height
}
);
}
}
.projects-sidebar
{
.multi-file-commit-panel-inner-scroll
{
flex
:
1
;
}
}
}
}
...
...
@@ -964,7 +958,7 @@
.ide-activity-bar
{
position
:
relative
;
flex
:
0
0
60px
;
flex
:
0
0
$ide-activity-bar-width
;
z-index
:
1
;
}
...
...
@@ -1060,10 +1054,12 @@
}
.ide-tree-header
{
flex
:
0
0
auto
;
display
:
flex
;
align-items
:
center
;
margin-bottom
:
8px
;
padding
:
12px
0
;
margin-left
:
$ide-tree-padding
;
margin-right
:
$ide-tree-padding
;
border-bottom
:
1px
solid
$white-dark
;
.ide-new-btn
{
...
...
@@ -1075,6 +1071,12 @@
}
}
.ide-tree-body
{
overflow
:
auto
;
padding-left
:
$ide-tree-padding
;
padding-right
:
$ide-tree-padding
;
}
.ide-sidebar-branch-title
{
font-weight
:
$gl-font-weight-normal
;
...
...
@@ -1163,14 +1165,23 @@
}
.ide-context-header
{
.avatar
{
flex
:
0
0
38px
;
}
.ide-merge-requests-dropdown.dropdown-menu
{
width
:
385px
;
max-height
:
initial
;
}
.avatar-container
{
flex
:
initial
;
margin-right
:
0
;
}
.ide-sidebar-project-title
{
margin-left
:
$ide-tree-text-start
-
$ide-project-avatar-end
;
}
}
.ide-context-body
{
overflow
:
hidden
;
}
.ide-sidebar-project-title
{
...
...
@@ -1178,10 +1189,11 @@
.sidebar-context-title
{
white-space
:
nowrap
;
}
display
:
block
;
.ide-sidebar-branch-title
{
min-width
:
50px
;
&
.text-secondary
{
font-weight
:
normal
;
}
}
}
...
...
changelogs/unreleased/47768-web-ide-redesign-header.yml
0 → 100644
View file @
db739548
---
title
:
Redesign Web IDE back button and context header
merge_request
:
20850
author
:
type
:
changed
locale/gitlab.pot
View file @
db739548
...
...
@@ -2911,7 +2911,7 @@ msgstr ""
msgid "IDE|Edit"
msgstr ""
msgid "IDE|Go
back
"
msgid "IDE|Go
to project
"
msgstr ""
msgid "IDE|Open in file view"
...
...
spec/javascripts/ide/components/activity_bar_spec.js
View file @
db739548
...
...
@@ -24,26 +24,6 @@ describe('IDE activity bar', () => {
resetStore
(
vm
.
$store
);
});
describe
(
'
goBackUrl
'
,
()
=>
{
it
(
'
renders the Go Back link with the referrer when present
'
,
()
=>
{
const
fakeReferrer
=
'
/example/README.md
'
;
spyOnProperty
(
document
,
'
referrer
'
).
and
.
returnValue
(
fakeReferrer
);
vm
.
$mount
();
expect
(
vm
.
goBackUrl
).
toEqual
(
fakeReferrer
);
});
it
(
'
renders the Go Back link with the project url when referrer is not present
'
,
()
=>
{
const
fakeReferrer
=
''
;
spyOnProperty
(
document
,
'
referrer
'
).
and
.
returnValue
(
fakeReferrer
);
vm
.
$mount
();
expect
(
vm
.
goBackUrl
).
toEqual
(
'
testing
'
);
});
});
describe
(
'
updateActivityBarView
'
,
()
=>
{
beforeEach
(()
=>
{
spyOn
(
vm
,
'
updateActivityBarView
'
);
...
...
spec/javascripts/vue_shared/components/project_avatar/default_spec.js
0 → 100644
View file @
db739548
import
Vue
from
'
vue
'
;
import
ProjectAvatarDefault
from
'
~/vue_shared/components/project_avatar/default.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
projectData
}
from
'
spec/ide/mock_data
'
;
import
{
getFirstCharacterCapitalized
}
from
'
~/lib/utils/text_utility
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
describe
(
'
ProjectAvatarDefault component
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
ProjectAvatarDefault
);
let
vm
;
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
project
:
projectData
,
});
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
it
(
'
renders identicon if project has no avatar_url
'
,
done
=>
{
const
expectedText
=
getFirstCharacterCapitalized
(
projectData
.
name
);
vm
.
project
=
{
...
vm
.
project
,
avatar_url
:
null
,
};
vm
.
$nextTick
()
.
then
(()
=>
{
const
identiconEl
=
vm
.
$el
.
querySelector
(
'
.identicon
'
);
expect
(
identiconEl
).
not
.
toBe
(
null
);
expect
(
identiconEl
.
textContent
.
trim
()).
toEqual
(
expectedText
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
it
(
'
renders avatar image if project has avatar_url
'
,
done
=>
{
const
avatarUrl
=
`
${
TEST_HOST
}
/images/home/nasa.svg`
;
vm
.
project
=
{
...
vm
.
project
,
avatar_url
:
avatarUrl
,
};
vm
.
$nextTick
()
.
then
(()
=>
{
expect
(
vm
.
$el
).
toContainElement
(
'
.avatar
'
);
expect
(
vm
.
$el
).
not
.
toContainElement
(
'
.identicon
'
);
expect
(
vm
.
$el
.
querySelector
(
'
img
'
)).
toHaveAttr
(
'
src
'
,
avatarUrl
);
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
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