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
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 @@ module ButtonHelper
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 @@ module ButtonHelper
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 @@ module IconsHelper
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 @@ module IconsHelper
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 @@ module ProjectsHelper
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 @@ module VisibilityLevelHelper
end
def
project_visibility_icon_description
(
level
)
"
#{
visibility_level_label
(
level
)
}
-
#{
project_visibility_level_description
(
level
)
}
"
"
#{
project_visibility_level_description
(
level
)
}
"
end
def
visibility_level_label
(
level
)
...
...
app/presenters/project_presenter.rb
View file @
ec4ad656
...
...
@@ -11,16 +11,18 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
presents
:project
AnchorData
=
Struct
.
new
(
:enabled
,
:label
,
:link
,
:class_modifier
)
MAX_TAGS_TO_SHOW
=
3
def
statistics_anchors
(
show_auto_devops_callout
:)
[
readme_anchor_data
,
changelog_anchor_data
,
contribution_guide_anchor_data
,
files_anchor_data
,
commits_anchor_data
,
branches_anchor_data
,
tags_anchor_data
,
readme_anchor_data
,
changelog_anchor_data
,
license_anchor_data
,
contribution_guide_anchor_data
,
gitlab_ci_anchor_data
,
autodevops_anchor_data
(
show_auto_devops_callout:
show_auto_devops_callout
),
kubernetes_cluster_anchor_data
...
...
@@ -31,7 +33,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
[
readme_anchor_data
,
changelog_anchor_data
,
license_anchor_data
,
contribution_guide_anchor_data
,
autodevops_anchor_data
(
show_auto_devops_callout:
show_auto_devops_callout
),
kubernetes_cluster_anchor_data
,
...
...
@@ -42,6 +43,10 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
def
empty_repo_statistics_anchors
[
files_anchor_data
,
commits_anchor_data
,
branches_anchor_data
,
tags_anchor_data
,
autodevops_anchor_data
,
kubernetes_cluster_anchor_data
].
compact
.
select
{
|
item
|
item
.
enabled
}
...
...
@@ -51,7 +56,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
[
new_file_anchor_data
,
readme_anchor_data
,
license_anchor_data
,
autodevops_anchor_data
,
kubernetes_cluster_anchor_data
].
compact
.
reject
{
|
item
|
item
.
enabled
}
...
...
@@ -182,95 +186,101 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def
files_anchor_data
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'Files (%{human_size})'
)
%
{
human_size:
storage_counter
(
statistics
.
total_repository_size
)
},
link
:
project_tree_path
(
project
))
AnchorData
.
new
(
true
,
_
(
'Files (%{human_size})'
)
%
{
human_size:
storage_counter
(
statistics
.
total_repository_size
)
},
empty_repo?
?
nil
:
project_tree_path
(
project
))
end
def
commits_anchor_data
OpenStruct
.
new
(
enabled:
true
,
label:
n_
(
'Commit (%{commit_count})'
,
'Commits (%{commit_count})'
,
statistics
.
commit_count
)
%
{
commit_count:
number_with_delimiter
(
statistics
.
commit_count
)
},
link
:
project_commits_path
(
project
,
repository
.
root_ref
))
AnchorData
.
new
(
true
,
n_
(
'Commit (%{commit_count})'
,
'Commits (%{commit_count})'
,
statistics
.
commit_count
)
%
{
commit_count:
number_with_delimiter
(
statistics
.
commit_count
)
},
empty_repo?
?
nil
:
project_commits_path
(
project
,
repository
.
root_ref
))
end
def
branches_anchor_data
OpenStruct
.
new
(
enabled:
true
,
label:
n_
(
'Branch (%{branch_count})'
,
'Branches (%{branch_count})'
,
repository
.
branch_count
)
%
{
branch_count:
number_with_delimiter
(
repository
.
branch_count
)
},
link
:
project_branches_path
(
project
))
AnchorData
.
new
(
true
,
n_
(
'Branch (%{branch_count})'
,
'Branches (%{branch_count})'
,
repository
.
branch_count
)
%
{
branch_count:
number_with_delimiter
(
repository
.
branch_count
)
},
empty_repo?
?
nil
:
project_branches_path
(
project
))
end
def
tags_anchor_data
OpenStruct
.
new
(
enabled:
true
,
label:
n_
(
'Tag (%{tag_count})'
,
'Tags (%{tag_count})'
,
repository
.
tag_count
)
%
{
tag_count:
number_with_delimiter
(
repository
.
tag_count
)
},
link
:
project_tags_path
(
project
))
AnchorData
.
new
(
true
,
n_
(
'Tag (%{tag_count})'
,
'Tags (%{tag_count})'
,
repository
.
tag_count
)
%
{
tag_count:
number_with_delimiter
(
repository
.
tag_count
)
},
empty_repo?
?
nil
:
project_tags_path
(
project
))
end
def
new_file_anchor_data
if
current_user
&&
can_current_user_push_to_default_branch?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'New file'
),
link:
project_new_blob_path
(
project
,
default_branch
||
'master'
),
class_modifier:
'new'
)
AnchorData
.
new
(
false
,
_
(
'New file'
),
project_new_blob_path
(
project
,
default_branch
||
'master'
),
'new'
)
end
end
def
readme_anchor_data
if
current_user
&&
can_current_user_push_to_default_branch?
&&
repository
.
readme
.
nil?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Add Readme'
),
link:
add_readme_path
)
AnchorData
.
new
(
false
,
_
(
'Add Readme'
),
add_readme_path
)
elsif
repository
.
readme
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'Readme'
),
link:
default_view
!=
'readme'
?
readme_path
:
'#readme'
)
AnchorData
.
new
(
true
,
_
(
'Readme'
),
default_view
!=
'readme'
?
readme_path
:
'#readme'
)
end
end
def
changelog_anchor_data
if
current_user
&&
can_current_user_push_to_default_branch?
&&
repository
.
changelog
.
blank?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Add Changelog'
),
link:
add_changelog_path
)
AnchorData
.
new
(
false
,
_
(
'Add Changelog'
),
add_changelog_path
)
elsif
repository
.
changelog
.
present?
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'Changelog'
),
link:
changelog_path
)
AnchorData
.
new
(
true
,
_
(
'Changelog'
),
changelog_path
)
end
end
def
license_anchor_data
if
current_user
&&
can_current_user_push_to_default_branch?
&&
repository
.
license_blob
.
blank?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Add License'
),
link:
add_license_path
)
elsif
repository
.
license_blob
.
present?
OpenStruct
.
new
(
enabled:
true
,
label:
license_short_name
,
link:
license_path
)
if
repository
.
license_blob
.
present?
AnchorData
.
new
(
true
,
license_short_name
,
license_path
)
else
if
current_user
&&
can_current_user_push_to_default_branch?
AnchorData
.
new
(
false
,
_
(
'Add license'
),
add_license_path
)
else
AnchorData
.
new
(
false
,
_
(
'No license. All rights reserved'
),
nil
)
end
end
end
def
contribution_guide_anchor_data
if
current_user
&&
can_current_user_push_to_default_branch?
&&
repository
.
contribution_guide
.
blank?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Add Contribution guide'
),
link:
add_contribution_guide_path
)
AnchorData
.
new
(
false
,
_
(
'Add Contribution guide'
),
add_contribution_guide_path
)
elsif
repository
.
contribution_guide
.
present?
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'Contribution guide'
),
link:
contribution_guide_path
)
AnchorData
.
new
(
true
,
_
(
'Contribution guide'
),
contribution_guide_path
)
end
end
def
autodevops_anchor_data
(
show_auto_devops_callout:
false
)
if
current_user
&&
can?
(
current_user
,
:admin_pipeline
,
project
)
&&
repository
.
gitlab_ci_yml
.
blank?
&&
!
show_auto_devops_callout
OpenStruct
.
new
(
enabled:
auto_devops_enabled?
,
label:
auto_devops_enabled?
?
_
(
'Auto DevOps enabled'
)
:
_
(
'Enable Auto DevOps'
),
link:
project_settings_ci_cd_path
(
project
,
anchor:
'autodevops-settings'
))
AnchorData
.
new
(
auto_devops_enabled?
,
auto_devops_enabled?
?
_
(
'Auto DevOps enabled'
)
:
_
(
'Enable Auto DevOps'
),
project_settings_ci_cd_path
(
project
,
anchor:
'autodevops-settings'
))
elsif
auto_devops_enabled?
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'Auto DevOps enabled'
),
link:
nil
)
AnchorData
.
new
(
true
,
_
(
'Auto DevOps enabled'
),
nil
)
end
end
...
...
@@ -282,32 +292,48 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
cluster_link
=
new_project_cluster_path
(
project
)
end
OpenStruct
.
new
(
enabled:
!
clusters
.
empty?
,
label:
clusters
.
empty?
?
_
(
'Add Kubernetes cluster'
)
:
_
(
'Kubernetes configured'
),
link:
cluster_link
)
AnchorData
.
new
(
!
clusters
.
empty?
,
clusters
.
empty?
?
_
(
'Add Kubernetes cluster'
)
:
_
(
'Kubernetes configured'
),
cluster_link
)
end
end
def
gitlab_ci_anchor_data
if
current_user
&&
can_current_user_push_code?
&&
repository
.
gitlab_ci_yml
.
blank?
&&
!
auto_devops_enabled?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Set up CI/CD'
),
link:
add_ci_yml_path
)
AnchorData
.
new
(
false
,
_
(
'Set up CI/CD'
),
add_ci_yml_path
)
elsif
repository
.
gitlab_ci_yml
.
present?
OpenStruct
.
new
(
enabled:
true
,
label:
_
(
'CI/CD configuration'
),
link:
ci_configuration_path
)
AnchorData
.
new
(
true
,
_
(
'CI/CD configuration'
),
ci_configuration_path
)
end
end
def
koding_anchor_data
if
current_user
&&
can_current_user_push_code?
&&
koding_enabled?
&&
repository
.
koding_yml
.
blank?
OpenStruct
.
new
(
enabled:
false
,
label:
_
(
'Set up Koding'
),
link:
add_koding_stack_path
)
AnchorData
.
new
(
false
,
_
(
'Set up Koding'
),
add_koding_stack_path
)
end
end
def
tags_to_show
project
.
tag_list
.
take
(
MAX_TAGS_TO_SHOW
)
end
def
count_of_extra_tags_not_shown
if
project
.
tag_list
.
count
>
MAX_TAGS_TO_SHOW
project
.
tag_list
.
count
-
MAX_TAGS_TO_SHOW
else
0
end
end
def
has_extra_tags?
count_of_extra_tags_not_shown
>
0
end
private
def
filename_path
(
filename
)
...
...
app/views/projects/_home_panel.html.haml
View file @
ec4ad656
-
empty_repo
=
@project
.
empty_repo?
.project-home-panel.text-center
{
class:
(
"empty-project"
if
empty_repo
)
}
-
license
=
@project
.
license_anchor_data
.project-home-panel
{
class:
(
"empty-project"
if
empty_repo
)
}
.limit-container-width
{
class:
container_class
}
.avatar-container.s70.project-avatar
=
project_icon
(
@project
,
alt:
@project
.
name
,
class:
'avatar s70 avatar-tile'
,
width:
70
,
height:
70
)
%h1
.project-title.qa-project-name
=
@project
.
name
%span
.visibility-icon.has-tooltip
{
data:
{
container:
'body'
},
title:
visibility_icon_description
(
@project
)
}
=
visibility_level_icon
(
@project
.
visibility_level
,
fw:
false
)
.project-header.d-flex.flex-row.flex-wrap.align-items-center.append-bottom-8
.project-title-row.d-flex.align-items-center
.avatar-container.project-avatar.float-none
=
project_icon
(
@project
,
alt:
@project
.
name
,
class:
'avatar avatar-tile'
)
%h1
.project-title.d-flex.align-items-baseline.qa-project-name
=
@project
.
name
.project-metadata.d-flex.flex-row.flex-wrap.align-items-baseline
.project-visibility.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip
{
data:
{
container:
'body'
},
title:
visibility_icon_description
(
@project
)
}
=
visibility_level_icon
(
@project
.
visibility_level
,
fw:
false
,
options:
{
class:
'icon'
})
=
visibility_level_label
(
@project
.
visibility_level
)
-
if
license
.
present?
.project-license.d-inline-flex.align-items-baseline
=
link_to_if
license
.
link
,
sprite_icon
(
'scale'
,
size:
16
,
css_class:
'icon'
)
+
license
.
label
,
license
.
link
,
class:
license
.
enabled
?
'btn btn-link btn-secondary-hover-link'
:
'btn btn-link'
-
if
@project
.
tag_list
.
present?
.project-tag-list.d-inline-flex.align-items-baseline.has-tooltip
{
data:
{
container:
'body'
},
title:
@project
.
has_extra_tags?
?
@project
.
tag_list
.
join
(
', '
)
:
nil
}
=
sprite_icon
(
'tag'
,
size:
16
,
css_class:
'icon'
)
=
@project
.
tags_to_show
-
if
@project
.
has_extra_tags?
=
_
(
"+ %{count} more"
)
%
{
count:
@project
.
count_of_extra_tags_not_shown
}
.project-home-desc
-
if
@project
.
description
.
present?
=
markdown_field
(
@project
,
:description
)
.project-description
.project-description-markdown.read-more-container
=
markdown_field
(
@project
,
:description
)
%button
.btn.btn-blank.btn-link.text-secondary.js-read-more-trigger.text-secondary.d-lg-none
{
type:
"button"
}
=
_
(
"Read more"
)
-
if
can?
(
current_user
,
:read_project
,
@project
)
.text-secondary.prepend-top-8
=
s_
(
'ProjectPage|Project ID: %{project_id}'
)
%
{
project_id:
@project
.
id
}
...
...
@@ -25,34 +44,42 @@
-
deleted_message
=
s_
(
'ForkedFromProjectPath|Forked from %{project_name} (deleted)'
)
=
deleted_message
%
{
project_name:
fork_source_name
(
@project
)
}
.project-badges.prepend-top-default.append-bottom-default
-
@project
.
badges
.
each
do
|
badge
|
%a
.append-right-8
{
href:
badge
.
rendered_link_url
(
@project
),
target:
'_blank'
,
rel:
'noopener noreferrer'
}
>
%img
.project-badge
{
src:
badge
.
rendered_image_url
(
@project
),
'aria-hidden'
:
true
,
alt:
''
}
>
.project-repo-buttons
.count-buttons
-
if
@project
.
badges
.
present?
.project-badges.prepend-top-default.append-bottom-default
-
@project
.
badges
.
each
do
|
badge
|
%a
.append-right-8
{
href:
badge
.
rendered_link_url
(
@project
),
target:
'_blank'
,
rel:
'noopener noreferrer'
}
>
%img
.project-badge
{
src:
badge
.
rendered_image_url
(
@project
),
'aria-hidden'
:
true
,
alt:
'Project badge'
}
>
.project-repo-buttons.d-inline-flex.flex-wrap
.count-buttons.d-inline-flex
=
render
'projects/buttons/star'
=
render
'projects/buttons/fork'
%span
.d-none.d-sm-inline
-
if
can?
(
current_user
,
:download_code
,
@project
)
.project-clone-holder
=
render
"shared/clone_panel"
-
if
can?
(
current_user
,
:download_code
,
@project
)
.project-clone-holder.d-inline-flex.d-sm-none
=
render
"shared/mobile_clone_panel"
-
if
show_xcode_link?
(
@project
)
.project-action-button.project-xcode.inline
=
render
"projects/buttons/xcode_link"
.project-clone-holder.d-none.d-sm-inline-flex
=
render
"shared/clone_panel"
-
if
current_user
-
if
can?
(
current_user
,
:download_code
,
@project
)
-
if
show_xcode_link?
(
@project
)
.project-action-button.project-xcode.inline
=
render
"projects/buttons/xcode_link"
-
if
current_user
-
if
can?
(
current_user
,
:download_code
,
@project
)
.d-none.d-sm-inline-flex
=
render
'projects/buttons/download'
,
project:
@project
,
ref:
@ref
.d-none.d-sm-inline-flex
=
render
'projects/buttons/dropdown'
.d-none.d-sm-inline-flex
=
render
'projects/buttons/koding'
.d-none.d-sm-inline-flex
=
render
'shared/notifications/button'
,
notification_setting:
@notification_setting
.d-none.d-sm-inline-flex
=
render
'shared/members/access_request_buttons'
,
source:
@project
app/views/projects/_stat_anchor_list.html.haml
View file @
ec4ad656
-
anchors
=
local_assigns
.
fetch
(
:anchors
,
[])
-
return
unless
anchors
.
any?
%ul
.nav
.justify-content-center
%ul
.nav
-
anchors
.
each
do
|
anchor
|
%li
.nav-item
=
link_to_if
anchor
.
link
,
anchor
.
label
,
anchor
.
link
,
class:
anchor
.
enabled
?
'nav-link stat-link'
:
"nav-link btn btn-
#{
anchor
.
class_modifier
||
'missing'
}
"
do
...
...
app/views/projects/buttons/_fork.html.haml
View file @
ec4ad656
-
unless
@project
.
empty_repo?
-
if
current_user
&&
can?
(
current_user
,
:fork_project
,
@project
)
-
if
current_user
.
already_forked?
(
@project
)
&&
current_user
.
manageable_namespaces
.
size
<
2
=
link_to
namespace_project_path
(
current_user
,
current_user
.
fork_of
(
@project
)),
title:
_
(
'Go to your fork'
),
class:
'btn has-tooltip'
do
=
custom_icon
(
'icon_fork'
)
%span
=
s_
(
'GoToYourFork|Fork'
)
-
else
-
can_create_fork
=
current_user
.
can?
(
:create_fork
)
=
link_to
new_project_fork_path
(
@project
),
class:
"btn btn-default
#{
'has-tooltip disabled'
unless
can_create_fork
}
"
,
title:
(
_
(
'You have reached your project limit'
)
unless
can_create_fork
)
do
=
custom_icon
(
'icon_fork'
)
%span
=
s_
(
'CreateNewFork|Fork'
)
.count-with-arrow
%span
.arrow
=
link_to
project_forks_path
(
@project
),
title:
n_
(
'Fork'
,
'Forks'
,
@project
.
forks_count
),
class:
'count'
do
=
@project
.
forks_count
.count-badge.d-inline-flex.align-item-stretch.append-right-8
%span
.fork-count.count-badge-count.d-flex.align-items-center
=
link_to
project_forks_path
(
@project
),
title:
n_
(
s_
(
'ProjectOverview|Fork'
),
s_
(
'ProjectOverview|Forks'
),
@project
.
forks_count
),
class:
'count'
do
=
@project
.
forks_count
-
if
current_user
.
already_forked?
(
@project
)
&&
current_user
.
manageable_namespaces
.
size
<
2
=
link_to
namespace_project_path
(
current_user
,
current_user
.
fork_of
(
@project
)),
title:
s_
(
'ProjectOverview|Go to your fork'
),
class:
'btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn'
do
=
sprite_icon
(
'fork'
,
{
css_class:
'icon'
})
%span
=
s_
(
'ProjectOverview|Fork'
)
-
else
-
can_create_fork
=
current_user
.
can?
(
:create_fork
)
=
link_to
new_project_fork_path
(
@project
),
class:
"btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn
#{
'has-tooltip disabled'
unless
can_create_fork
}
"
,
title:
(
s_
(
'ProjectOverview|You have reached your project limit'
)
unless
can_create_fork
)
do
=
sprite_icon
(
'fork'
,
{
css_class:
'icon'
})
%span
=
s_
(
'ProjectOverview|Fork'
)
app/views/projects/buttons/_star.html.haml
View file @
ec4ad656
-
if
current_user
%button
.btn.btn-default.star-btn.toggle-star
{
type:
"button"
,
data:
{
endpoint:
toggle_star_project_path
(
@project
,
:json
)
}
}
>
-
if
current_user
.
starred?
(
@project
)
=
sprite_icon
(
'star'
)
%span
.starred
=
_
(
'Unstar'
)
-
else
=
sprite_icon
(
'star-o'
)
%span
=
s_
(
'StarProject|Star'
)
.count-with-arrow
%span
.arrow
%span
.count.star-count
.count-badge.d-inline-flex.align-item-stretch.append-right-8
%span
.star-count.count-badge-count.d-flex.align-items-center
=
@project
.
star_count
%button
.count-badge-button.btn.btn-default.d-flex.align-items-center.star-btn.toggle-star
{
type:
"button"
,
data:
{
endpoint:
toggle_star_project_path
(
@project
,
:json
)
}
}
-
if
current_user
.
starred?
(
@project
)
=
sprite_icon
(
'star'
,
{
css_class:
'icon'
})
%span
.starred
=
s_
(
'ProjectOverview|Unstar'
)
-
else
=
sprite_icon
(
'star-o'
,
{
css_class:
'icon'
})
%span
=
s_
(
'ProjectOverview|Star'
)
-
else
=
link_to
new_user_session_path
,
class:
'btn has-tooltip star-btn'
,
title:
_
(
'You must sign in to star a project'
)
do
=
sprite_icon
(
'star'
)
#{
s_
(
'StarProject|Star'
)
}
.count-with-arrow
%span
.arrow
%span
.count
.count-badge.d-inline-flex.align-item-stretch.append-right-8
%span
.star-count.count-badge-count.d-flex.align-items-center
=
@project
.
star_count
=
link_to
new_user_session_path
,
class:
'btn btn-default has-tooltip count-badge-button d-flex align-items-center star-btn'
,
title:
s_
(
'ProjectOverview|You must sign in to star a project'
)
do
=
sprite_icon
(
'star-o'
,
{
css_class:
'icon'
})
%span
=
s_
(
'ProjectOverview|Star'
)
app/views/projects/empty.html.haml
View file @
ec4ad656
...
...
@@ -32,9 +32,13 @@
=
_
(
'Otherwise it is recommended you start with one of the options below.'
)
.prepend-top-20
%nav
.project-stats
{
class:
container_class
}
=
render
'stat_anchor_list'
,
anchors:
@project
.
empty_repo_statistics_anchors
=
render
'stat_anchor_list'
,
anchors:
@project
.
empty_repo_statistics_buttons
%nav
.project-stats
{
class:
[
container_class
,
(
"limit-container-width"
unless
fluid_layout
)]
}
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left
=
icon
(
'angle-left'
)
.fade-right
=
icon
(
'angle-right'
)
.nav-links.scrolling-tabs
=
render
'stat_anchor_list'
,
anchors:
@project
.
empty_repo_statistics_anchors
=
render
'stat_anchor_list'
,
anchors:
@project
.
empty_repo_statistics_buttons
-
if
can?
(
current_user
,
:push_code
,
@project
)
%div
{
class:
[
container_class
,
(
"limit-container-width"
unless
fluid_layout
)]
}
...
...
@@ -42,7 +46,7 @@
.empty_wrapper
%h3
#repo-command-line-instructions
.page-title-empty
Command line instructions
.git-empty
.git-empty
.js-git-empty
%fieldset
%h5
Git global setup
%pre
.bg-light
...
...
@@ -54,7 +58,7 @@
%h5
Create a new repository
%pre
.bg-light
:preserve
git clone
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'clone'
)
}
git clone
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'
js-
clone'
)
}
cd
#{
h
@project
.
path
}
touch README.md
git add README.md
...
...
@@ -69,7 +73,7 @@
:preserve
cd existing_folder
git init
git remote add origin
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'clone'
)
}
git remote add origin
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'
js-
clone'
)
}
git add .
git commit -m "Initial commit"
-
if
@project
.
can_current_user_push_to_default_branch?
...
...
@@ -82,7 +86,7 @@
:preserve
cd existing_repo
git remote rename origin old-origin
git remote add origin
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'clone'
)
}
git remote add origin
#{
content_tag
(
:span
,
default_url_to_repo
,
class:
'
js-
clone'
)
}
-
if
@project
.
can_current_user_push_to_default_branch?
%span><
git
push
-u
origin
--all
...
...
app/views/projects/show.html.haml
View file @
ec4ad656
...
...
@@ -19,8 +19,13 @@
-
if
can?
(
current_user
,
:download_code
,
@project
)
%nav
.project-stats
{
class:
[
container_class
,
(
"limit-container-width"
unless
fluid_layout
)]
}
=
render
'stat_anchor_list'
,
anchors:
@project
.
statistics_anchors
(
show_auto_devops_callout:
show_auto_devops_callout
)
=
render
'stat_anchor_list'
,
anchors:
@project
.
statistics_buttons
(
show_auto_devops_callout:
show_auto_devops_callout
)
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left
=
icon
(
'angle-left'
)
.fade-right
=
icon
(
'angle-right'
)
.nav-links.scrolling-tabs
=
render
'stat_anchor_list'
,
anchors:
@project
.
statistics_anchors
(
show_auto_devops_callout:
show_auto_devops_callout
)
=
render
'stat_anchor_list'
,
anchors:
@project
.
statistics_buttons
(
show_auto_devops_callout:
show_auto_devops_callout
)
=
repository_languages_bar
(
@project
.
repository_languages
)
%div
{
class:
[
container_class
,
(
"limit-container-width"
unless
fluid_layout
)]
}
...
...
app/views/shared/_clone_panel.html.haml
View file @
ec4ad656
-
project
=
project
||
@project
.git-clone-holder.input-group
.git-clone-holder.
js-git-clone-holder.
input-group
.input-group-prepend
-
if
allowed_protocols_present?
.input-group-text.clone-dropdown-btn.btn
%span
%span
.js-clone-dropdown-label
=
enabled_project_button
(
project
,
enabled_protocol
)
-
else
%a
#clone-dropdown
.input-group-text.btn.clone-dropdown-btn.qa-clone-dropdown
{
href:
'#'
,
data:
{
toggle:
'dropdown'
}
}
%span
%span
.js-clone-dropdown-label
=
default_clone_protocol
.
upcase
=
icon
(
'caret-down'
)
%ul
.dropdown-menu.dropdown-menu-selectable.clone-options-dropdown
...
...
app/views/shared/_mobile_clone_panel.html.haml
0 → 100644
View file @
ec4ad656
-
project
=
project
||
@project
-
ssh_copy_label
=
_
(
"Copy SSH clone URL"
)
-
http_copy_label
=
_
(
"Copy HTTPS clone URL"
)
.btn-group.mobile-git-clone.js-mobile-git-clone
=
clipboard_button
(
button_text:
default_clone_label
,
target:
'#project_clone'
,
hide_button_icon:
true
,
class:
"input-group-text clone-dropdown-btn js-clone-dropdown-label btn btn-default"
)
%button
.btn.btn-default.dropdown-toggle.js-dropdown-toggle
{
type:
"button"
,
data:
{
toggle:
"dropdown"
}
}
=
icon
(
"caret-down"
,
class:
"dropdown-btn-icon"
)
%ul
.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown
{
data:
{
dropdown:
true
}
}
%li
=
dropdown_item_with_description
(
ssh_copy_label
,
project
.
ssh_url_to_repo
,
href:
project
.
ssh_url_to_repo
,
data:
{
clone_type:
'ssh'
})
%li
=
dropdown_item_with_description
(
http_copy_label
,
project
.
http_url_to_repo
,
href:
project
.
http_url_to_repo
,
data:
{
clone_type:
'http'
})
changelogs/unreleased/44704-improve-project-overview-ui.yml
0 → 100644
View file @
ec4ad656
---
title
:
Update design of project overview page
merge_request
:
20536
author
:
type
:
changed
locale/gitlab.pot
View file @
ec4ad656
...
...
@@ -150,6 +150,9 @@ msgstr ""
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr ""
msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
msgstr ""
...
...
@@ -319,10 +322,10 @@ msgstr ""
msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add
Licens
e"
msgid "Add
Readm
e"
msgstr ""
msgid "Add
Readm
e"
msgid "Add
licens
e"
msgstr ""
msgid "Add new application"
...
...
@@ -1897,6 +1900,15 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
msgid "Copy %{protocol} clone URL"
msgstr ""
msgid "Copy HTTPS clone URL"
msgstr ""
msgid "Copy SSH clone URL"
msgstr ""
msgid "Copy URL to clipboard"
msgstr ""
...
...
@@ -1990,9 +2002,6 @@ msgstr ""
msgid "Create project label"
msgstr ""
msgid "CreateNewFork|Fork"
msgstr ""
msgid "CreateTag|Tag"
msgstr ""
...
...
@@ -2730,11 +2739,6 @@ msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "Fork"
msgid_plural "Forks"
msgstr[0] ""
msgstr[1] ""
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
...
...
@@ -2858,12 +2862,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
msgid "Go to your fork"
msgstr ""
msgid "GoToYourFork|Fork"
msgstr ""
msgid "Google Code import"
msgstr ""
...
...
@@ -3895,6 +3893,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
msgid "No license. All rights reserved"
msgstr ""
msgid "No merge requests found"
msgstr ""
...
...
@@ -4554,6 +4555,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
msgid "ProjectOverview|Fork"
msgstr ""
msgid "ProjectOverview|Forks"
msgstr ""
msgid "ProjectOverview|Go to your fork"
msgstr ""
msgid "ProjectOverview|Star"
msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
msgid "ProjectOverview|You must sign in to star a project"
msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
...
...
@@ -6516,9 +6538,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
msgid "You must sign in to star a project"
msgstr ""
msgid "You need permission."
msgstr ""
...
...
qa/qa/page/project/show.rb
View file @
ec4ad656
...
...
@@ -23,7 +23,7 @@ module QA
end
view
'app/views/projects/buttons/_fork.html.haml'
do
element
:fork_label
,
"%span= s_('
GoToYourFork
|Fork')"
element
:fork_label
,
"%span= s_('
ProjectOverview
|Fork')"
element
:fork_link
,
"link_to new_project_fork_path(@project)"
end
...
...
@@ -32,7 +32,7 @@ module QA
end
view
'app/presenters/project_presenter.rb'
do
element
:new_file_button
,
"
label:
_('New file'),"
element
:new_file_button
,
"_('New file'),"
end
def
project_name
...
...
spec/features/projects/files/project_owner_creates_license_file_spec.rb
View file @
ec4ad656
...
...
@@ -36,7 +36,7 @@ describe 'Projects > Files > Project owner creates a license file', :js do
end
it
'project maintainer creates a license file from the "Add license" link'
do
click_link
'Add
L
icense'
click_link
'Add
l
icense'
expect
(
page
).
to
have_content
(
'New file'
)
expect
(
current_path
).
to
eq
(
...
...
spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
View file @
ec4ad656
...
...
@@ -10,7 +10,7 @@ describe 'Projects > Files > Project owner sees a link to create a license file
it
'project maintainer creates a license file from a template'
do
visit
project_path
(
project
)
click_on
'Add
L
icense'
click_on
'Add
l
icense'
expect
(
page
).
to
have_content
(
'New file'
)
expect
(
current_path
).
to
eq
(
...
...
spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
View file @
ec4ad656
require
'spec_helper'
describe
'Projects > Show > User sees setup shortcut buttons'
do
# For "New file", "Add
L
icense" functionality,
# For "New file", "Add
l
icense" functionality,
# see spec/features/projects/files/project_owner_creates_license_file_spec.rb
# see spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
...
...
@@ -58,9 +58,9 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
end
end
it
'"Add
L
icense" button linked to new file populated for a license'
do
page
.
within
(
'.project-
stats
'
)
do
expect
(
page
).
to
have_link
(
'Add
L
icense'
,
href:
presenter
.
add_license_path
)
it
'"Add
l
icense" button linked to new file populated for a license'
do
page
.
within
(
'.project-
metadata
'
)
do
expect
(
page
).
to
have_link
(
'Add
l
icense'
,
href:
presenter
.
add_license_path
)
end
end
...
...
@@ -201,13 +201,13 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
end
end
it
'no "Add
L
icense" button if the project already has a license'
do
it
'no "Add
l
icense" button if the project already has a license'
do
visit
project_path
(
project
)
expect
(
project
.
repository
.
license_blob
).
not_to
be_nil
page
.
within
(
'.project-stats'
)
do
expect
(
page
).
not_to
have_link
(
'Add
L
icense'
)
expect
(
page
).
not_to
have_link
(
'Add
l
icense'
)
end
end
...
...
spec/features/projects_spec.rb
View file @
ec4ad656
...
...
@@ -2,6 +2,7 @@ require 'spec_helper'
describe
'Project'
do
include
ProjectForksHelper
include
MobileHelpers
describe
'creating from template'
do
let
(
:user
)
{
create
(
:user
)
}
...
...
@@ -54,25 +55,72 @@ describe 'Project' do
it
'parses Markdown'
do
project
.
update_attribute
(
:description
,
'This is **my** project'
)
visit
path
expect
(
page
).
to
have_css
(
'.project-
home-desc
> p > strong'
)
expect
(
page
).
to
have_css
(
'.project-
description > .project-description-markdown
> p > strong'
)
end
it
'passes through html-pipeline'
do
project
.
update_attribute
(
:description
,
'This project is the :poop:'
)
visit
path
expect
(
page
).
to
have_css
(
'.project-
home-desc
> p > gl-emoji'
)
expect
(
page
).
to
have_css
(
'.project-
description > .project-description-markdown
> p > gl-emoji'
)
end
it
'sanitizes unwanted tags'
do
project
.
update_attribute
(
:description
,
"```
\n
code
\n
```"
)
visit
path
expect
(
page
).
not_to
have_css
(
'.project-
home-desc
code'
)
expect
(
page
).
not_to
have_css
(
'.project-
description
code'
)
end
it
'permits `rel` attribute on links'
do
project
.
update_attribute
(
:description
,
'https://google.com/'
)
visit
path
expect
(
page
).
to
have_css
(
'.project-home-desc a[rel]'
)
expect
(
page
).
to
have_css
(
'.project-description a[rel]'
)
end
context
'read more'
,
:js
do
let
(
:read_more_selector
)
{
'.read-more-container'
}
let
(
:read_more_trigger_selector
)
{
'.project-home-desc .js-read-more-trigger'
}
it
'does not display "read more" link on desktop breakpoint'
do
project
.
update_attribute
(
:description
,
'This is **my** project'
)
visit
path
expect
(
find
(
read_more_trigger_selector
,
visible:
false
)).
not_to
be_visible
end
it
'displays "read more" link on mobile breakpoint'
do
project
.
update_attribute
(
:description
,
'This is **my** project'
)
visit
path
resize_screen_xs
find
(
read_more_trigger_selector
).
click
expect
(
page
).
to
have_css
(
'.project-description .is-expanded'
)
end
end
end
describe
'copy clone URL to clipboard'
,
:js
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:path
)
{
project_path
(
project
)
}
before
do
sign_in
(
create
(
:admin
))
visit
path
end
context
'desktop component'
do
it
'shows on md and larger breakpoints'
do
expect
(
find
(
'.git-clone-holder'
)).
to
be_visible
expect
(
find
(
'.mobile-git-clone'
,
visible:
false
)).
not_to
be_visible
end
end
context
'mobile component'
do
it
'shows mobile component on sm and smaller breakpoints'
do
resize_screen_xs
expect
(
find
(
'.mobile-git-clone'
)).
to
be_visible
expect
(
find
(
'.git-clone-holder'
,
visible:
false
)).
not_to
be_visible
end
end
end
...
...
spec/javascripts/fixtures/projects.rb
View file @
ec4ad656
...
...
@@ -6,6 +6,7 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
let
(
:admin
)
{
create
(
:admin
)
}
let
(
:namespace
)
{
create
(
:namespace
,
name:
'frontend-fixtures'
)}
let
(
:project
)
{
create
(
:project
,
namespace:
namespace
,
path:
'builds-project'
)
}
let
(
:project_with_repo
)
{
create
(
:project
,
:repository
,
description:
'Code and stuff'
)
}
let
(
:project_variable_populated
)
{
create
(
:project
,
namespace:
namespace
,
path:
'builds-project2'
)
}
let!
(
:variable1
)
{
create
(
:ci_variable
,
project:
project_variable_populated
)
}
let!
(
:variable2
)
{
create
(
:ci_variable
,
project:
project_variable_populated
)
}
...
...
@@ -35,6 +36,15 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
store_frontend_fixture
(
response
,
example
.
description
)
end
it
'projects/overview.html.raw'
do
|
example
|
get
:show
,
namespace_id:
project_with_repo
.
namespace
.
to_param
,
id:
project_with_repo
expect
(
response
).
to
be_success
store_frontend_fixture
(
response
,
example
.
description
)
end
it
'projects/edit.html.raw'
do
|
example
|
get
:edit
,
namespace_id:
project
.
namespace
.
to_param
,
...
...
spec/javascripts/read_more_spec.js
0 → 100644
View file @
ec4ad656
import
initReadMore
from
'
~/read_more
'
;
describe
(
'
Read more click-to-expand functionality
'
,
()
=>
{
const
fixtureName
=
'
projects/overview.html.raw
'
;
preloadFixtures
(
fixtureName
);
beforeEach
(()
=>
{
loadFixtures
(
fixtureName
);
});
describe
(
'
expands target element
'
,
()
=>
{
it
(
'
adds "is-expanded" class to target element
'
,
()
=>
{
const
target
=
document
.
querySelector
(
'
.read-more-container
'
);
const
trigger
=
document
.
querySelector
(
'
.js-read-more-trigger
'
);
initReadMore
();
trigger
.
click
();
expect
(
target
.
classList
.
contains
(
'
is-expanded
'
)).
toEqual
(
true
);
});
});
});
spec/presenters/project_presenter_spec.rb
View file @
ec4ad656
...
...
@@ -159,39 +159,76 @@ describe ProjectPresenter do
end
end
context
'statistics anchors (empty repo)'
do
let
(
:project
)
{
create
(
:project
,
:empty_repo
)
}
let
(
:presenter
)
{
described_class
.
new
(
project
,
current_user:
user
)
}
describe
'#files_anchor_data'
do
it
'returns files data'
do
expect
(
presenter
.
files_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Files (0 Bytes)'
,
link:
nil
)
end
end
describe
'#commits_anchor_data'
do
it
'returns commits data'
do
expect
(
presenter
.
commits_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Commits (0)'
,
link:
nil
)
end
end
describe
'#branches_anchor_data'
do
it
'returns branches data'
do
expect
(
presenter
.
branches_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
"Branches (0)"
,
link:
nil
)
end
end
describe
'#tags_anchor_data'
do
it
'returns tags data'
do
expect
(
presenter
.
tags_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
"Tags (0)"
,
link:
nil
)
end
end
end
context
'statistics anchors'
do
let
(
:project
)
{
create
(
:project
,
:repository
)
}
let
(
:presenter
)
{
described_class
.
new
(
project
,
current_user:
user
)
}
describe
'#files_anchor_data'
do
it
'returns files data'
do
expect
(
presenter
.
files_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Files (0 Bytes)'
,
link:
presenter
.
project_tree_path
(
project
)
))
expect
(
presenter
.
files_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Files (0 Bytes)'
,
link:
presenter
.
project_tree_path
(
project
))
end
end
describe
'#commits_anchor_data'
do
it
'returns commits data'
do
expect
(
presenter
.
commits_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Commits (0)'
,
link:
presenter
.
project_commits_path
(
project
,
project
.
repository
.
root_ref
)
))
expect
(
presenter
.
commits_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Commits (0)'
,
link:
presenter
.
project_commits_path
(
project
,
project
.
repository
.
root_ref
))
end
end
describe
'#branches_anchor_data'
do
it
'returns branches data'
do
expect
(
presenter
.
branches_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
"Branches (
#{
project
.
repository
.
branches
.
size
}
)"
,
link:
presenter
.
project_branches_path
(
project
)
))
expect
(
presenter
.
branches_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
"Branches (
#{
project
.
repository
.
branches
.
size
}
)"
,
link:
presenter
.
project_branches_path
(
project
))
end
end
describe
'#tags_anchor_data'
do
it
'returns tags data'
do
expect
(
presenter
.
tags_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
"Tags (
#{
project
.
repository
.
tags
.
size
}
)"
,
link:
presenter
.
project_tags_path
(
project
)
))
expect
(
presenter
.
tags_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
"Tags (
#{
project
.
repository
.
tags
.
size
}
)"
,
link:
presenter
.
project_tags_path
(
project
))
end
end
...
...
@@ -199,10 +236,10 @@ describe ProjectPresenter do
it
'returns new file data if user can push'
do
project
.
add_developer
(
user
)
expect
(
presenter
.
new_file_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
"New file"
,
link:
presenter
.
project_new_blob_path
(
project
,
'master'
),
class_modifier:
'new'
)
)
expect
(
presenter
.
new_file_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
"New file"
,
link:
presenter
.
project_new_blob_path
(
project
,
'master'
),
class_modifier:
'new'
)
end
it
'returns nil if user cannot push'
do
...
...
@@ -227,9 +264,9 @@ describe ProjectPresenter do
project
.
add_developer
(
user
)
allow
(
project
.
repository
).
to
receive
(
:readme
).
and_return
(
nil
)
expect
(
presenter
.
readme_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Add Readme'
,
link:
presenter
.
add_readme_path
)
)
expect
(
presenter
.
readme_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Add Readme'
,
link:
presenter
.
add_readme_path
)
end
end
...
...
@@ -237,9 +274,9 @@ describe ProjectPresenter do
it
'returns anchor data'
do
allow
(
project
.
repository
).
to
receive
(
:readme
).
and_return
(
double
(
name:
'readme'
))
expect
(
presenter
.
readme_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Readme'
,
link:
presenter
.
readme_path
)
)
expect
(
presenter
.
readme_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Readme'
,
link:
presenter
.
readme_path
)
end
end
end
...
...
@@ -250,9 +287,9 @@ describe ProjectPresenter do
project
.
add_developer
(
user
)
allow
(
project
.
repository
).
to
receive
(
:changelog
).
and_return
(
nil
)
expect
(
presenter
.
changelog_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Add Changelog'
,
link:
presenter
.
add_changelog_path
)
)
expect
(
presenter
.
changelog_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Add Changelog'
,
link:
presenter
.
add_changelog_path
)
end
end
...
...
@@ -260,9 +297,9 @@ describe ProjectPresenter do
it
'returns anchor data'
do
allow
(
project
.
repository
).
to
receive
(
:changelog
).
and_return
(
double
(
name:
'foo'
))
expect
(
presenter
.
changelog_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Changelog'
,
link:
presenter
.
changelog_path
)
)
expect
(
presenter
.
changelog_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Changelog'
,
link:
presenter
.
changelog_path
)
end
end
end
...
...
@@ -273,9 +310,9 @@ describe ProjectPresenter do
project
.
add_developer
(
user
)
allow
(
project
.
repository
).
to
receive
(
:license_blob
).
and_return
(
nil
)
expect
(
presenter
.
license_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Add L
icense'
,
link:
presenter
.
add_license_path
)
)
expect
(
presenter
.
license_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Add l
icense'
,
link:
presenter
.
add_license_path
)
end
end
...
...
@@ -283,9 +320,9 @@ describe ProjectPresenter do
it
'returns anchor data'
do
allow
(
project
.
repository
).
to
receive
(
:license_blob
).
and_return
(
double
(
name:
'foo'
))
expect
(
presenter
.
license_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
presenter
.
license_short_name
,
link:
presenter
.
license_path
)
)
expect
(
presenter
.
license_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
presenter
.
license_short_name
,
link:
presenter
.
license_path
)
end
end
end
...
...
@@ -296,9 +333,9 @@ describe ProjectPresenter do
project
.
add_developer
(
user
)
allow
(
project
.
repository
).
to
receive
(
:contribution_guide
).
and_return
(
nil
)
expect
(
presenter
.
contribution_guide_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Add Contribution guide'
,
link:
presenter
.
add_contribution_guide_path
)
)
expect
(
presenter
.
contribution_guide_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Add Contribution guide'
,
link:
presenter
.
add_contribution_guide_path
)
end
end
...
...
@@ -306,9 +343,9 @@ describe ProjectPresenter do
it
'returns anchor data'
do
allow
(
project
.
repository
).
to
receive
(
:contribution_guide
).
and_return
(
double
(
name:
'foo'
))
expect
(
presenter
.
contribution_guide_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Contribution guide'
,
link:
presenter
.
contribution_guide_path
)
)
expect
(
presenter
.
contribution_guide_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Contribution guide'
,
link:
presenter
.
contribution_guide_path
)
end
end
end
...
...
@@ -318,9 +355,9 @@ describe ProjectPresenter do
it
'returns anchor data'
do
allow
(
project
).
to
receive
(
:auto_devops_enabled?
).
and_return
(
true
)
expect
(
presenter
.
autodevops_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Auto DevOps enabled'
,
link:
nil
)
)
expect
(
presenter
.
autodevops_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Auto DevOps enabled'
,
link:
nil
)
end
end
...
...
@@ -330,9 +367,9 @@ describe ProjectPresenter do
allow
(
project
).
to
receive
(
:auto_devops_enabled?
).
and_return
(
false
)
allow
(
project
.
repository
).
to
receive
(
:gitlab_ci_yml
).
and_return
(
nil
)
expect
(
presenter
.
autodevops_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Enable Auto DevOps'
,
link:
presenter
.
project_settings_ci_cd_path
(
project
,
anchor:
'autodevops-settings'
)
))
expect
(
presenter
.
autodevops_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Enable Auto DevOps'
,
link:
presenter
.
project_settings_ci_cd_path
(
project
,
anchor:
'autodevops-settings'
))
end
end
end
...
...
@@ -343,9 +380,9 @@ describe ProjectPresenter do
project
.
add_maintainer
(
user
)
cluster
=
create
(
:cluster
,
projects:
[
project
])
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Kubernetes configured'
,
link:
presenter
.
project_cluster_path
(
project
,
cluster
)
))
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Kubernetes configured'
,
link:
presenter
.
project_cluster_path
(
project
,
cluster
))
end
it
'returns link to clusters page if more than one exists'
do
...
...
@@ -353,17 +390,17 @@ describe ProjectPresenter do
create
(
:cluster
,
:production_environment
,
projects:
[
project
])
create
(
:cluster
,
projects:
[
project
])
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
true
,
label:
'Kubernetes configured'
,
link:
presenter
.
project_clusters_path
(
project
)
))
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
have_attributes
(
enabled:
true
,
label:
'Kubernetes configured'
,
link:
presenter
.
project_clusters_path
(
project
))
end
it
'returns link to create a cluster if no cluster exists'
do
project
.
add_maintainer
(
user
)
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Add Kubernetes cluster'
,
link:
presenter
.
new_project_cluster_path
(
project
)
))
expect
(
presenter
.
kubernetes_cluster_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Add Kubernetes cluster'
,
link:
presenter
.
new_project_cluster_path
(
project
))
end
end
...
...
@@ -380,9 +417,9 @@ describe ProjectPresenter do
allow
(
project
.
repository
).
to
receive
(
:koding_yml
).
and_return
(
nil
)
allow
(
Gitlab
::
CurrentSettings
).
to
receive
(
:koding_enabled?
).
and_return
(
true
)
expect
(
presenter
.
koding_anchor_data
).
to
eq
(
OpenStruct
.
new
(
enabled:
false
,
label:
'Set up Koding'
,
link:
presenter
.
add_koding_stack_path
)
)
expect
(
presenter
.
koding_anchor_data
).
to
have_attributes
(
enabled:
false
,
label:
'Set up Koding'
,
link:
presenter
.
add_koding_stack_path
)
end
it
'returns nil if user cannot push'
do
...
...
spec/views/projects/_home_panel.html.haml_spec.rb
View file @
ec4ad656
...
...
@@ -9,6 +9,7 @@ describe 'projects/_home_panel' do
allow
(
view
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
view
).
to
receive
(
:can?
).
with
(
user
,
:read_project
,
project
).
and_return
(
false
)
allow
(
project
).
to
receive
(
:license_anchor_data
).
and_return
(
false
)
end
context
'when user is signed in'
do
...
...
@@ -63,6 +64,7 @@ describe 'projects/_home_panel' do
allow
(
view
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
view
).
to
receive
(
:can?
).
with
(
user
,
:read_project
,
project
).
and_return
(
false
)
allow
(
project
).
to
receive
(
:license_anchor_data
).
and_return
(
false
)
end
context
'has no badges'
do
...
...
@@ -71,8 +73,7 @@ describe 'projects/_home_panel' do
it
'should not render any badge'
do
render
expect
(
rendered
).
to
have_selector
(
'.project-badges'
)
expect
(
rendered
).
not_to
have_selector
(
'.project-badges > a'
)
expect
(
rendered
).
not_to
have_selector
(
'.project-badges'
)
end
end
...
...
@@ -118,6 +119,7 @@ describe 'projects/_home_panel' do
assign
(
:project
,
project
)
allow
(
view
).
to
receive
(
:current_user
).
and_return
(
user
)
allow
(
project
).
to
receive
(
:license_anchor_data
).
and_return
(
false
)
end
context
'user can read project'
do
...
...
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