summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2019-08-08 21:23:22 +0000
committerGerrit Code Review <review@openstack.org>2019-08-08 21:23:22 +0000
commit459ee2f1d3c18ef264b473d75850ffdec6fd163e (patch)
tree4657dcd2b630e4a557fb7fbfdc6014f968b9a8d4
parent9bde4211a706c6ca618aba3e7cda91b0dce08efe (diff)
parent5b0bbb6ca5fc76af90421d05f81a925147af3021 (diff)
downloadzuul-459ee2f1d3c18ef264b473d75850ffdec6fd163e.tar.gz
Merge "Add permalinks to task detail popup"
-rw-r--r--web/src/containers/build/Console.jsx51
-rw-r--r--web/src/index.css5
-rw-r--r--web/src/pages/BuildConsole.jsx4
3 files changed, 51 insertions, 9 deletions
diff --git a/web/src/containers/build/Console.jsx b/web/src/containers/build/Console.jsx
index e5067bd1e..9843aeb17 100644
--- a/web/src/containers/build/Console.jsx
+++ b/web/src/containers/build/Console.jsx
@@ -60,6 +60,20 @@ function hasInterestingKeys (obj, keys) {
return ret
}
+function makeTaskPath (path) {
+ return path.join('/')
+}
+
+function taskPathMatches (ref, test) {
+ if (test.length < ref.length)
+ return false
+ for (let i=0; i < ref.length; i++) {
+ if (ref[i] !== test[i])
+ return false
+ }
+ return true
+}
+
class TaskOutput extends React.Component {
static propTypes = {
data: PropTypes.object,
@@ -180,6 +194,8 @@ class HostTask extends React.Component {
task: PropTypes.object,
host: PropTypes.object,
errorIds: PropTypes.object,
+ taskPath: PropTypes.array,
+ displayPath: PropTypes.array,
}
state = {
@@ -201,13 +217,16 @@ class HostTask extends React.Component {
constructor (props) {
super(props)
- const { host } = this.props
+ const { host, taskPath, displayPath } = this.props
hostTaskStats(this.state, host)
+
+ if (taskPathMatches(taskPath, displayPath))
+ this.state.showModal = true
}
render () {
- const { hostname, task, host, errorIds } = this.props
+ const { hostname, task, host, taskPath, errorIds } = this.props
const ai = []
if (this.state.skipped) {
@@ -244,6 +263,7 @@ class HostTask extends React.Component {
)
const expand = errorIds.has(task.task.id)
+
let name = task.task.name
if (!name) {
name = host.action
@@ -286,7 +306,13 @@ class HostTask extends React.Component {
>
<Icon type="pf" name="close" />
</button>
- <Modal.Title>{hostname}</Modal.Title>
+ <Modal.Title>{hostname}
+ <span className="zuul-console-modal-header-link">
+ <a href={'#'+makeTaskPath(taskPath)}>
+ <Icon type="fa" name="link" title="Permalink" />
+ </a>
+ </span>
+ </Modal.Title>
</Modal.Header>
<Modal.Body>
<TaskOutput data={host}/>
@@ -301,13 +327,17 @@ class PlayBook extends React.Component {
static propTypes = {
playbook: PropTypes.object,
errorIds: PropTypes.object,
+ taskPath: PropTypes.array,
+ displayPath: PropTypes.array,
}
render () {
- const { playbook, errorIds } = this.props
+ const { playbook, errorIds, taskPath, displayPath } = this.props
const expandAll = (playbook.phase === 'run')
- const expand = (expandAll || errorIds.has(playbook.phase + playbook.index))
+ const expand = (expandAll ||
+ errorIds.has(playbook.phase + playbook.index) ||
+ taskPathMatches(taskPath, displayPath))
const ai = []
if (playbook.trusted) {
@@ -340,7 +370,10 @@ class PlayBook extends React.Component {
<Row key={idx2+hostname}>
<Col sm={12}>
<HostTask hostname={hostname}
- task={task} host={host} errorIds={errorIds}/>
+ taskPath={taskPath.concat([
+ idx.toString(), idx2.toString(), hostname])}
+ displayPath={displayPath} task={task} host={host}
+ errorIds={errorIds}/>
</Col>
</Row>
))))}
@@ -354,6 +387,7 @@ class PlayBook extends React.Component {
class Console extends React.Component {
static propTypes = {
output: PropTypes.array,
+ displayPath: PropTypes.array,
}
constructor (props) {
@@ -394,13 +428,14 @@ class Console extends React.Component {
}
render () {
- const { output } = this.props
+ const { output, displayPath } = this.props
return (
<React.Fragment>
<ListView key="playbooks" className="zuul-console">
{output.map((playbook, idx) => (
- <PlayBook key={idx} playbook={playbook} errorIds={this.errorIds}/>))}
+ <PlayBook key={idx} playbook={playbook} taskPath={[idx.toString()]}
+ displayPath={displayPath} errorIds={this.errorIds}/>))}
</ListView>
</React.Fragment>
)
diff --git a/web/src/index.css b/web/src/index.css
index 5f917e77e..9e7ac0138 100644
--- a/web/src/index.css
+++ b/web/src/index.css
@@ -226,6 +226,11 @@ pre.version {
{
cursor: default;
}
+.zuul-console-modal-header-link
+{
+ margin-left: 2em;
+ font-size: 18px;
+}
.zuul-console-task-detail
{
width: 80%;
diff --git a/web/src/pages/BuildConsole.jsx b/web/src/pages/BuildConsole.jsx
index 7ffba3d26..550197e41 100644
--- a/web/src/pages/BuildConsole.jsx
+++ b/web/src/pages/BuildConsole.jsx
@@ -42,6 +42,8 @@ class BuildConsolePage extends Refreshable {
render () {
const { remoteData } = this.props
const build = remoteData.builds[this.props.match.params.buildId]
+ const hash = this.props.location.hash.substring(1).split('/')
+
return (
<React.Fragment>
<div style={{float: 'right'}}>
@@ -49,7 +51,7 @@ class BuildConsolePage extends Refreshable {
</div>
{build && build.output &&
<Build build={build} active='console'>
- <Console output={build.output}/>
+ <Console output={build.output} displayPath={hash.length>0?hash:undefined}/>
</Build>}
</React.Fragment>
)