ICTU/quality-time

View on GitHub
components/frontend/src/subject/SubjectTitle.js

Summary

Maintainability
D
1 day
Test Coverage
import { bool, func, object, string } from "prop-types"
import { useContext } from "react"
import { Icon, Menu } from "semantic-ui-react"

import { delete_subject, set_subject_attribute } from "../api/subject"
import { activeTabIndex, tabChangeHandler } from "../app_ui_settings"
import { ChangeLog } from "../changelog/ChangeLog"
import { DataModel } from "../context/DataModel"
import { EDIT_REPORT_PERMISSION, ReadOnlyOrEditable } from "../context/Permissions"
import { Header, Tab } from "../semantic_ui_react_wrappers"
import { Share } from "../share/Share"
import { reportPropType, settingsPropType } from "../sharedPropTypes"
import { slugify } from "../utils"
import { DeleteButton, ReorderButtonGroup } from "../widgets/Button"
import { FocusableTab } from "../widgets/FocusableTab"
import { HeaderWithDetails } from "../widgets/HeaderWithDetails"
import { HyperLink } from "../widgets/HyperLink"
import { SubjectParameters } from "./SubjectParameters"

function SubjectHeader({ subjectType }) {
    const url = `https://quality-time.readthedocs.io/en/v${process.env.REACT_APP_VERSION}/reference.html${slugify(subjectType.name)}`
    return (
        <Header>
            <Header.Content>
                {subjectType.name}
                <Header.Subheader>
                    {subjectType.description}{" "}
                    <HyperLink url={url}>
                        Read the Docs <Icon name="external" link />
                    </HyperLink>
                </Header.Subheader>
            </Header.Content>
        </Header>
    )
}
SubjectHeader.propTypes = {
    subjectType: object,
}

function ButtonRow({ subject_uuid, firstSubject, lastSubject, reload }) {
    return (
        <ReadOnlyOrEditable
            requiredPermissions={[EDIT_REPORT_PERMISSION]}
            editableComponent={
                <>
                    <ReorderButtonGroup
                        first={firstSubject}
                        last={lastSubject}
                        moveable="subject"
                        onClick={(direction) => {
                            set_subject_attribute(subject_uuid, "position", direction, reload)
                        }}
                    />
                    <DeleteButton itemType="subject" onClick={() => delete_subject(subject_uuid, reload)} />
                </>
            }
        />
    )
}
ButtonRow.propTypes = {
    subject_uuid: string,
    firstSubject: bool,
    lastSubject: bool,
    reload: func,
}

export function SubjectTitle({
    atReportsOverview,
    report,
    subject,
    subject_uuid,
    firstSubject,
    lastSubject,
    reload,
    settings,
}) {
    const dataModel = useContext(DataModel)
    const tabIndex = activeTabIndex(settings.expandedItems, subject_uuid)
    const subjectType = dataModel.subjects[subject.type] || { name: "Unknown subject type" }
    const subjectName = subject.name || subjectType.name
    const subjectTitle = (atReportsOverview ? report.title + " ❯ " : "") + subjectName
    const subjectUrl = `${window.location}#${subject_uuid}`
    const panes = [
        {
            menuItem: (
                <Menu.Item key="configuration">
                    <Icon name="settings" />
                    <FocusableTab>{"Configuration"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <SubjectParameters
                        subject={subject}
                        subject_uuid={subject_uuid}
                        subject_name={subjectName}
                        reload={reload}
                    />
                </Tab.Pane>
            ),
        },
        {
            menuItem: (
                <Menu.Item key="changelog">
                    <Icon name="history" />
                    <FocusableTab>{"Changelog"}</FocusableTab>
                </Menu.Item>
            ),
            render: () => (
                <Tab.Pane>
                    <ChangeLog subject_uuid={subject_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="Subject permanent link" url={subjectUrl} />
                </Tab.Pane>
            ),
        },
    ]

    return (
        <HeaderWithDetails
            className="sticky"
            header={subjectTitle}
            item_uuid={`${subject_uuid}:${tabIndex}`}
            level="h2"
            settings={settings}
            style={{ marginTop: 50 }}
            subheader={subject.subtitle}
        >
            <SubjectHeader subjectType={subjectType} />
            <Tab
                defaultActiveIndex={tabIndex}
                onTabChange={tabChangeHandler(settings.expandedItems, subject_uuid)}
                panes={panes}
            />
            <div style={{ marginTop: "20px" }}>
                <ButtonRow
                    subject_uuid={subject_uuid}
                    firstSubject={firstSubject}
                    lastSubject={lastSubject}
                    reload={reload}
                />
            </div>
        </HeaderWithDetails>
    )
}
SubjectTitle.propTypes = {
    atReportsOverview: bool,
    firstSubject: bool,
    lastSubject: bool,
    reload: func,
    report: reportPropType,
    settings: settingsPropType,
    subject: object,
    subject_uuid: string,
}