ICTU/quality-time

View on GitHub
components/frontend/src/report/ReportTitle.js

Summary

Maintainability
F
1 wk
Test Coverage
import { func, string } from "prop-types"
import { Grid, Icon, Menu } from "semantic-ui-react"

import { delete_report, set_report_attribute } from "../api/report"
import { activeTabIndex, tabChangeHandler } from "../app_ui_settings"
import { ChangeLog } from "../changelog/ChangeLog"
import { EDIT_REPORT_PERMISSION, ReadOnlyOrEditable } from "../context/Permissions"
import { defaultDesiredResponseTimes } from "../defaults"
import { Comment } from "../fields/Comment"
import { IntegerInput } from "../fields/IntegerInput"
import { StringInput } from "../fields/StringInput"
import { NotificationDestinations } from "../notification/NotificationDestinations"
import { Label, Segment, Tab } from "../semantic_ui_react_wrappers"
import { Share } from "../share/Share"
import { reportPropType, settingsPropType } from "../sharedPropTypes"
import { STATUS_DESCRIPTION, STATUS_NAME } from "../utils"
import { DeleteButton } from "../widgets/Button"
import { FocusableTab } from "../widgets/FocusableTab"
import { HeaderWithDetails } from "../widgets/HeaderWithDetails"
import { LabelWithHelp } from "../widgets/LabelWithHelp"
import { setDocumentTitle } from "./document_title"
import { IssueTracker } from "./IssueTracker"

function ReportConfiguration({ reload, report }) {
    return (
        <Grid stackable>
            <Grid.Row columns={2}>
                <Grid.Column>
                    <StringInput
                        id="report-title"
                        label="Report title"
                        requiredPermissions={[EDIT_REPORT_PERMISSION]}
                        set_value={(value) => set_report_attribute(report.report_uuid, "title", value, reload)}
                        value={report.title}
                    />
                </Grid.Column>
                <Grid.Column>
                    <StringInput
                        id="report-subtitle"
                        label="Report subtitle"
                        requiredPermissions={[EDIT_REPORT_PERMISSION]}
                        set_value={(value) => set_report_attribute(report.report_uuid, "subtitle", value, reload)}
                        value={report.subtitle}
                    />
                </Grid.Column>
            </Grid.Row>
            <Grid.Row>
                <Grid.Column>
                    <Comment
                        id="report-comment"
                        set_value={(value) => set_report_attribute(report.report_uuid, "comment", value, reload)}
                        value={report.comment}
                    />
                </Grid.Column>
            </Grid.Row>
        </Grid>
    )
}
ReportConfiguration.propTypes = {
    reload: func,
    report: reportPropType,
}

function ReactionTimes({ reload, report }) {
    const desiredResponseTimes = report.desired_response_times ?? {}
    return (
        <>
            <Segment>
                <Label attached="top" size="large">
                    Desired metric response times
                </Label>
                <Grid stackable>
                    <Grid.Row columns={4}>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-white"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-white"
                                        label={STATUS_NAME.unknown}
                                        help={STATUS_DESCRIPTION.unknown}
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["unknown"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={desiredResponseTimes["unknown"] ?? defaultDesiredResponseTimes["unknown"]}
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-red"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-red"
                                        label={STATUS_NAME.target_not_met}
                                        help={STATUS_DESCRIPTION.target_not_met}
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["target_not_met"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={
                                    desiredResponseTimes["target_not_met"] ??
                                    defaultDesiredResponseTimes["target_not_met"]
                                }
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-yellow"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-yellow"
                                        label={STATUS_NAME.near_target_met}
                                        help={STATUS_DESCRIPTION.near_target_met}
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["near_target_met"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={
                                    desiredResponseTimes["near_target_met"] ??
                                    defaultDesiredResponseTimes["near_target_met"]
                                }
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-grey"
                                label={
                                    <LabelWithHelp
                                        hoverable
                                        labelFor="desired-response-time-grey"
                                        label={STATUS_NAME.debt_target_met}
                                        help={STATUS_DESCRIPTION.debt_target_met}
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["debt_target_met"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={
                                    desiredResponseTimes["debt_target_met"] ??
                                    defaultDesiredResponseTimes["debt_target_met"]
                                }
                            />
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            </Segment>
            <Segment>
                <Label attached="top" size="large">
                    Desired time after which to review measurement entities (violations, warnings, issues, etc.)
                </Label>
                <Grid stackable>
                    <Grid.Row columns={4}>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-confirmed"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-confirmed"
                                        label="Confirmed"
                                        help="Confirmed means that an entity has been reviewed and should be dealt with."
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["confirmed"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={desiredResponseTimes["confirmed"] ?? defaultDesiredResponseTimes["confirmed"]}
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-fixed"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-fixed"
                                        label="Fixed"
                                        help="Fixed means that an entity can be ignored because it has been fixed, or will be fixed shortly, and thus disappear."
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["fixed"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={desiredResponseTimes["fixed"] ?? defaultDesiredResponseTimes["fixed"]}
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-false-positive"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-false-positive"
                                        label="False positive"
                                        help="False positive means an entity has been incorrectly identified as a problem and should be ignored."
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["false_positive"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={
                                    desiredResponseTimes["false_positive"] ??
                                    defaultDesiredResponseTimes["false_positive"]
                                }
                            />
                        </Grid.Column>
                        <Grid.Column>
                            <IntegerInput
                                id="desired-response-time-wont-fix"
                                label={
                                    <LabelWithHelp
                                        labelFor="desired-response-time-wont-fix"
                                        label="Won't fix"
                                        help="Won't fix means that an entity can be ignored because it will not be fixed."
                                    />
                                }
                                requiredPermissions={[EDIT_REPORT_PERMISSION]}
                                set_value={(value) => {
                                    desiredResponseTimes["wont_fix"] = parseInt(value)
                                    set_report_attribute(
                                        report.report_uuid,
                                        "desired_response_times",
                                        desiredResponseTimes,
                                        reload,
                                    )
                                }}
                                unit="days"
                                value={desiredResponseTimes["wont_fix"] ?? defaultDesiredResponseTimes["wont_fix"]}
                            />
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            </Segment>
        </>
    )
}
ReactionTimes.propTypes = {
    reload: func,
    report: reportPropType,
}

function ButtonRow({ 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" }}
                >
                    <DeleteButton itemType="report" onClick={() => delete_report(report_uuid, openReportsOverview)} />
                </span>
            }
        />
    )
}
ButtonRow.propTypes = {
    report_uuid: string,
    openReportsOverview: func,
}

export function ReportTitle({ report, openReportsOverview, reload, settings }) {
    const report_uuid = report.report_uuid
    const tabIndex = activeTabIndex(settings.expandedItems, report_uuid)
    const reportUrl = `${window.location}`
    const panes = [
        {
            menuItem: (
                <Menu.Item key="configuration">
                    <Icon name="settings" />
                    <FocusableTab>{"Configuration"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <ReportConfiguration report={report} reload={reload} />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="reaction_times">
                    <Icon name="time" />
                    <FocusableTab>{"Desired reaction times"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <ReactionTimes report={report} reload={reload} />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="notifications">
                    <Icon name="feed" />
                    <FocusableTab>{"Notifications"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <NotificationDestinations
                        destinations={report.notification_destinations || {}}
                        report_uuid={report_uuid}
                        reload={reload}
                    />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="issue_tracker">
                    <Icon name="tasks" />
                    <FocusableTab>{"Issue tracker"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <IssueTracker report={report} reload={reload} />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="changelog">
                    <Icon name="history" />
                    <FocusableTab>{"Changelog"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <ChangeLog report_uuid={report_uuid} timestamp={report.timestamp} />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="share">
                    <Icon name="share square" />
                    <FocusableTab>{"Share"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <Share title="Report permanent link" url={reportUrl} />
                </Tab.Pane>
            ),
        },
    ]
    setDocumentTitle(report.title)

    return (
        <HeaderWithDetails
            header={report.title}
            item_uuid={`${report.report_uuid}:${tabIndex}`}
            level="h1"
            settings={settings}
            subheader={report.subtitle}
        >
            <Tab
                defaultActiveIndex={tabIndex}
                onTabChange={tabChangeHandler(settings.expandedItems, report_uuid)}
                panes={panes}
            />
            <div style={{ marginTop: "20px" }}>
                <ButtonRow report_uuid={report_uuid} openReportsOverview={openReportsOverview} />
            </div>
        </HeaderWithDetails>
    )
}
ReportTitle.propTypes = {
    openReportsOverview: func,
    reload: func,
    report: reportPropType,
    settings: settingsPropType,
}