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
Jérome Perrin
gitlab-ce
Commits
cad686cc
Commit
cad686cc
authored
May 26, 2017
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Creates a mediator for pipeline details vue in order to mount several vue apps with the same data
parent
8e2fefc6
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
142 additions
and
106 deletions
+142
-106
app/assets/javascripts/pipelines/components/graph/graph_component.vue
...avascripts/pipelines/components/graph/graph_component.vue
+16
-52
app/assets/javascripts/pipelines/graph_bundle.js
app/assets/javascripts/pipelines/graph_bundle.js
+0
-10
app/assets/javascripts/pipelines/pipeline_details_bundle.js
app/assets/javascripts/pipelines/pipeline_details_bundle.js
+31
-0
app/assets/javascripts/pipelines/pipeline_details_mediatior.js
...ssets/javascripts/pipelines/pipeline_details_mediatior.js
+51
-0
app/assets/javascripts/pipelines/stores/pipeline_store.js
app/assets/javascripts/pipelines/stores/pipeline_store.js
+3
-3
app/views/projects/pipelines/_with_tabs.html.haml
app/views/projects/pipelines/_with_tabs.html.haml
+1
-5
app/views/projects/pipelines/show.html.haml
app/views/projects/pipelines/show.html.haml
+6
-0
changelogs/unreleased/31849-pipeline-show-view-realtime.yml
changelogs/unreleased/31849-pipeline-show-view-realtime.yml
+5
-0
config/webpack.config.js
config/webpack.config.js
+3
-3
spec/javascripts/pipelines/graph/graph_component_spec.js
spec/javascripts/pipelines/graph/graph_component_spec.js
+26
-33
No files found.
app/assets/javascripts/pipelines/components/graph/graph_component.vue
View file @
cad686cc
<
script
>
<
script
>
/* global Flash */
import
Visibility
from
'
visibilityjs
'
;
import
Poll
from
'
../../../lib/utils/poll
'
;
import
PipelineService
from
'
../../services/pipeline_service
'
;
import
PipelineStore
from
'
../../stores/pipeline_store
'
;
import
stageColumnComponent
from
'
./stage_column_component.vue
'
;
import
stageColumnComponent
from
'
./stage_column_component.vue
'
;
import
loadingIcon
from
'
../../../vue_shared/components/loading_icon.vue
'
;
import
loadingIcon
from
'
../../../vue_shared/components/loading_icon.vue
'
;
import
'
../../../flash
'
;
import
'
../../../flash
'
;
export
default
{
export
default
{
props
:
{
isLoading
:
{
type
:
Boolean
,
required
:
true
,
},
pipeline
:
{
type
:
Object
,
required
:
true
,
},
},
components
:
{
components
:
{
stageColumnComponent
,
stageColumnComponent
,
loadingIcon
,
loadingIcon
,
},
},
data
()
{
computed
:
{
const
DOMdata
=
document
.
getElementById
(
'
js-pipeline-graph-vue
'
).
dataset
;
graph
()
{
const
store
=
new
PipelineStore
();
return
this
.
pipeline
.
details
&&
this
.
pipeline
.
details
.
stages
;
},
return
{
isLoading
:
false
,
endpoint
:
DOMdata
.
endpoint
,
store
,
state
:
store
.
state
,
};
},
created
()
{
this
.
service
=
new
PipelineService
(
this
.
endpoint
);
const
poll
=
new
Poll
({
resource
:
this
.
service
,
method
:
'
getPipeline
'
,
successCallback
:
this
.
successCallback
,
errorCallback
:
this
.
errorCallback
,
});
if
(
!
Visibility
.
hidden
())
{
this
.
isLoading
=
true
;
poll
.
makeRequest
();
}
Visibility
.
change
(()
=>
{
if
(
!
Visibility
.
hidden
())
{
poll
.
restart
();
}
else
{
poll
.
stop
();
}
});
},
},
methods
:
{
methods
:
{
successCallback
(
response
)
{
const
data
=
response
.
json
();
this
.
isLoading
=
false
;
this
.
store
.
storeGraph
(
data
.
details
.
stages
);
},
errorCallback
()
{
this
.
isLoading
=
false
;
return
new
Flash
(
'
An error occurred while fetching the pipeline.
'
);
},
capitalizeStageName
(
name
)
{
capitalizeStageName
(
name
)
{
return
name
.
charAt
(
0
).
toUpperCase
()
+
name
.
slice
(
1
);
return
name
.
charAt
(
0
).
toUpperCase
()
+
name
.
slice
(
1
);
},
},
...
@@ -101,7 +65,7 @@
...
@@ -101,7 +65,7 @@
v-if=
"!isLoading"
v-if=
"!isLoading"
class=
"stage-column-list"
>
class=
"stage-column-list"
>
<stage-column-component
<stage-column-component
v-for=
"(stage, index) in
state.
graph"
v-for=
"(stage, index) in graph"
:title=
"capitalizeStageName(stage.name)"
:title=
"capitalizeStageName(stage.name)"
:jobs=
"stage.groups"
:jobs=
"stage.groups"
:key=
"stage.name"
:key=
"stage.name"
...
...
app/assets/javascripts/pipelines/graph_bundle.js
deleted
100644 → 0
View file @
8e2fefc6
import
Vue
from
'
vue
'
;
import
pipelineGraph
from
'
./components/graph/graph_component.vue
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
new
Vue
({
el
:
'
#js-pipeline-graph-vue
'
,
components
:
{
pipelineGraph
,
},
render
:
createElement
=>
createElement
(
'
pipeline-graph
'
),
}));
app/assets/javascripts/pipelines/pipeline_details_bundle.js
0 → 100644
View file @
cad686cc
import
Vue
from
'
vue
'
;
import
PipelinesMediator
from
'
./pipeline_details_mediatior
'
;
import
pipelineGraph
from
'
./components/graph/graph_component.vue
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
const
dataset
=
document
.
querySelector
(
'
.js-pipeline-details-vue
'
).
dataset
;
const
mediator
=
new
PipelinesMediator
({
endpoint
:
dataset
.
endpoint
});
mediator
.
fetchPipeline
();
const
pipelineGraphApp
=
new
Vue
({
el
:
'
#js-pipeline-graph-vue
'
,
data
:
{
mediator
,
},
components
:
{
pipelineGraph
,
},
render
(
createElement
)
{
return
createElement
(
'
pipeline-graph
'
,
{
props
:
{
isLoading
:
this
.
mediator
.
state
.
isLoading
,
pipeline
:
this
.
mediator
.
store
.
state
.
pipeline
,
},
});
},
});
return
pipelineGraphApp
;
});
app/assets/javascripts/pipelines/pipeline_details_mediatior.js
0 → 100644
View file @
cad686cc
/* global Flash */
import
Visibility
from
'
visibilityjs
'
;
import
Poll
from
'
../lib/utils/poll
'
;
import
PipelineStore
from
'
./stores/pipeline_store
'
;
import
PipelineService
from
'
./services/pipeline_service
'
;
export
default
class
pipelinesMediator
{
constructor
(
options
)
{
this
.
options
=
options
||
{};
this
.
store
=
new
PipelineStore
();
this
.
service
=
new
PipelineService
(
options
.
endpoint
);
this
.
state
=
{};
this
.
state
.
isLoading
=
false
;
}
fetchPipeline
()
{
this
.
poll
=
new
Poll
({
resource
:
this
.
service
,
method
:
'
getPipeline
'
,
successCallback
:
this
.
successCallback
.
bind
(
this
),
errorCallback
:
this
.
errorCallback
.
bind
(
this
),
});
if
(
!
Visibility
.
hidden
())
{
this
.
state
.
isLoading
=
true
;
this
.
poll
.
makeRequest
();
}
Visibility
.
change
(()
=>
{
if
(
!
Visibility
.
hidden
())
{
this
.
poll
.
restart
();
}
else
{
this
.
poll
.
stop
();
}
});
}
successCallback
(
response
)
{
const
data
=
response
.
json
();
this
.
state
.
isLoading
=
false
;
this
.
store
.
storePipeline
(
data
);
}
errorCallback
()
{
this
.
state
.
isLoading
=
false
;
return
new
Flash
(
'
An error occurred while fetching the pipeline.
'
);
}
}
app/assets/javascripts/pipelines/stores/pipeline_store.js
View file @
cad686cc
...
@@ -2,10 +2,10 @@ export default class PipelineStore {
...
@@ -2,10 +2,10 @@ export default class PipelineStore {
constructor
()
{
constructor
()
{
this
.
state
=
{};
this
.
state
=
{};
this
.
state
.
graph
=
[]
;
this
.
state
.
pipeline
=
{}
;
}
}
store
Graph
(
graph
=
[]
)
{
store
Pipeline
(
pipeline
=
{}
)
{
this
.
state
.
graph
=
graph
;
this
.
state
.
pipeline
=
pipeline
;
}
}
}
}
app/views/projects/pipelines/_with_tabs.html.haml
View file @
cad686cc
-
failed_builds
=
@pipeline
.
statuses
.
latest
.
failed
-
failed_builds
=
@pipeline
.
statuses
.
latest
.
failed
-
content_for
:page_specific_javascripts
do
=
page_specific_javascript_bundle_tag
(
'common_vue'
)
=
page_specific_javascript_bundle_tag
(
'pipelines_graph'
)
.tabs-holder
.tabs-holder
%ul
.pipelines-tabs.nav-links.no-top.no-bottom
%ul
.pipelines-tabs.nav-links.no-top.no-bottom
%li
.js-pipeline-tab-link
%li
.js-pipeline-tab-link
...
@@ -21,7 +17,7 @@
...
@@ -21,7 +17,7 @@
.tab-content
.tab-content
#js-tab-pipeline
.tab-pane
#js-tab-pipeline
.tab-pane
#js-pipeline-graph-vue
{
data:
{
endpoint:
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
@pipeline
,
format: :json
)
}
}
#js-pipeline-graph-vue
#js-tab-builds
.tab-pane
#js-tab-builds
.tab-pane
-
if
pipeline
.
yaml_errors
.
present?
-
if
pipeline
.
yaml_errors
.
present?
...
...
app/views/projects/pipelines/show.html.haml
View file @
cad686cc
...
@@ -7,3 +7,9 @@
...
@@ -7,3 +7,9 @@
=
render
"projects/pipelines/info"
=
render
"projects/pipelines/info"
=
render
"projects/pipelines/with_tabs"
,
pipeline:
@pipeline
=
render
"projects/pipelines/with_tabs"
,
pipeline:
@pipeline
.js-pipeline-details-vue
{
data:
{
endpoint:
namespace_project_pipeline_path
(
@project
.
namespace
,
@project
,
@pipeline
,
format: :json
)
}
}
-
content_for
:page_specific_javascripts
do
=
webpack_bundle_tag
(
'common_vue'
)
=
webpack_bundle_tag
(
'pipelines_details'
)
changelogs/unreleased/31849-pipeline-show-view-realtime.yml
0 → 100644
View file @
cad686cc
---
title
:
Creates a mediator for pipeline details vue in order to mount several vue apps
with the same data
merge_request
:
author
:
config/webpack.config.js
View file @
cad686cc
...
@@ -23,6 +23,7 @@ var config = {
...
@@ -23,6 +23,7 @@ var config = {
},
},
context
:
path
.
join
(
ROOT_PATH
,
'
app/assets/javascripts
'
),
context
:
path
.
join
(
ROOT_PATH
,
'
app/assets/javascripts
'
),
entry
:
{
entry
:
{
balsamiq_viewer
:
'
./blob/balsamiq_viewer.js
'
,
blob
:
'
./blob_edit/blob_bundle.js
'
,
blob
:
'
./blob_edit/blob_bundle.js
'
,
boards
:
'
./boards/boards_bundle.js
'
,
boards
:
'
./boards/boards_bundle.js
'
,
common
:
'
./commons/index.js
'
,
common
:
'
./commons/index.js
'
,
...
@@ -47,8 +48,7 @@ var config = {
...
@@ -47,8 +48,7 @@ var config = {
notebook_viewer
:
'
./blob/notebook_viewer.js
'
,
notebook_viewer
:
'
./blob/notebook_viewer.js
'
,
pdf_viewer
:
'
./blob/pdf_viewer.js
'
,
pdf_viewer
:
'
./blob/pdf_viewer.js
'
,
pipelines
:
'
./pipelines/index.js
'
,
pipelines
:
'
./pipelines/index.js
'
,
balsamiq_viewer
:
'
./blob/balsamiq_viewer.js
'
,
pipelines_details
:
'
./pipelines/pipeline_details_bundle.js
'
,
pipelines_graph
:
'
./pipelines/graph_bundle.js
'
,
profile
:
'
./profile/profile_bundle.js
'
,
profile
:
'
./profile/profile_bundle.js
'
,
protected_branches
:
'
./protected_branches/protected_branches_bundle.js
'
,
protected_branches
:
'
./protected_branches/protected_branches_bundle.js
'
,
protected_tags
:
'
./protected_tags
'
,
protected_tags
:
'
./protected_tags
'
,
...
@@ -146,7 +146,7 @@ var config = {
...
@@ -146,7 +146,7 @@ var config = {
'
notebook_viewer
'
,
'
notebook_viewer
'
,
'
pdf_viewer
'
,
'
pdf_viewer
'
,
'
pipelines
'
,
'
pipelines
'
,
'
pipelines_
graph
'
,
'
pipelines_
details
'
,
'
schedule_form
'
,
'
schedule_form
'
,
'
schedules_index
'
,
'
schedules_index
'
,
'
sidebar
'
,
'
sidebar
'
,
...
...
spec/javascripts/pipelines/graph/graph_component_spec.js
View file @
cad686cc
...
@@ -14,49 +14,42 @@ describe('graph component', () => {
...
@@ -14,49 +14,42 @@ describe('graph component', () => {
describe
(
'
while is loading
'
,
()
=>
{
describe
(
'
while is loading
'
,
()
=>
{
it
(
'
should render a loading icon
'
,
()
=>
{
it
(
'
should render a loading icon
'
,
()
=>
{
const
component
=
new
GraphComponent
().
$mount
(
'
#js-pipeline-graph-vue
'
);
const
component
=
new
GraphComponent
({
propsData
:
{
isLoading
:
true
,
pipeline
:
{},
},
}).
$mount
(
'
#js-pipeline-graph-vue
'
);
expect
(
component
.
$el
.
querySelector
(
'
.loading-icon
'
)).
toBeDefined
();
expect
(
component
.
$el
.
querySelector
(
'
.loading-icon
'
)).
toBeDefined
();
});
});
});
});
describe
(
'
with a successfull response
'
,
()
=>
{
describe
(
'
with data
'
,
()
=>
{
const
interceptor
=
(
request
,
next
)
=>
{
it
(
'
should render the graph
'
,
()
=>
{
next
(
request
.
respondWith
(
JSON
.
stringify
(
graphJSON
),
{
const
component
=
new
GraphComponent
({
status
:
200
,
propsData
:
{
}));
isLoading
:
false
,
};
pipeline
:
graphJSON
,
},
}).
$mount
(
'
#js-pipeline-graph-vue
'
);
beforeEach
(()
=>
{
expect
(
component
.
$el
.
classList
.
contains
(
'
js-pipeline-graph
'
)).
toEqual
(
true
);
Vue
.
http
.
interceptors
.
push
(
interceptor
);
});
afterEach
(()
=>
{
Vue
.
http
.
interceptors
=
_
.
without
(
Vue
.
http
.
interceptors
,
interceptor
);
});
it
(
'
should render the graph
'
,
(
done
)
=>
{
const
component
=
new
GraphComponent
().
$mount
(
'
#js-pipeline-graph-vue
'
);
setTimeout
(()
=>
{
expect
(
component
.
$el
.
classList
.
contains
(
'
js-pipeline-graph
'
)).
toEqual
(
true
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.stage-column:first-child
'
).
classList
.
contains
(
'
no-margin
'
),
component
.
$el
.
querySelector
(
'
.stage-column:first-child
'
).
classList
.
contains
(
'
no-margin
'
),
).
toEqual
(
true
);
).
toEqual
(
true
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2)
'
).
classList
.
contains
(
'
left-margin
'
),
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2)
'
).
classList
.
contains
(
'
left-margin
'
),
).
toEqual
(
true
);
).
toEqual
(
true
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2) .build:nth-child(1)
'
).
classList
.
contains
(
'
left-connector
'
),
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2) .build:nth-child(1)
'
).
classList
.
contains
(
'
left-connector
'
),
).
toEqual
(
true
);
).
toEqual
(
true
);
expect
(
component
.
$el
.
querySelector
(
'
loading-icon
'
)).
toBe
(
null
);
expect
(
component
.
$el
.
querySelector
(
'
loading-icon
'
)).
toBe
(
null
);
expect
(
component
.
$el
.
querySelector
(
'
.stage-column-list
'
)).
toBeDefined
();
expect
(
component
.
$el
.
querySelector
(
'
.stage-column-list
'
)).
toBeDefined
();
done
();
},
0
);
});
});
});
});
});
});
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