diff options
author | Zuul <zuul@review.opendev.org> | 2023-05-03 00:30:33 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2023-05-03 00:30:33 +0000 |
commit | 51194abf561de04972996199d825613a94cd3b2f (patch) | |
tree | ad759bc813af0bb716135251da1e54135748c276 /web/src/containers/build | |
parent | bbdbe81790f4926e5e00085309589a2c52e5230b (diff) | |
parent | 59cd5de78baa31150958e6d0d6733407c0e95805 (diff) | |
download | zuul-51194abf561de04972996199d825613a94cd3b2f.tar.gz |
Merge "web: add dark mode and theme selection"
Diffstat (limited to 'web/src/containers/build')
-rw-r--r-- | web/src/containers/build/Artifact.jsx | 25 | ||||
-rw-r--r-- | web/src/containers/build/BuildOutput.jsx | 30 | ||||
-rw-r--r-- | web/src/containers/build/BuildOutput.test.jsx | 8 | ||||
-rw-r--r-- | web/src/containers/build/Buildset.jsx | 8 | ||||
-rw-r--r-- | web/src/containers/build/Console.jsx | 32 |
5 files changed, 74 insertions, 29 deletions
diff --git a/web/src/containers/build/Artifact.jsx b/web/src/containers/build/Artifact.jsx index 3793222d9..0ada93a0c 100644 --- a/web/src/containers/build/Artifact.jsx +++ b/web/src/containers/build/Artifact.jsx @@ -18,15 +18,16 @@ import { TreeView, } from 'patternfly-react' import ReactJson from 'react-json-view' - +import { connect } from 'react-redux' class Artifact extends React.Component { static propTypes = { - artifact: PropTypes.object.isRequired + artifact: PropTypes.object.isRequired, + preferences: PropTypes.object, } render() { - const { artifact } = this.props + const { artifact, preferences } = this.props return ( <table className="table table-striped table-bordered" style={{width:'50%'}}> <tbody> @@ -41,7 +42,8 @@ class Artifact extends React.Component { collapsed={true} sortKeys={true} enableClipboard={false} - displayDataTypes={false}/> + displayDataTypes={false} + theme={preferences.darkMode ? 'tomorrow' : 'rjv-default'}/> :artifact.metadata[key].toString()} </td> </tr> @@ -54,17 +56,18 @@ class Artifact extends React.Component { class ArtifactList extends React.Component { static propTypes = { - artifacts: PropTypes.array.isRequired + artifacts: PropTypes.array.isRequired, + preferences: PropTypes.object, } render() { - const { artifacts } = this.props + const { artifacts, preferences } = this.props const nodes = artifacts.map((artifact, index) => { const node = {text: <a href={artifact.url}>{artifact.name}</a>, icon: null} if (artifact.metadata) { - node['nodes']= [{text: <Artifact key={index} artifact={artifact}/>, + node['nodes']= [{text: <Artifact key={index} artifact={artifact} preferences={preferences}/>, icon: ''}] } return node @@ -83,4 +86,10 @@ class ArtifactList extends React.Component { } } -export default ArtifactList +function mapStateToProps(state) { + return { + preferences: state.preferences, + } +} + +export default connect(mapStateToProps)(ArtifactList) diff --git a/web/src/containers/build/BuildOutput.jsx b/web/src/containers/build/BuildOutput.jsx index 1098ed2c7..58f0e13b5 100644 --- a/web/src/containers/build/BuildOutput.jsx +++ b/web/src/containers/build/BuildOutput.jsx @@ -13,6 +13,7 @@ // under the License. import * as React from 'react' +import { connect } from 'react-redux' import { Fragment } from 'react' import ReAnsi from '@softwarefactory-project/re-ansi' import PropTypes from 'prop-types' @@ -73,6 +74,7 @@ class BuildOutputLabel extends React.Component { class BuildOutput extends React.Component { static propTypes = { output: PropTypes.object, + preferences: PropTypes.object, } renderHosts (hosts) { @@ -109,8 +111,12 @@ class BuildOutput extends React.Component { renderFailedTask (host, task) { const max_lines = 42 + let zuulOutputClass = 'zuul-build-output' + if (this.props.preferences.darkMode) { + zuulOutputClass = 'zuul-build-output-dark' + } return ( - <Card key={host + task.zuul_log_id} className="zuul-task-summary-failed"> + <Card key={host + task.zuul_log_id} className="zuul-task-summary-failed" style={this.props.preferences.darkMode ? {background: 'var(--pf-global--BackgroundColor--300)'} : {}}> <CardHeader> <TimesIcon style={{ color: 'var(--pf-global--danger-color--100)' }}/> Task <strong>{task.name}</strong> @@ -119,25 +125,25 @@ class BuildOutput extends React.Component { <CardBody> {task.invocation && task.invocation.module_args && task.invocation.module_args._raw_params && ( - <pre key="cmd" title="cmd" className={`${'cmd'}`}> + <pre key="cmd" title="cmd" className={'cmd ' + zuulOutputClass}> {task.invocation.module_args._raw_params} </pre> )} {task.msg && ( - <pre key="msg" title="msg">{task.msg}</pre> + <pre key="msg" title="msg" className={zuulOutputClass}>{task.msg}</pre> )} {task.exception && ( - <pre key="exc" style={{ color: 'red' }} title="exc">{task.exception}</pre> + <pre key="exc" style={{ color: 'red' }} title="exc" className={zuulOutputClass}>{task.exception}</pre> )} {task.stdout_lines && task.stdout_lines.length > 0 && ( <Fragment> {task.stdout_lines.length > max_lines && ( <details className={`${'foldable'} ${'stdout'}`}><summary></summary> - <pre key="stdout" title="stdout"> + <pre key="stdout" title="stdout" className={zuulOutputClass}> <ReAnsi log={task.stdout_lines.slice(0, -max_lines).join('\n')} /> </pre> </details>)} - <pre key="stdout" title="stdout"> + <pre key="stdout" title="stdout" className={zuulOutputClass}> <ReAnsi log={task.stdout_lines.slice(-max_lines).join('\n')} /> </pre> </Fragment> @@ -146,12 +152,12 @@ class BuildOutput extends React.Component { <Fragment> {task.stderr_lines.length > max_lines && ( <details className={`${'foldable'} ${'stderr'}`}><summary></summary> - <pre key="stderr" title="stderr"> + <pre key="stderr" title="stderr" className={zuulOutputClass}> <ReAnsi log={task.stderr_lines.slice(0, -max_lines).join('\n')} /> </pre> </details> )} - <pre key="stderr" title="stderr"> + <pre key="stderr" title="stderr" className={zuulOutputClass}> <ReAnsi log={task.stderr_lines.slice(-max_lines).join('\n')} /> </pre> </Fragment> @@ -177,4 +183,10 @@ class BuildOutput extends React.Component { } -export default BuildOutput +function mapStateToProps(state) { + return { + preferences: state.preferences, + } +} + +export default connect(mapStateToProps)(BuildOutput) diff --git a/web/src/containers/build/BuildOutput.test.jsx b/web/src/containers/build/BuildOutput.test.jsx index c76236a2e..defa342c5 100644 --- a/web/src/containers/build/BuildOutput.test.jsx +++ b/web/src/containers/build/BuildOutput.test.jsx @@ -14,6 +14,8 @@ import React from 'react' import ReactDOM from 'react-dom' +import { Provider } from 'react-redux' +import configureStore from '../../store' import BuildOutput from './BuildOutput' const fakeOutput = (width, height) => ({ @@ -31,7 +33,11 @@ it('BuildOutput renders big task', () => { const div = document.createElement('div') const output = fakeOutput(512, 1024) const begin = performance.now() - ReactDOM.render(<BuildOutput output={output} />, div, () => { + const store = configureStore() + ReactDOM.render( + <Provider store={store}> + <BuildOutput output={output} /> + </Provider>, div, () => { const end = performance.now() console.log('Render took ' + (end - begin) + ' milliseconds.') }) diff --git a/web/src/containers/build/Buildset.jsx b/web/src/containers/build/Buildset.jsx index 2ca70549d..5492b7a13 100644 --- a/web/src/containers/build/Buildset.jsx +++ b/web/src/containers/build/Buildset.jsx @@ -47,7 +47,7 @@ import { addNotification, addApiError } from '../../actions/notifications' import { ChartModal } from '../charts/ChartModal' import BuildsetGanttChart from '../charts/GanttChart' -function Buildset({ buildset, timezone, tenant, user }) { +function Buildset({ buildset, timezone, tenant, user, preferences }) { const buildset_link = buildExternalLink(buildset) const [isGanttChartModalOpen, setIsGanttChartModalOpen] = useState(false) @@ -319,7 +319,9 @@ function Buildset({ buildset, timezone, tenant, user }) { value={ <> <strong>Message:</strong> - <pre>{buildset.message}</pre> + <div className={preferences.darkMode ? 'zuul-console-dark' : ''}> + <pre>{buildset.message}</pre> + </div> </> } /> @@ -349,10 +351,12 @@ Buildset.propTypes = { tenant: PropTypes.object, timezone: PropTypes.string, user: PropTypes.object, + preferences: PropTypes.object, } export default connect((state) => ({ tenant: state.tenant, timezone: state.timezone, user: state.user, + preferences: state.preferences, }))(Buildset) diff --git a/web/src/containers/build/Console.jsx b/web/src/containers/build/Console.jsx index 9cd10df92..826ebe3cd 100644 --- a/web/src/containers/build/Console.jsx +++ b/web/src/containers/build/Console.jsx @@ -18,6 +18,7 @@ import * as React from 'react' import ReAnsi from '@softwarefactory-project/re-ansi' import PropTypes from 'prop-types' import ReactJson from 'react-json-view' +import { connect } from 'react-redux' import { Button, @@ -60,6 +61,7 @@ class TaskOutput extends React.Component { static propTypes = { data: PropTypes.object, include: PropTypes.array, + preferences: PropTypes.object, } renderResults(value) { @@ -130,7 +132,8 @@ class TaskOutput extends React.Component { name={null} sortKeys={true} enableClipboard={false} - displayDataTypes={false}/> + displayDataTypes={false} + theme={this.props.preferences.darkMode ? 'tomorrow' : 'rjv-default'}/> </pre> ) } else { @@ -142,7 +145,7 @@ class TaskOutput extends React.Component { } return ( - <div key={key}> + <div className={this.props.preferences.darkMode ? 'zuul-console-dark' : 'zuul-console-light'} key={key}> {ret && <h5>{key}</h5>} {ret && ret} </div> @@ -170,6 +173,7 @@ class HostTask extends React.Component { errorIds: PropTypes.object, taskPath: PropTypes.array, displayPath: PropTypes.array, + preferences: PropTypes.object, } state = { @@ -290,7 +294,7 @@ class HostTask extends React.Component { </DataListCell> ) - const content = <TaskOutput data={this.props.host} include={INTERESTING_KEYS}/> + const content = <TaskOutput data={this.props.host} include={INTERESTING_KEYS} preferences={this.props.preferences}/> let item = null if (interestingKeys) { @@ -354,7 +358,7 @@ class HostTask extends React.Component { isOpen={this.state.showModal} onClose={this.close} description={modalDescription}> - <TaskOutput data={host}/> + <TaskOutput data={host} preferences={this.props.preferences}/> </Modal> </> ) @@ -367,6 +371,7 @@ class PlayBook extends React.Component { errorIds: PropTypes.object, taskPath: PropTypes.array, displayPath: PropTypes.array, + preferences: PropTypes.object, } constructor(props) { @@ -404,8 +409,8 @@ class PlayBook extends React.Component { dataListCells.push( <DataListCell key='name' width={1}> <strong> - {playbook.phase[0].toUpperCase() + playbook.phase.slice(1)} playbook< - /strong> + {playbook.phase[0].toUpperCase() + playbook.phase.slice(1)} playbook + </strong> </DataListCell>) dataListCells.push( <DataListCell key='path' width={5}> @@ -463,7 +468,8 @@ class PlayBook extends React.Component { taskPath={taskPath.concat([ idx.toString(), idx2.toString(), hostname])} displayPath={displayPath} task={task} host={host} - errorIds={errorIds}/> + errorIds={errorIds} + preferences={this.props.preferences}/> ))))} </DataList> @@ -484,6 +490,7 @@ class Console extends React.Component { errorIds: PropTypes.object, output: PropTypes.array, displayPath: PropTypes.array, + preferences: PropTypes.object, } render () { @@ -492,7 +499,7 @@ class Console extends React.Component { return ( <React.Fragment> <br /> - <span className="zuul-console"> + <span className={`zuul-console ${this.props.preferences.darkMode ? 'zuul-console-dark' : 'zuul-console-light'}`}> <DataList isCompact={true} style={{ fontSize: 'var(--pf-global--FontSize--md)' }}> { @@ -500,6 +507,7 @@ class Console extends React.Component { <PlayBook key={idx} playbook={playbook} taskPath={[idx.toString()]} displayPath={displayPath} errorIds={errorIds} + preferences={this.props.preferences} />)) } </DataList> @@ -509,5 +517,11 @@ class Console extends React.Component { } } +function mapStateToProps(state) { + return { + preferences: state.preferences, + } +} + -export default Console +export default connect(mapStateToProps)(Console) |