-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add ui_next dashboard #8402
Merged
softwarefactory-project-zuul
merged 8 commits into
ansible:devel
from
jlmitch5:dashboardAug20
Oct 22, 2020
Merged
add ui_next dashboard #8402
Changes from 5 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
782e8d5
add two_weeks filter to dashbaord job graph api view
5ea98ab
add copy of template list for dashboard use, moving around shared ws …
a3c5f50
add dashboard (including counts, line chart and portal mode style lis…
8839fb9
remove unused comment from template lists
5f4d6da
update dashboard to 3 tab single pane
52deb7f
update dashboard and graph code to aid in automated testing
2c0de9c
update render dashboard default unit t est
e30569c
Change the id from / to -
tiagodread File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import Base from '../Base'; | ||
|
||
class Dashboard extends Base { | ||
constructor(http) { | ||
super(http); | ||
this.baseUrl = '/api/v2/dashboard/'; | ||
} | ||
|
||
readJobGraph(params) { | ||
return this.http.get(`${this.baseUrl}graphs/jobs/`, { | ||
params, | ||
}); | ||
} | ||
} | ||
|
||
export default Dashboard; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,253 @@ | ||
import React, { Component, Fragment } from 'react'; | ||
import React, { Fragment, useCallback, useEffect, useState } from 'react'; | ||
import styled from 'styled-components'; | ||
import { withI18n } from '@lingui/react'; | ||
import { t } from '@lingui/macro'; | ||
import { | ||
Card, | ||
CardHeader, | ||
CardActions, | ||
CardBody, | ||
PageSection, | ||
PageSectionVariants, | ||
Select, | ||
SelectVariant, | ||
SelectOption, | ||
Tabs, | ||
Tab, | ||
TabTitleText, | ||
Title, | ||
} from '@patternfly/react-core'; | ||
|
||
class Dashboard extends Component { | ||
render() { | ||
const { i18n } = this.props; | ||
const { light } = PageSectionVariants; | ||
|
||
return ( | ||
<Fragment> | ||
<PageSection variant={light} className="pf-m-condensed"> | ||
<Title size="2xl" headingLevel="h2"> | ||
{i18n._(t`Dashboard`)} | ||
</Title> | ||
</PageSection> | ||
<PageSection /> | ||
</Fragment> | ||
); | ||
import useRequest from '../../util/useRequest'; | ||
import { DashboardAPI } from '../../api'; | ||
import JobList from '../../components/JobList'; | ||
|
||
import LineChart from './shared/LineChart'; | ||
import Count from './shared/Count'; | ||
import DashboardTemplateList from './shared/DashboardTemplateList'; | ||
|
||
const Counts = styled.div` | ||
display: grid; | ||
grid-template-columns: repeat(6, 1fr); | ||
grid-gap: var(--pf-global--spacer--lg); | ||
|
||
@media (max-width: 900px) { | ||
grid-template-columns: repeat(3, 1fr); | ||
grid-auto-rows: 1fr; | ||
} | ||
`; | ||
|
||
const MainPageSection = styled(PageSection)` | ||
padding-top: 0; | ||
padding-bottom: 0; | ||
|
||
& .spacer { | ||
margin-bottom: var(--pf-global--spacer--lg); | ||
} | ||
`; | ||
|
||
const GraphCardHeader = styled(CardHeader)` | ||
margin-top: var(--pf-global--spacer--lg); | ||
`; | ||
|
||
const GraphCardActions = styled(CardActions)` | ||
margin-left: initial; | ||
padding-left: 0; | ||
`; | ||
|
||
function Dashboard({ i18n }) { | ||
const { light } = PageSectionVariants; | ||
|
||
const [isPeriodDropdownOpen, setIsPeriodDropdownOpen] = useState(false); | ||
const [isJobTypeDropdownOpen, setIsJobTypeDropdownOpen] = useState(false); | ||
const [periodSelection, setPeriodSelection] = useState('month'); | ||
const [jobTypeSelection, setJobTypeSelection] = useState('all'); | ||
const [activeTabId, setActiveTabId] = useState(0); | ||
|
||
const { | ||
result: { jobGraphData, countData }, | ||
request: fetchDashboardGraph, | ||
} = useRequest( | ||
useCallback(async () => { | ||
const [{ data }, { data: dataFromCount }] = await Promise.all([ | ||
DashboardAPI.readJobGraph({ | ||
period: periodSelection, | ||
job_type: jobTypeSelection, | ||
}), | ||
DashboardAPI.read(), | ||
]); | ||
const newData = {}; | ||
data.jobs.successful.forEach(([dateSecs, count]) => { | ||
if (!newData[dateSecs]) { | ||
newData[dateSecs] = {}; | ||
} | ||
newData[dateSecs].successful = count; | ||
}); | ||
data.jobs.failed.forEach(([dateSecs, count]) => { | ||
if (!newData[dateSecs]) { | ||
newData[dateSecs] = {}; | ||
} | ||
newData[dateSecs].failed = count; | ||
}); | ||
const jobData = Object.keys(newData).map(dateSecs => { | ||
const [created] = new Date(dateSecs * 1000).toISOString().split('T'); | ||
newData[dateSecs].created = created; | ||
return newData[dateSecs]; | ||
}); | ||
return { | ||
jobGraphData: jobData, | ||
countData: dataFromCount, | ||
}; | ||
}, [periodSelection, jobTypeSelection]), | ||
{ | ||
jobGraphData: [], | ||
countData: {}, | ||
} | ||
); | ||
|
||
useEffect(() => { | ||
fetchDashboardGraph(); | ||
}, [fetchDashboardGraph, periodSelection, jobTypeSelection]); | ||
|
||
return ( | ||
<Fragment> | ||
<PageSection variant={light} className="pf-m-condensed"> | ||
<Title size="2xl" headingLevel="h2"> | ||
{i18n._(t`Dashboard`)} | ||
</Title> | ||
</PageSection> | ||
<PageSection> | ||
<Counts> | ||
<Count | ||
link="/hosts" | ||
data={countData?.hosts?.total} | ||
label={i18n._(t`Hosts`)} | ||
/> | ||
<Count | ||
failed | ||
link="/hosts?host.last_job_host_summary__failed=true" | ||
data={countData?.hosts?.failed} | ||
label={i18n._(t`Failed hosts`)} | ||
/> | ||
<Count | ||
link="/inventories" | ||
data={countData?.inventories?.total} | ||
label={i18n._(t`Inventories`)} | ||
/> | ||
<Count | ||
failed | ||
link="/inventories?inventory.inventory_sources_with_failures__gt=0" | ||
data={countData?.inventories?.failed} | ||
label={i18n._(t`Inventory sync failures`)} | ||
/> | ||
<Count | ||
link="/projects" | ||
data={countData?.projects?.total} | ||
label={i18n._(t`Projects`)} | ||
/> | ||
<Count | ||
failed | ||
link="/projects?project.status__in=failed,canceled" | ||
data={countData?.projects?.failed} | ||
label={i18n._(t`Project sync failures`)} | ||
/> | ||
</Counts> | ||
</PageSection> | ||
<MainPageSection> | ||
<div className="spacer"> | ||
<Card> | ||
<Tabs | ||
aria-label={i18n._(t`Tabs`)} | ||
activeKey={activeTabId} | ||
onSelect={(key, eventKey) => setActiveTabId(eventKey)} | ||
> | ||
<Tab | ||
aria-label={i18n._(t`Job status graph tab`)} | ||
eventKey={0} | ||
title={<TabTitleText>{i18n._(t`Job status`)}</TabTitleText>} | ||
/> | ||
<Tab | ||
aria-label={i18n._(t`Recent Jobs list tab`)} | ||
eventKey={1} | ||
title={<TabTitleText>{i18n._(t`Recent Jobs`)}</TabTitleText>} | ||
/> | ||
<Tab | ||
aria-label={i18n._(t`Recent Templates list tab`)} | ||
eventKey={2} | ||
title={ | ||
<TabTitleText>{i18n._(t`Recent Templates`)}</TabTitleText> | ||
} | ||
/> | ||
</Tabs> | ||
{activeTabId === 0 && ( | ||
<Fragment> | ||
<GraphCardHeader> | ||
<GraphCardActions> | ||
<Select | ||
variant={SelectVariant.single} | ||
placeholderText={i18n._(t`Select period`)} | ||
aria-label={i18n._(t`Select period`)} | ||
className="periodSelect" | ||
onToggle={setIsPeriodDropdownOpen} | ||
onSelect={(event, selection) => | ||
setPeriodSelection(selection) | ||
} | ||
selections={periodSelection} | ||
isOpen={isPeriodDropdownOpen} | ||
> | ||
<SelectOption key="month" value="month"> | ||
{i18n._(t`Past month`)} | ||
</SelectOption> | ||
<SelectOption key="two_weeks" value="two_weeks"> | ||
{i18n._(t`Past two weeks`)} | ||
</SelectOption> | ||
<SelectOption key="week" value="week"> | ||
{i18n._(t`Past week`)} | ||
</SelectOption> | ||
</Select> | ||
<Select | ||
variant={SelectVariant.single} | ||
placeholderText={i18n._(t`Select job type`)} | ||
aria-label={i18n._(t`Select job type`)} | ||
className="jobTypeSelect" | ||
onToggle={setIsJobTypeDropdownOpen} | ||
onSelect={(event, selection) => | ||
setJobTypeSelection(selection) | ||
} | ||
selections={jobTypeSelection} | ||
isOpen={isJobTypeDropdownOpen} | ||
> | ||
<SelectOption key="all" value="all"> | ||
{i18n._(t`All job types`)} | ||
</SelectOption> | ||
<SelectOption key="inv_sync" value="inv_sync"> | ||
{i18n._(t`Inventory sync`)} | ||
</SelectOption> | ||
<SelectOption key="scm_update" value="scm_update"> | ||
{i18n._(t`SCM update`)} | ||
</SelectOption> | ||
<SelectOption key="playbook_run" value="playbook_run"> | ||
{i18n._(t`Playbook run`)} | ||
</SelectOption> | ||
</Select> | ||
</GraphCardActions> | ||
</GraphCardHeader> | ||
<CardBody> | ||
<LineChart | ||
height={390} | ||
id="d3-line-chart-root" | ||
data={jobGraphData} | ||
/> | ||
</CardBody> | ||
</Fragment> | ||
)} | ||
{activeTabId === 1 && <JobList defaultParams={{ page_size: 5 }} />} | ||
{activeTabId === 2 && <DashboardTemplateList />} | ||
</Card> | ||
</div> | ||
</MainPageSection> | ||
</Fragment> | ||
); | ||
} | ||
|
||
export default withI18n()(Dashboard); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ryanpetrello this look good to you? Just want to make sure we're not sneaking something by y'all without a review.