Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
d66342f2
Commit
d66342f2
authored
Sep 23, 2016
by
Ruben Davila
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'ce/8-12-stable' into 8-12-stable-ee
Conflicts: VERSION
parents
8a0ad9b6
afd43301
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
149 additions
and
80 deletions
+149
-80
CHANGELOG
CHANGELOG
+5
-1
app/assets/javascripts/cycle-analytics.js.es6
app/assets/javascripts/cycle-analytics.js.es6
+17
-16
app/assets/stylesheets/framework/variables.scss
app/assets/stylesheets/framework/variables.scss
+6
-0
app/assets/stylesheets/pages/cycle_analytics.scss
app/assets/stylesheets/pages/cycle_analytics.scss
+39
-16
app/controllers/search_controller.rb
app/controllers/search_controller.rb
+2
-2
app/views/projects/cycle_analytics/show.html.haml
app/views/projects/cycle_analytics/show.html.haml
+15
-13
doc/api/README.md
doc/api/README.md
+1
-0
lib/banzai/filter/sanitization_filter.rb
lib/banzai/filter/sanitization_filter.rb
+32
-32
spec/features/search_spec.rb
spec/features/search_spec.rb
+32
-0
No files found.
CHANGELOG
View file @
d66342f2
Please view this file on the master branch, on stable branches it's out of date.
v 8.12.1 (unreleased)
v 8.12.2 (unreleased)
v 8.12.1
- Fix a memory leak in HTML::Pipeline::SanitizationFilter::WHITELIST
- Fix issue with search filter labels not displaying
v 8.12.0
- Update the rouge gem to 2.0.6, which adds highlighting support for JSX, Prometheus, and others. !6251
...
...
app/assets/javascripts/cycle-analytics.js.es6
View file @
d66342f2
((global) => {
const COOKIE_NAME = 'cycle_analytics_help_dismissed';
const store = gl.cycleAnalyticsStore = {
isLoading: true,
hasError: false,
isHelpDismissed: $.cookie(COOKIE_NAME),
analytics: {}
};
gl.CycleAnalytics = class CycleAnalytics {
constructor() {
const that = this;
this.isHelpDismissed = $.cookie(COOKIE_NAME);
this.vue = new Vue({
el: '#cycle-analytics',
name: 'CycleAnalytics',
created: this.fetchData(),
data:
this.decorateData({ isLoading: true })
,
data:
store
,
methods: {
dismissLanding() {
that.dismissLanding();
...
...
@@ -21,6 +26,7 @@
}
fetchData(options) {
store.isLoading = true;
options = options || { startDate: 30 };
$.ajax({
...
...
@@ -30,22 +36,20 @@
contentType: 'application/json',
data: { start_date: options.startDate }
}).done((data) => {
this.
vue.$data = this.
decorateData(data);
this.decorateData(data);
this.initDropdown();
})
.error((data) => {
this.handleError(data);
})
.always(() => {
this.vu
e.isLoading = false;
stor
e.isLoading = false;
})
}
decorateData(data) {
data.summary = data.summary || [];
data.stats = data.stats || [];
data.isHelpDismissed = this.isHelpDismissed;
data.isLoading = data.isLoading || false;
data.summary.forEach((item) => {
item.value = item.value || '-';
...
...
@@ -53,23 +57,21 @@
data.stats.forEach((item) => {
item.value = item.value || '- - -';
})
})
;
return
data;
store.analytics =
data;
}
handleError(data) {
this.vue.$data = {
hasError: true,
isHelpDismissed: this.isHelpDismissed
};
store.hasError = true;
new Flash('There was an error while fetching cycle analytics data.', 'alert');
}
dismissLanding() {
this.vue.isHelpDismissed = true;
$.cookie(COOKIE_NAME, true);
store.isHelpDismissed = true;
$.cookie(COOKIE_NAME, true, {
path: gon.relative_url_root || '/'
});
}
initDropdown() {
...
...
@@ -82,7 +84,6 @@
const value = $target.data('value');
$label.text($target.text().trim());
this.vue.isLoading = true;
this.fetchData({ startDate: value });
})
}
...
...
app/assets/stylesheets/framework/variables.scss
View file @
d66342f2
...
...
@@ -269,6 +269,12 @@ $calendar-hover-bg: #ecf3fe;
$calendar-border-color
:
rgba
(
#000
,
.1
);
$calendar-unselectable-bg
:
$gray-light
;
/*
* Cycle Analytics
*/
$cycle-analytics-box-padding
:
30px
;
$cycle-analytics-box-text-color
:
#8c8c8c
;
/*
* Personal Access Tokens
*/
...
...
app/assets/stylesheets/pages/cycle_analytics.scss
View file @
d66342f2
#cycle-analytics
{
margin
:
24px
auto
0
;
width
:
800px
;
max-
width
:
800px
;
position
:
relative
;
.panel
{
...
...
@@ -9,10 +9,18 @@
padding
:
24px
0
;
border-bottom
:
none
;
position
:
relative
;
@media
(
max-width
:
$screen-sm-min
)
{
padding
:
6px
0
24px
;
}
}
.column
{
text-align
:
center
;
@media
(
max-width
:
$screen-sm-min
)
{
padding
:
15px
0
;
}
.header
{
font-size
:
30px
;
...
...
@@ -28,11 +36,14 @@
&
:last-child
{
text-align
:
right
;
@media
(
max-width
:
$screen-sm-min
)
{
text-align
:
center
;
}
}
}
.dropdown
{
position
:
relative
;
top
:
13px
;
}
}
...
...
@@ -40,7 +51,7 @@
.bordered-box
{
border
:
1px
solid
$border-color
;
@include
border-radius
(
$border-radius-default
);
position
:
relative
;
}
.content-list
{
...
...
@@ -60,9 +71,15 @@
line-height
:
19px
;
font-size
:
15px
;
font-weight
:
600
;
color
:
$gl-title-color
;
}
&
:text
{
color
:
#8c8c8c
;
&
.text
{
color
:
$layout-link-gray
;
&
.value-col
{
color
:
$gl-title-color
;
}
}
}
}
...
...
@@ -71,7 +88,9 @@
text-align
:
right
;
span
{
line-height
:
42px
;
position
:
relative
;
vertical-align
:
middle
;
top
:
3px
;
}
}
}
...
...
@@ -82,21 +101,25 @@
.dismiss-icon
{
position
:
absolute
;
right
:
$
gl
-padding
;
right
:
$
cycle-analytics-box
-padding
;
cursor
:
pointer
;
color
:
#b2b2b2
;
}
svg
{
margin
:
0
20px
;
float
:
left
;
width
:
136px
;
height
:
136px
;
.svg-container
{
text-align
:
center
;
svg
{
width
:
136px
;
height
:
136px
;
}
}
.inner-content
{
width
:
480px
;
float
:
left
;
@media
(
max-width
:
$screen-sm-min
)
{
padding
:
0
28px
;
text-align
:
center
;
}
h4
{
color
:
$gl-text-color
;
...
...
@@ -104,7 +127,7 @@
}
p
{
color
:
#8c8c8c
;
color
:
$cycle-analytics-box-text-color
;
margin-bottom
:
$gl-padding
;
}
}
...
...
app/controllers/search_controller.rb
View file @
d66342f2
...
...
@@ -6,8 +6,6 @@ class SearchController < ApplicationController
layout
'search'
def
show
return
if
params
[
:search
].
nil?
||
params
[
:search
].
blank?
if
params
[
:project_id
].
present?
@project
=
Project
.
find_by
(
id:
params
[
:project_id
])
@project
=
nil
unless
can?
(
current_user
,
:download_code
,
@project
)
...
...
@@ -18,6 +16,8 @@ class SearchController < ApplicationController
@group
=
nil
unless
can?
(
current_user
,
:read_group
,
@group
)
end
return
if
params
[
:search
].
nil?
||
params
[
:search
].
blank?
@search_term
=
params
[
:search
]
@scope
=
params
[
:scope
]
...
...
app/views/projects/cycle_analytics/show.html.haml
View file @
d66342f2
...
...
@@ -2,18 +2,20 @@
-
page_title
"Cycle Analytics"
=
render
"projects/pipelines/head"
#cycle-analytics
{
"v-cloak"
=>
"true"
,
data:
{
request_path:
project_cycle_analytics_path
(
@project
)}}
#cycle-analytics
{
class:
container_class
,
"v-cloak"
=>
"true"
,
data:
{
request_path:
project_cycle_analytics_path
(
@project
)}}
.bordered-box.landing.content-block
{
"v-if"
=>
"!isHelpDismissed"
}
=
icon
(
'times'
,
class:
'dismiss-icon'
,
"@click"
:
"dismissLanding()"
)
=
custom_icon
(
'icon_cycle_analytics_splash'
)
.inner-content
%h4
Introducing Cycle Analytics
%p
Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.
.row
.col-sm-3.col-xs-12.svg-container
=
custom_icon
(
'icon_cycle_analytics_splash'
)
.col-sm-8.col-xs-12.inner-content
%h4
Introducing Cycle Analytics
%p
Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.
=
link_to
"Read more"
,
help_page_path
(
'user/project/cycle_analytics'
),
target:
'_blank'
,
class:
'btn'
=
link_to
"Read more"
,
help_page_path
(
'user/project/cycle_analytics'
),
target:
'_blank'
,
class:
'btn'
=
icon
(
"spinner spin"
,
"v-show"
=>
"isLoading"
)
...
...
@@ -25,11 +27,11 @@
.content-block
.container-fluid
.row
.col-
xs-3.column
{
"v-for"
=>
"item in
summary"
}
.col-
sm-3.col-xs-12.column
{
"v-for"
=>
"item in analytics.
summary"
}
%h3
.header
{{item.value}}
%p
.text
{{item.title}}
.col-
xs-3
.column
.col-
sm-3.col-xs-12
.column
.dropdown.inline.js-ca-dropdown
%button
.dropdown-menu-toggle
{
"data-toggle"
=>
"dropdown"
,
:type
=>
"button"
}
%span
.dropdown-label
Last 30 days
...
...
@@ -44,14 +46,14 @@
.bordered-box
%ul
.content-list
%li
{
"v-for"
=>
"item in stats"
}
%li
{
"v-for"
=>
"item in
analytics.
stats"
}
.container-fluid
.row
.col-xs-
10
.title-col
.col-xs-
8
.title-col
%p
.title
{{item.title}}
%p
.text
{{item.description}}
.col-xs-
2
.value-col
.col-xs-
4
.value-col
%span
{{item.value}}
doc/api/README.md
View file @
d66342f2
...
...
@@ -10,6 +10,7 @@ following locations:
-
[
Award Emoji
](
award_emoji.md
)
-
[
Branches
](
branches.md
)
-
[
Broadcast Messages
](
broadcast_messages.md
)
-
[
Builds
](
builds.md
)
-
[
Build Triggers
](
build_triggers.md
)
-
[
Build Variables
](
build_variables.md
)
...
...
lib/banzai/filter/sanitization_filter.rb
View file @
d66342f2
...
...
@@ -7,7 +7,7 @@ module Banzai
UNSAFE_PROTOCOLS
=
%w(data javascript vbscript)
.
freeze
def
whitelist
whitelist
=
super
.
dup
whitelist
=
super
customize_whitelist
(
whitelist
)
...
...
@@ -42,58 +42,58 @@ module Banzai
# Allow any protocol in `a` elements...
whitelist
[
:protocols
].
delete
(
'a'
)
whitelist
[
:transformers
]
=
whitelist
[
:transformers
].
dup
# ...but then remove links with unsafe protocols
whitelist
[
:transformers
].
push
(
remove_unsafe_links
)
whitelist
[
:transformers
].
push
(
self
.
class
.
remove_unsafe_links
)
# Remove `rel` attribute from `a` elements
whitelist
[
:transformers
].
push
(
remove_rel
)
whitelist
[
:transformers
].
push
(
self
.
class
.
remove_rel
)
# Remove `class` attribute from non-highlight spans
whitelist
[
:transformers
].
push
(
clean_spans
)
whitelist
[
:transformers
].
push
(
self
.
class
.
clean_spans
)
whitelist
end
def
remove_unsafe_links
lambda
do
|
env
|
node
=
env
[
:node
]
class
<<
self
def
remove_unsafe_links
lambda
do
|
env
|
node
=
env
[
:node
]
return
unless
node
.
name
==
'a'
return
unless
node
.
has_attribute?
(
'href'
)
return
unless
node
.
name
==
'a'
return
unless
node
.
has_attribute?
(
'href'
)
begin
uri
=
Addressable
::
URI
.
parse
(
node
[
'href'
])
uri
.
scheme
=
uri
.
scheme
.
strip
.
downcase
if
uri
.
scheme
begin
uri
=
Addressable
::
URI
.
parse
(
node
[
'href'
])
uri
.
scheme
=
uri
.
scheme
.
strip
.
downcase
if
uri
.
scheme
node
.
remove_attribute
(
'href'
)
if
UNSAFE_PROTOCOLS
.
include?
(
uri
.
scheme
)
rescue
Addressable
::
URI
::
InvalidURIError
node
.
remove_attribute
(
'href'
)
node
.
remove_attribute
(
'href'
)
if
UNSAFE_PROTOCOLS
.
include?
(
uri
.
scheme
)
rescue
Addressable
::
URI
::
InvalidURIError
node
.
remove_attribute
(
'href'
)
end
end
end
end
def
remove_rel
lambda
do
|
env
|
if
env
[
:node_name
]
==
'a'
env
[
:node
].
remove_attribute
(
'rel'
)
def
remove_rel
lambda
do
|
env
|
if
env
[
:node_name
]
==
'a'
env
[
:node
].
remove_attribute
(
'rel'
)
end
end
end
end
def
clean_spans
lambda
do
|
env
|
node
=
env
[
:node
]
def
clean_spans
lambda
do
|
env
|
node
=
env
[
:node
]
return
unless
node
.
name
==
'span'
return
unless
node
.
has_attribute?
(
'class'
)
return
unless
node
.
name
==
'span'
return
unless
node
.
has_attribute?
(
'class'
)
unless
has_ancestor?
(
node
,
'pre'
)
node
.
remove_attribute
(
'class'
)
end
unless
node
.
ancestors
.
any?
{
|
n
|
n
.
name
.
casecmp
(
'pre'
).
zero?
}
node
.
remove_attribute
(
'class'
)
end
{
node_whitelist:
[
node
]
}
{
node_whitelist:
[
node
]
}
end
end
end
end
...
...
spec/features/search_spec.rb
View file @
d66342f2
require
'spec_helper'
describe
"Search"
,
feature:
true
do
include
WaitForAjax
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
namespace:
user
.
namespace
)
}
let!
(
:issue
)
{
create
(
:issue
,
project:
project
,
assignee:
user
)
}
...
...
@@ -16,6 +18,36 @@ describe "Search", feature: true do
expect
(
page
).
not_to
have_selector
(
'.search'
)
end
context
'search filters'
,
js:
true
do
let
(
:group
)
{
create
(
:group
)
}
before
do
group
.
add_owner
(
user
)
end
it
'shows group name after filtering'
do
find
(
'.js-search-group-dropdown'
).
click
wait_for_ajax
page
.
within
'.search-holder'
do
click_link
group
.
name
end
expect
(
find
(
'.js-search-group-dropdown'
)).
to
have_content
(
group
.
name
)
end
it
'shows project name after filtering'
do
page
.
within
(
'.project-filter'
)
do
find
(
'.js-search-project-dropdown'
).
click
wait_for_ajax
click_link
project
.
name_with_namespace
end
expect
(
find
(
'.js-search-project-dropdown'
)).
to
have_content
(
project
.
name_with_namespace
)
end
end
describe
'searching for Projects'
do
it
'finds a project'
do
page
.
within
'.search-holder'
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