Skip to content

Commit

Permalink
Migrate components from SUIR to MUI.
Browse files Browse the repository at this point in the history
  • Loading branch information
fniessink committed Dec 18, 2024
1 parent 0b0611a commit f84d25a
Show file tree
Hide file tree
Showing 45 changed files with 634 additions and 468 deletions.
7 changes: 4 additions & 3 deletions components/frontend/src/fields/DateInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import "./DateInput.css"
import { bool, func, string } from "prop-types"

import { ReadOnlyOrEditable } from "../context/Permissions"
import { Form, Icon, Label } from "../semantic_ui_react_wrappers"
import { Form, Label } from "../semantic_ui_react_wrappers"
import { labelPropType, permissionsPropType } from "../sharedPropTypes"
import { toISODateStringInCurrentTZ } from "../utils"
import { DatePicker } from "../widgets/DatePicker"
import { CalendarIcon } from "../widgets/icons"
import { ReadOnlyInput } from "./ReadOnlyInput"

function EditableDateInput({ ariaLabelledBy, label, placeholder, required, set_value, value }) {
value = value ? new Date(value) : null
return (
<Form.Input error={required && !value} label={label} labelPosition="left" required={required}>
<Label>
<Icon fitted name="calendar" />
<Label style={{ padding: "8px" }}>
<CalendarIcon />
</Label>
<DatePicker
ariaLabelledBy={ariaLabelledBy}
Expand Down
7 changes: 3 additions & 4 deletions components/frontend/src/issue/IssuesRows.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { ErrorMessage } from "../errorMessage"
import { MultipleChoiceInput } from "../fields/MultipleChoiceInput"
import { metricPropType, reportPropType } from "../sharedPropTypes"
import { getMetricIssueIds } from "../utils"
import { ActionButton } from "../widgets/Button"
import { ActionButton } from "../widgets/buttons/ActionButton"
import { AddItemIcon } from "../widgets/icons"
import { LabelWithHelp } from "../widgets/LabelWithHelp"
import { showMessage } from "../widgets/toast"

Expand All @@ -18,8 +19,7 @@ function CreateIssueButton({ issueTrackerConfigured, issueTrackerInstruction, me
<ActionButton
action="Create new"
disabled={!issueTrackerConfigured}
fluid
icon="plus"
icon={<AddItemIcon />}
itemType="issue"
onClick={() => add_metric_issue(metric_uuid, reload)}
popup={
Expand All @@ -28,7 +28,6 @@ function CreateIssueButton({ issueTrackerConfigured, issueTrackerInstruction, me
tracked issue identifiers.{issueTrackerInstruction}
</>
}
position="top center"
/>
)
}
Expand Down
10 changes: 6 additions & 4 deletions components/frontend/src/measurement/MeasurementValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { bool, string } from "prop-types"
import { useContext } from "react"

import { DataModel } from "../context/DataModel"
import { Icon, Label, Message, Popup } from "../semantic_ui_react_wrappers"
import { Label, Message, Popup } from "../semantic_ui_react_wrappers"
import { datePropType, measurementPropType, metricPropType } from "../sharedPropTypes"
import { IGNORABLE_SOURCE_ENTITY_STATUSES, SOURCE_ENTITY_STATUS_NAME } from "../source/source_entity_status"
import {
Expand All @@ -17,13 +17,14 @@ import {
isMeasurementStale,
sum,
} from "../utils"
import { IgnoreIcon, LoadingIcon } from "../widgets/icons"
import { TimeAgoWithDate } from "../widgets/TimeAgoWithDate"
import { WarningMessage } from "../widgets/WarningMessage"

function measurementValueLabel(hasIgnoredEntities, stale, updating, value) {
const measurementValue = hasIgnoredEntities ? (
<>
<Icon name="hide" /> {value}
<IgnoreIcon /> {value}
</>
) : (
value
Expand All @@ -34,7 +35,8 @@ function measurementValueLabel(hasIgnoredEntities, stale, updating, value) {
if (updating) {
return (
<Label color="yellow">
<Icon loading name="hourglass" /> {measurementValue}
<LoadingIcon />
{measurementValue}
</Label>
)
}
Expand Down Expand Up @@ -124,7 +126,7 @@ export function MeasurementValue({ metric, reportDate }) {
info
header={
<span>
<Icon name="hide" /> {`Ignored ${unit}`}
<IgnoreIcon /> {`Ignored ${unit}`}
</span>
}
content={ignoredEntitiesMessage(metric.latest_measurement, unit)}
Expand Down
5 changes: 3 additions & 2 deletions components/frontend/src/measurement/MeasurementValue.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ it("renders an outdated value", async () => {
})
const measurementValue = screen.getByText(/1/)
expect(measurementValue.className).toContain("yellow")
expect(measurementValue.children[0].className).toContain("loading")
expect(screen.getAllByTestId("LoopIcon").length).toBe(1)
await userEvent.hover(measurementValue)
await waitFor(() => {
expect(screen.queryByText(/Latest measurement out of date/)).not.toBe(null)
Expand All @@ -74,7 +74,7 @@ it("renders a value for which a measurement was requested", async () => {
})
const measurementValue = screen.getByText(/1/)
expect(measurementValue.className).toContain("yellow")
expect(measurementValue.children[0].className).toContain("loading")
expect(screen.getAllByTestId("LoopIcon").length).toBe(1)
await userEvent.hover(measurementValue)
await waitFor(() => {
expect(screen.queryByText(/Measurement requested/)).not.toBe(null)
Expand All @@ -90,6 +90,7 @@ it("renders a value for which a measurement was requested, but which is now up t
})
const measurementValue = screen.getByText(/1/)
expect(measurementValue.className).not.toContain("yellow")
expect(screen.queryAllByTestId("LoopIcon").length).toBe(0)
await userEvent.hover(measurementValue)
await waitFor(() => {
expect(screen.queryByText(/Measurement requested/)).toBe(null)
Expand Down
29 changes: 21 additions & 8 deletions components/frontend/src/metric/MetricDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ import { Logo } from "../source/Logo"
import { SourceEntities } from "../source/SourceEntities"
import { Sources } from "../source/Sources"
import { getSourceName, isMeasurementRequested } from "../utils"
import { ActionButton, DeleteButton, PermLinkButton, ReorderButtonGroup } from "../widgets/Button"
import { ButtonRow } from "../widgets/ButtonRow"
import { ActionButton } from "../widgets/buttons/ActionButton"
import { DeleteButton } from "../widgets/buttons/DeleteButton"
import { PermLinkButton } from "../widgets/buttons/PermLinkButton"
import { ReorderButtonGroup } from "../widgets/buttons/ReorderButtonGroup"
import { RefreshIcon } from "../widgets/icons"
import { changelogTabPane, configurationTabPane, tabPane } from "../widgets/TabPane"
import { showMessage } from "../widgets/toast"
import { MetricConfigurationParameters } from "./MetricConfigurationParameters"
Expand All @@ -34,7 +39,7 @@ function RequestMeasurementButton({ metric, metric_uuid, reload }) {
<ActionButton
action="Measure"
disabled={measurementRequested}
icon="refresh"
icon={<RefreshIcon />}
itemType="metric"
loading={measurementRequested}
onClick={() => set_metric_attribute(metric_uuid, "measurement_requested", new Date().toISOString(), reload)}
Expand All @@ -48,12 +53,21 @@ RequestMeasurementButton.propTypes = {
reload: func,
}

function Buttons({ isFirstMetric, isLastMetric, metric, metric_uuid, reload, stopFilteringAndSorting, url }) {
function MetricDetailsButtonRow({
isFirstMetric,
isLastMetric,
metric,
metric_uuid,
reload,
stopFilteringAndSorting,
url,
}) {
const deleteButton = <DeleteButton itemType="metric" onClick={() => delete_metric(metric_uuid, reload)} />
return (
<ReadOnlyOrEditable
requiredPermissions={[EDIT_REPORT_PERMISSION]}
editableComponent={
<div style={{ marginTop: "20px" }}>
<ButtonRow rightButton={deleteButton}>
<ReorderButtonGroup
first={isFirstMetric}
last={isLastMetric}
Expand All @@ -66,13 +80,12 @@ function Buttons({ isFirstMetric, isLastMetric, metric, metric_uuid, reload, sto
/>
<PermLinkButton itemType="metric" url={url} />
<RequestMeasurementButton metric={metric} metric_uuid={metric_uuid} reload={reload} />
<DeleteButton itemType="metric" onClick={() => delete_metric(metric_uuid, reload)} />
</div>
</ButtonRow>
}
/>
)
}
Buttons.propTypes = {
MetricDetailsButtonRow.propTypes = {
isFirstMetric: bool,
isLastMetric: bool,
metric: metricPropType,
Expand Down Expand Up @@ -198,7 +211,7 @@ export function MetricDetails({
onTabChange={tabChangeHandler(expandedItems, metric_uuid)}
panes={panes}
/>
<Buttons
<MetricDetailsButtonRow
metric={metric}
metric_uuid={metric_uuid}
isFirstMetric={isFirstMetric}
Expand Down
2 changes: 1 addition & 1 deletion components/frontend/src/metric/MetricDetails.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ it("displays whether sources have warnings", async () => {
it("moves the metric", async () => {
const mockCallback = jest.fn()
await renderMetricDetails(mockCallback)
await act(async () => fireEvent.click(screen.getByLabelText(/Move metric to the last row/)))
await act(async () => fireEvent.click(screen.getByRole("button", { name: /Move metric to the last row/ })))
expect(mockCallback).toHaveBeenCalled()
expect(measurement_api.get_metric_measurements).toHaveBeenCalled()
})
Expand Down
9 changes: 2 additions & 7 deletions components/frontend/src/metric/MetricTypeHeader.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Icon } from "semantic-ui-react"

import { Header } from "../semantic_ui_react_wrappers"
import { metricTypePropType } from "../sharedPropTypes"
import { slugify } from "../utils"
import { HyperLink } from "../widgets/HyperLink"
import { ReadTheDocsLink } from "../widgets/ReadTheDocsLink"

export function MetricTypeHeader({ metricType }) {
const url = `https://quality-time.readthedocs.io/en/v${process.env.REACT_APP_VERSION}/reference.html${slugify(metricType.name)}`
Expand All @@ -15,10 +13,7 @@ export function MetricTypeHeader({ metricType }) {
<Header.Content>
{metricType.name}
<Header.Subheader>
{metricType.description}{" "}
<HyperLink url={url}>
Read the Docs <Icon name="external" link />
</HyperLink>
{metricType.description} <ReadTheDocsLink url={url} />
{howToConfigure}
</Header.Subheader>
</Header.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { EDIT_REPORT_PERMISSION, ReadOnlyOrEditable } from "../context/Permissio
import { StringInput } from "../fields/StringInput"
import { Message, Segment } from "../semantic_ui_react_wrappers"
import { destinationPropType } from "../sharedPropTypes"
import { AddButton, DeleteButton } from "../widgets/Button"
import { AddButton } from "../widgets/buttons/AddButton"
import { DeleteButton } from "../widgets/buttons/DeleteButton"
import { HyperLink } from "../widgets/HyperLink"
import { LabelWithHelp } from "../widgets/LabelWithHelp"

Expand Down
26 changes: 11 additions & 15 deletions components/frontend/src/report/ReportTitle.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import { Label, Segment, Tab } from "../semantic_ui_react_wrappers"
import { entityStatusPropType, reportPropType, settingsPropType } from "../sharedPropTypes"
import { SOURCE_ENTITY_STATUS_DESCRIPTION, SOURCE_ENTITY_STATUS_NAME } from "../source/source_entity_status"
import { getDesiredResponseTime } from "../utils"
import { DeleteButton, PermLinkButton } from "../widgets/Button"
import { ButtonRow } from "../widgets/ButtonRow"
import { DeleteButton } from "../widgets/buttons/DeleteButton"
import { PermLinkButton } from "../widgets/buttons/PermLinkButton"
import { HeaderWithDetails } from "../widgets/HeaderWithDetails"
import { LabelWithHelp } from "../widgets/LabelWithHelp"
import { changelogTabPane, configurationTabPane, tabPane } from "../widgets/TabPane"
Expand Down Expand Up @@ -141,26 +143,22 @@ ReactionTimes.propTypes = {
report: reportPropType,
}

function ButtonRow({ report_uuid, openReportsOverview, url }) {
function ReportTitleButtonRow({ report_uuid, openReportsOverview, url }) {
const deleteButton = (
<DeleteButton itemType="report" onClick={() => delete_report(report_uuid, openReportsOverview)} />
)
return (
<ReadOnlyOrEditable
requiredPermissions={[EDIT_REPORT_PERMISSION]}
editableComponent={
<span
/* The delete button needs to be in a span with an explicit height because otherwise it is
considered to have a height of zero. Maybe because it is floated right? Button rows that have
buttons on the left-hand side don't have this problem.
*/
style={{ height: "36px", width: "100%", display: "block" }}
>
<ButtonRow rightButton={deleteButton}>
<PermLinkButton itemType="report" url={url} />
<DeleteButton itemType="report" onClick={() => delete_report(report_uuid, openReportsOverview)} />
</span>
</ButtonRow>
}
/>
)
}
ButtonRow.propTypes = {
ReportTitleButtonRow.propTypes = {
report_uuid: string,
openReportsOverview: func,
url: string,
Expand Down Expand Up @@ -200,9 +198,7 @@ export function ReportTitle({ report, openReportsOverview, reload, settings }) {
onTabChange={tabChangeHandler(settings.expandedItems, report_uuid)}
panes={panes}
/>
<div style={{ marginTop: "20px" }}>
<ButtonRow report_uuid={report_uuid} openReportsOverview={openReportsOverview} url={reportUrl} />
</div>
<ReportTitleButtonRow report_uuid={report_uuid} openReportsOverview={openReportsOverview} url={reportUrl} />
</HeaderWithDetails>
)
}
Expand Down
3 changes: 2 additions & 1 deletion components/frontend/src/report/ReportsOverview.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import {
} from "../sharedPropTypes"
import { Subjects } from "../subject/Subjects"
import { getReportsTags } from "../utils"
import { AddButton, CopyButton } from "../widgets/Button"
import { AddButton } from "../widgets/buttons/AddButton"
import { CopyButton } from "../widgets/buttons/CopyButton"
import { CommentSegment } from "../widgets/CommentSegment"
import { report_options } from "../widgets/menu_options"
import { ReportsOverviewErrorMessage } from "./ReportErrorMessage"
Expand Down
36 changes: 17 additions & 19 deletions components/frontend/src/source/Source.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import {
stringsPropType,
} from "../sharedPropTypes"
import { getMetricName, getSourceName } from "../utils"
import { DeleteButton, ReorderButtonGroup } from "../widgets/Button"
import { ButtonRow } from "../widgets/ButtonRow"
import { DeleteButton } from "../widgets/buttons/DeleteButton"
import { ReorderButtonGroup } from "../widgets/buttons/ReorderButtonGroup"
import { HyperLink } from "../widgets/HyperLink"
import { changelogTabPane, configurationTabPane } from "../widgets/TabPane"
import { SourceParameters } from "./SourceParameters"
Expand All @@ -30,31 +32,27 @@ function select_sources_parameter_keys(changed_fields, source_uuid) {
: []
}

function ButtonGridRow({ first_source, last_source, reload, source_uuid }) {
function SourceButtonRow({ first_source, last_source, reload, source_uuid }) {
const deleteButton = <DeleteButton itemType="source" onClick={() => delete_source(source_uuid, reload)} />
return (
<ReadOnlyOrEditable
requiredPermissions={[EDIT_REPORT_PERMISSION]}
editableComponent={
<div style={{ marginTop: "20px" }}>
<Grid.Row>
<Grid.Column>
<ReorderButtonGroup
first={first_source}
last={last_source}
moveable="source"
onClick={(direction) => {
set_source_attribute(source_uuid, "position", direction, reload)
}}
/>
<DeleteButton itemType="source" onClick={() => delete_source(source_uuid, reload)} />
</Grid.Column>
</Grid.Row>
</div>
<ButtonRow rightButton={deleteButton}>
<ReorderButtonGroup
first={first_source}
last={last_source}
moveable="source"
onClick={(direction) => {
set_source_attribute(source_uuid, "position", direction, reload)
}}
/>
</ButtonRow>
}
/>
)
}
ButtonGridRow.propTypes = {
SourceButtonRow.propTypes = {
first_source: bool,
last_source: bool,
reload: func,
Expand Down Expand Up @@ -192,7 +190,7 @@ export function Source({
<>
<SourceTypeHeader metricTypeId={metric.type} sourceTypeId={source.type} sourceType={sourceType} />
<Tab panes={panes} />
<ButtonGridRow
<SourceButtonRow
first_source={first_source}
last_source={last_source}
reload={reload}
Expand Down
5 changes: 3 additions & 2 deletions components/frontend/src/source/SourceEntities.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import "./SourceEntities.css"

import HelpIcon from "@mui/icons-material/Help"
import { bool, func, object, string } from "prop-types"
import { useContext, useState } from "react"
import { Message } from "semantic-ui-react"

import { DataModel } from "../context/DataModel"
import { Button, Icon, Popup, Table } from "../semantic_ui_react_wrappers"
import { Button, Popup, Table } from "../semantic_ui_react_wrappers"
import {
alignmentPropType,
childrenPropType,
Expand Down Expand Up @@ -146,7 +147,7 @@ function EntityAttributeHeaderCell({ entityAttribute, ...sortProps }) {
trigger={
<span>
&nbsp;
<Icon role="tooltip" aria-label="help" tabIndex="0" name="help circle" />
<HelpIcon fontSize="inherit" sx={{ verticalAlign: "middle" }} tabIndex="0" />
</span>
}
content={entityAttribute.help}
Expand Down
2 changes: 1 addition & 1 deletion components/frontend/src/source/SourceEntities.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ it("sorts the entities by minutes", async () => {

it("shows help", async () => {
renderSourceEntities()
await userEvent.hover(screen.queryByRole("tooltip", { name: /help/ }))
await userEvent.hover(screen.queryByTestId("HelpIcon"))
await waitFor(() => {
expect(screen.queryByText(/help text/)).not.toBe(null)
})
Expand Down
Loading

0 comments on commit f84d25a

Please sign in to comment.