Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
GitLab
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
projects.thm.de
GitLab
Commits
ec4ad656
Commit
ec4ad656
authored
Sep 06, 2018
by
Dennis Tang
Committed by
Phil Hughes
Sep 06, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Resolve "Improve project overview UI"
parent
d32cec18
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
705 additions
and
354 deletions
+705
-354
app/assets/javascripts/pages/projects/project.js
app/assets/javascripts/pages/projects/project.js
+35
-22
app/assets/javascripts/pages/projects/show/index.js
app/assets/javascripts/pages/projects/show/index.js
+4
-1
app/assets/javascripts/read_more.js
app/assets/javascripts/read_more.js
+41
-0
app/assets/stylesheets/framework.scss
app/assets/stylesheets/framework.scss
+1
-0
app/assets/stylesheets/framework/mobile.scss
app/assets/stylesheets/framework/mobile.scss
+2
-6
app/assets/stylesheets/framework/read_more.scss
app/assets/stylesheets/framework/read_more.scss
+13
-0
app/assets/stylesheets/framework/variables.scss
app/assets/stylesheets/framework/variables.scss
+1
-0
app/assets/stylesheets/pages/projects.scss
app/assets/stylesheets/pages/projects.scss
+148
-87
app/helpers/button_helper.rb
app/helpers/button_helper.rb
+5
-4
app/helpers/icons_helper.rb
app/helpers/icons_helper.rb
+2
-2
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+4
-0
app/helpers/visibility_level_helper.rb
app/helpers/visibility_level_helper.rb
+1
-1
app/presenters/project_presenter.rb
app/presenters/project_presenter.rb
+92
-66
app/views/projects/_home_panel.html.haml
app/views/projects/_home_panel.html.haml
+55
-28
app/views/projects/_stat_anchor_list.html.haml
app/views/projects/_stat_anchor_list.html.haml
+1
-1
app/views/projects/buttons/_fork.html.haml
app/views/projects/buttons/_fork.html.haml
+15
-15
app/views/projects/buttons/_star.html.haml
app/views/projects/buttons/_star.html.haml
+14
-16
app/views/projects/empty.html.haml
app/views/projects/empty.html.haml
+11
-7
app/views/projects/show.html.haml
app/views/projects/show.html.haml
+7
-2
app/views/shared/_clone_panel.html.haml
app/views/shared/_clone_panel.html.haml
+3
-3
app/views/shared/_mobile_clone_panel.html.haml
app/views/shared/_mobile_clone_panel.html.haml
+13
-0
changelogs/unreleased/44704-improve-project-overview-ui.yml
changelogs/unreleased/44704-improve-project-overview-ui.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+38
-19
qa/qa/page/project/show.rb
qa/qa/page/project/show.rb
+2
-2
spec/features/projects/files/project_owner_creates_license_file_spec.rb
...projects/files/project_owner_creates_license_file_spec.rb
+1
-1
spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
...sees_link_to_create_license_file_in_empty_project_spec.rb
+1
-1
spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
...es/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+6
-6
spec/features/projects_spec.rb
spec/features/projects_spec.rb
+52
-4
spec/javascripts/fixtures/projects.rb
spec/javascripts/fixtures/projects.rb
+10
-0
spec/javascripts/read_more_spec.js
spec/javascripts/read_more_spec.js
+23
-0
spec/presenters/project_presenter_spec.rb
spec/presenters/project_presenter_spec.rb
+95
-58
spec/views/projects/_home_panel.html.haml_spec.rb
spec/views/projects/_home_panel.html.haml_spec.rb
+4
-2
No files found.
app/assets/javascripts/pages/projects/project.js
View file @
ec4ad656
...
...
@@ -13,40 +13,52 @@ export default class Project {
constructor
()
{
const
$cloneOptions
=
$
(
'
ul.clone-options-dropdown
'
);
const
$projectCloneField
=
$
(
'
#project_clone
'
);
const
$cloneBtn
Text
=
$
(
'
a.clone-dropdown-btn span
'
);
const
$cloneBtn
Label
=
$
(
'
.js-git-clone-holder .js-clone-dropdown-label
'
);
const
selectedCloneOption
=
$cloneBtn
Text
.
text
().
trim
();
const
selectedCloneOption
=
$cloneBtn
Label
.
text
().
trim
();
if
(
selectedCloneOption
.
length
>
0
)
{
$
(
`a:contains('
${
selectedCloneOption
}
')`
,
$cloneOptions
).
addClass
(
'
is-active
'
);
}
$
(
'
a
'
,
$cloneOptions
).
on
(
'
click
'
,
(
e
)
=>
{
$
(
'
a
'
,
$cloneOptions
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
const
$this
=
$
(
e
.
currentTarget
);
const
url
=
$this
.
attr
(
'
href
'
);
const
activeText
=
$this
.
find
(
'
.dropdown-menu-inner-title
'
).
text
(
);
const
cloneType
=
$this
.
data
(
'
cloneType
'
);
e
.
preventDefault
();
$
(
'
.is-active
'
,
$cloneOptions
).
removeClass
(
'
is-active
'
);
$
(
`a[data-clone-type="
${
cloneType
}
"]`
).
each
(
function
()
{
const
$el
=
$
(
this
);
const
activeText
=
$el
.
find
(
'
.dropdown-menu-inner-title
'
).
text
();
const
$container
=
$el
.
closest
(
'
.project-clone-holder
'
);
const
$label
=
$container
.
find
(
'
.js-clone-dropdown-label
'
);
$
(
'
.is-active
'
,
$cloneOptions
).
not
(
$this
).
removeClass
(
'
is-active
'
);
$this
.
toggleClass
(
'
is-active
'
);
$projectCloneField
.
val
(
url
);
$cloneBtnText
.
text
(
activeText
);
$el
.
toggleClass
(
'
is-active
'
);
$label
.
text
(
activeText
);
});
return
$
(
'
.clone
'
).
text
(
url
);
$projectCloneField
.
val
(
url
);
$
(
'
.js-git-empty .js-clone
'
).
text
(
url
);
});
// Ref switcher
Project
.
initRefSwitcher
();
$
(
'
.project-refs-select
'
).
on
(
'
change
'
,
function
()
{
return
$
(
this
).
parents
(
'
form
'
).
submit
();
return
$
(
this
)
.
parents
(
'
form
'
)
.
submit
();
});
$
(
'
.hide-no-ssh-message
'
).
on
(
'
click
'
,
function
(
e
)
{
Cookies
.
set
(
'
hide_no_ssh_message
'
,
'
false
'
);
$
(
this
).
parents
(
'
.no-ssh-key-message
'
).
remove
();
$
(
this
)
.
parents
(
'
.no-ssh-key-message
'
)
.
remove
();
return
e
.
preventDefault
();
});
$
(
'
.hide-no-password-message
'
).
on
(
'
click
'
,
function
(
e
)
{
Cookies
.
set
(
'
hide_no_password_message
'
,
'
false
'
);
$
(
this
).
parents
(
'
.no-password-message
'
).
remove
();
$
(
this
)
.
parents
(
'
.no-password-message
'
)
.
remove
();
return
e
.
preventDefault
();
});
Project
.
projectSelectDropdown
();
...
...
@@ -58,7 +70,7 @@ export default class Project {
}
static
changeProject
(
url
)
{
return
window
.
location
=
url
;
return
(
window
.
location
=
url
)
;
}
static
initRefSwitcher
()
{
...
...
@@ -73,14 +85,15 @@ export default class Project {
selected
=
$dropdown
.
data
(
'
selected
'
);
return
$dropdown
.
glDropdown
({
data
(
term
,
callback
)
{
axios
.
get
(
$dropdown
.
data
(
'
refsUrl
'
),
{
params
:
{
ref
:
$dropdown
.
data
(
'
ref
'
),
search
:
term
,
},
})
.
then
(({
data
})
=>
callback
(
data
))
.
catch
(()
=>
flash
(
__
(
'
An error occurred while getting projects
'
)));
axios
.
get
(
$dropdown
.
data
(
'
refsUrl
'
),
{
params
:
{
ref
:
$dropdown
.
data
(
'
ref
'
),
search
:
term
,
},
})
.
then
(({
data
})
=>
callback
(
data
))
.
catch
(()
=>
flash
(
__
(
'
An error occurred while getting projects
'
)));
},
selectable
:
true
,
filterable
:
true
,
...
...
app/assets/javascripts/pages/projects/show/index.js
View file @
ec4ad656
...
...
@@ -8,15 +8,18 @@ import BlobViewer from '~/blob/viewer/index';
import
Activities
from
'
~/activities
'
;
import
{
ajaxGet
}
from
'
~/lib/utils/common_utils
'
;
import
GpgBadges
from
'
~/gpg_badges
'
;
import
initReadMore
from
'
~/read_more
'
;
import
Star
from
'
../../../star
'
;
import
notificationsDropdown
from
'
../../../notifications_dropdown
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
initReadMore
();
new
Star
();
// eslint-disable-line no-new
notificationsDropdown
();
new
ShortcutsNavigation
();
// eslint-disable-line no-new
new
NotificationsForm
();
// eslint-disable-line no-new
new
UserCallout
({
// eslint-disable-line no-new
// eslint-disable-next-line no-new
new
UserCallout
({
setCalloutPerProject
:
false
,
className
:
'
js-autodevops-banner
'
,
});
...
...
app/assets/javascripts/read_more.js
0 → 100644
View file @
ec4ad656
/**
* ReadMore
*
* Adds "read more" functionality to elements.
*
* Specifically, it looks for a trigger, by default ".js-read-more-trigger", and adds the class
* "is-expanded" to the previous element in order to provide a click to expand functionality.
*
* This is useful for long text elements that you would like to truncate, especially for mobile.
*
* Example Markup
* <div class="read-more-container">
* <p>Some text that should be long enough to have to truncate within a specified container.</p>
* <p>This text will not appear in the container, as only the first line can be truncated.</p>
* <p>This should also not appear, if everything is working correctly!</p>
* </div>
* <button class="js-read-more-trigger">Read more</button>
*
*/
export
default
function
initReadMore
(
triggerSelector
=
'
.js-read-more-trigger
'
)
{
const
triggerEls
=
document
.
querySelectorAll
(
triggerSelector
);
if
(
!
triggerEls
)
return
;
triggerEls
.
forEach
(
triggerEl
=>
{
const
targetEl
=
triggerEl
.
previousElementSibling
;
if
(
!
targetEl
)
{
return
;
}
triggerEl
.
addEventListener
(
'
click
'
,
e
=>
{
targetEl
.
classList
.
add
(
'
is-expanded
'
);
e
.
target
.
remove
();
},
{
once
:
true
},
);
});
}
app/assets/stylesheets/framework.scss
View file @
ec4ad656
...
...
@@ -64,3 +64,4 @@
@import
'framework/ci_variable_list'
;
@import
'framework/feature_highlight'
;
@import
'framework/terms'
;
@import
'framework/read_more'
;
app/assets/stylesheets/framework/mobile.scss
View file @
ec4ad656
...
...
@@ -44,12 +44,8 @@
.project-repo-buttons
{
display
:
block
;
.count-buttons
.btn
{
margin
:
0
10px
;
}
.count-buttons
.count-with-arrow
{
display
:
none
;
.count-buttons
.count-badge
{
margin-top
:
$gl-padding-8
;
}
}
}
...
...
app/assets/stylesheets/framework/read_more.scss
0 → 100644
View file @
ec4ad656
.read-more-container
{
@include
media-breakpoint-down
(
md
)
{
&
:not
(
.is-expanded
)
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
>
*
{
display
:
inline
;
}
}
}
}
app/assets/stylesheets/framework/variables.scss
View file @
ec4ad656
...
...
@@ -271,6 +271,7 @@ $performance-bar-height: 35px;
$flash-height
:
52px
;
$context-header-height
:
60px
;
$breadcrumb-min-height
:
48px
;
$project-title-row-height
:
24px
;
/*
* Common component specific colors
...
...
app/assets/stylesheets/pages/projects.scss
View file @
ec4ad656
...
...
@@ -115,7 +115,7 @@
.project-feature-controls
{
display
:
flex
;
align-items
:
center
;
margin
:
8px
0
;
margin
:
$gl-padding-8
0
;
max-width
:
432px
;
.toggle-wrapper
{
...
...
@@ -144,12 +144,8 @@
.group-home-panel
{
padding-top
:
24px
;
padding-bottom
:
24px
;
border-bottom
:
1px
solid
$border-color
;
@include
media-breakpoint-up
(
sm
)
{
border-bottom
:
1px
solid
$border-color
;
}
.project-avatar
,
.group-avatar
{
float
:
none
;
margin
:
0
auto
;
...
...
@@ -175,7 +171,6 @@
}
}
.project-home-desc
,
.group-home-desc
{
margin-left
:
auto
;
margin-right
:
auto
;
...
...
@@ -199,6 +194,62 @@
}
}
.project-home-panel
{
padding-top
:
$gl-padding-8
;
padding-bottom
:
$gl-padding-24
;
.project-title-row
{
margin-right
:
$gl-padding-8
;
}
.project-avatar
{
width
:
$project-title-row-height
;
height
:
$project-title-row-height
;
flex-shrink
:
0
;
flex-basis
:
$project-title-row-height
;
margin
:
0
$gl-padding-8
0
0
;
}
.project-title
{
font-size
:
20px
;
line-height
:
$project-title-row-height
;
font-weight
:
bold
;
}
.project-metadata
{
font-weight
:
normal
;
font-size
:
14px
;
line-height
:
$gl-btn-line-height
;
color
:
$gl-text-color-secondary
;
.icon
{
margin-right
:
$gl-padding-4
;
font-size
:
16px
;
}
.project-visibility
,
.project-license
,
.project-tag-list
{
margin-right
:
$gl-padding-8
;
}
.project-license
{
.btn
{
line-height
:
0
;
border-width
:
0
;
}
}
.project-tag-list
,
.project-license
{
.icon
{
position
:
relative
;
top
:
2px
;
}
}
}
}
.nav
>
.project-repo-buttons
{
margin-top
:
0
;
}
...
...
@@ -206,8 +257,6 @@
.project-repo-buttons
,
.group-buttons
{
.btn
{
padding
:
3px
10px
;
&
:last-child
{
margin-left
:
0
;
}
...
...
@@ -222,11 +271,15 @@
.fa-caret-down
{
margin-left
:
3px
;
&
.dropdown-btn-icon
{
margin-left
:
0
;
}
}
}
.project-action-button
{
margin
:
15px
5px
0
;
margin
:
$gl-padding
$gl-padding-8
0
0
;
vertical-align
:
top
;
}
...
...
@@ -243,82 +296,45 @@
.count-buttons
{
display
:
inline-block
;
vertical-align
:
top
;
margin-top
:
15px
;
}
margin-top
:
$gl-padding
;
.project-clone-holder
{
display
:
inline-block
;
margin
:
15px
5px
0
0
;
.count-badge
{
height
:
$input-height
;
input
{
height
:
28px
;
.icon
{
top
:
-1px
;
}
}
}
.count-with-arrow
{
display
:
inline-block
;
position
:
relative
;
margin-left
:
4px
;
.count-badge-count
,
.count-badge-button
{
border
:
1px
solid
$border-color
;
line-height
:
1
;
}
.arrow
{
&
::before
{
content
:
''
;
display
:
inline-block
;
position
:
absolute
;
width
:
0
;
height
:
0
;
border-color
:
transparent
;
border-style
:
solid
;
top
:
50%
;
left
:
0
;
margin-top
:
-6px
;
border-width
:
7px
5px
7px
0
;
border-right-color
:
$count-arrow-border
;
pointer-events
:
none
;
}
.count
,
.count-badge-button
{
color
:
$gl-text-color
;
}
&
::after
{
content
:
''
;
position
:
absolute
;
width
:
0
;
height
:
0
;
border-color
:
transparent
;
border-style
:
solid
;
top
:
50%
;
left
:
1px
;
margin-top
:
-9px
;
border-width
:
10px
7px
10px
0
;
border-right-color
:
$white-light
;
pointer-events
:
none
;
}
.count-badge-count
{
padding
:
0
12px
;
border-right
:
0
;
border-radius
:
$border-radius-base
0
0
$border-radius-base
;
background
:
$gray-light
;
}
.count
{
@include
btn-white
;
display
:
inline-block
;
background
:
$white-light
;
border-radius
:
2px
;
border-width
:
1px
;
border-style
:
solid
;
font-size
:
13px
;
font-weight
:
$gl-font-weight-bold
;
line-height
:
13px
;
letter-spacing
:
0
.4px
;
padding
:
6px
14px
;
text-align
:
center
;
vertical-align
:
middle
;
touch-action
:
manipulation
;
background-image
:
none
;
white-space
:
nowrap
;
margin
:
0
10px
0
4px
;
.count-badge-button
{
border-radius
:
0
$border-radius-base
$border-radius-base
0
;
}
}
a
{
color
:
inherit
;
}
.project-clone-holder
{
display
:
inline-block
;
margin
:
$gl-padding
$gl-padding-8
0
0
;
&
:hover
{
background
:
$white-light
;
}
input
{
height
:
$input-height
;
}
}
...
...
@@ -333,6 +349,14 @@
min-width
:
320px
;
}
}
.mobile-git-clone
{
margin-top
:
$gl-padding-8
;
.dropdown-menu-inner-content
{
@extend
.monospace
;
}
}
}
.split-one
{
...
...
@@ -511,7 +535,6 @@
.controls
{
margin-left
:
auto
;
}
}
.choose-template
{
...
...
@@ -574,7 +597,7 @@
flex-wrap
:
wrap
;
.btn
{
padding
:
8px
;
padding
:
$gl-padding-8
;
margin-right
:
10px
;
}
...
...
@@ -651,7 +674,7 @@
left
:
-10px
;
top
:
50%
;
z-index
:
10
;
padding
:
8px
0
;
padding
:
$gl-padding-8
0
;
text-align
:
center
;
background-color
:
$white-light
;
color
:
$gl-text-color-tertiary
;
...
...
@@ -665,7 +688,7 @@
left
:
50%
;
top
:
0
;
transform
:
translateX
(
-50%
);
padding
:
0
8px
;
padding
:
0
$gl-padding-8
;
}
}
...
...
@@ -699,17 +722,51 @@
.project-stats
{
font-size
:
0
;
text-align
:
center
;
max-width
:
100%
;
border-bottom
:
1px
solid
$border-color
;
.nav
{
margin-top
:
$gl-padding-8
;
margin-bottom
:
$gl-padding-8
;
.scrolling-tabs-container
{
.scrolling-tabs
{
margin-top
:
$gl-padding-8
;
margin-bottom
:
$gl-padding-8
;
flex-wrap
:
wrap
;
border-bottom
:
0
;
}
.fade-left
,
.fade-right
{
top
:
0
;
height
:
100%
;
.fa
{
top
:
50%
;
margin-top
:
-
$gl-padding-8
;
}
}
.nav
{
flex-basis
:
100%
;
+
.nav
{
margin
:
$gl-padding-8
0
;
}
}
@include
media-breakpoint-down
(
md
)
{
flex-direction
:
column
;
.nav
{
flex-wrap
:
nowrap
;
}
.nav
:first-child
{
margin-right
:
$gl-padding-8
;
}
}
}
.nav
{
>
li
{
display
:
inline-block
;
margin-top
:
$gl-padding-4
;
margin-bottom
:
$gl-padding-4
;
&
:not
(
:last-child
)
{
margin-right
:
$gl-padding
;
...
...
@@ -732,13 +789,17 @@
font-size
:
$gl-font-size
;
line-height
:
$gl-btn-line-height
;
color
:
$gl-text-color-secondary
;
white-space
:
nowrap
;
}
.stat-link
{
border-bottom
:
0
;
&
:hover
,
&
:focus
{
color
:
$gl-text-color
;
text-decoration
:
underline
;
border-bottom
:
0
;
}
}
...
...
@@ -868,7 +929,7 @@ pre.light-well {
}
.git-clone-holder
{
width
:
3
8
0px
;
width
:
3
2
0px
;
.btn-clipboard
{
border
:
1px
solid
$border-color
;
...
...
app/helpers/button_helper.rb
View file @
ec4ad656
...
...
@@ -61,7 +61,7 @@ def http_clone_button(project, append_link: true)
dropdown_description
=
http_dropdown_description
(
protocol
)
append_url
=
project
.
http_url_to_repo
if
append_link
dropdown_item_with_description
(
protocol
,
dropdown_description
,
href:
append_url
)
dropdown_item_with_description
(
protocol
,
dropdown_description
,
href:
append_url
,
data:
{
clone_type:
'http'
}
)
end
def
http_dropdown_description
(
protocol
)
...
...
@@ -80,16 +80,17 @@ def ssh_clone_button(project, append_link: true)
append_url
=
project
.
ssh_url_to_repo
if
append_link
dropdown_item_with_description
(
'SSH'
,
dropdown_description
,
href:
append_url
)
dropdown_item_with_description
(
'SSH'
,
dropdown_description
,
href:
append_url
,
data:
{
clone_type:
'ssh'
}
)
end
def
dropdown_item_with_description
(
title
,
description
,
href:
nil
)
def
dropdown_item_with_description
(
title
,
description
,
href:
nil
,
data:
nil
)
button_content
=
content_tag
(
:strong
,
title
,
class:
'dropdown-menu-inner-title'
)
button_content
<<
content_tag
(
:span
,
description
,
class:
'dropdown-menu-inner-content'
)
if
description
content_tag
(
href
?
:a
:
:span
),
(
href
?
button_content
:
title
),
class:
"
#{
title
.
downcase
}
-selector"
,
href:
(
href
if
href
)
href:
(
href
if
href
),
data:
(
data
if
data
)
end
end
app/helpers/icons_helper.rb
View file @
ec4ad656
...
...
@@ -86,7 +86,7 @@ def boolean_to_icon(value)
end
end
def
visibility_level_icon
(
level
,
fw:
true
)
def
visibility_level_icon
(
level
,
fw:
true
,
options:
{}
)
name
=
case
level
when
Gitlab
::
VisibilityLevel
::
PRIVATE
...
...
@@ -99,7 +99,7 @@ def visibility_level_icon(level, fw: true)
name
<<
" fw"
if
fw
icon
(
name
)
icon
(
name
,
options
)
end
def
file_type_icon_class
(
type
,
mode
,
name
)
...
...
app/helpers/projects_helper.rb
View file @
ec4ad656
...
...
@@ -351,6 +351,10 @@ def default_url_to_repo(project = @project)
end
end
def
default_clone_label
_
(
"Copy %{protocol} clone URL"
)
%
{
protocol:
default_clone_protocol
.
upcase
}
end
def
default_clone_protocol
if
allowed_protocols_present?
enabled_protocol
...
...
app/helpers/visibility_level_helper.rb
View file @
ec4ad656
...
...
@@ -138,7 +138,7 @@ def group_visibility_icon_description(level)
end