components/src/report-form-controls/report-configuration-tabs.js (161 lines of code) (raw):
import React, {useCallback, useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import Select from '@jetbrains/ring-ui/components/select/select';
import {i18n} from 'hub-dashboard-addons/dist/localization';
import Tab from '@jetbrains/ring-ui/components/tabs/tab';
import Tabs from '@jetbrains/ring-ui/components/tabs/dumb-tabs';
import {usePermissions} from '../permissions/permissions';
const reportToSelectItem = (report, trimmedLabel) => {
if (!report) {
return null;
}
const getOptionDescription = currentReport => {
const description = currentReport.owner &&
(currentReport.owner.name || currentReport.owner.login);
return description && currentReport.own
? `${description} (${i18n('me')})`
: description;
};
const getOptionLabel = currentReport => (
currentReport.id
? currentReport.name || i18n('Unnamed')
: i18n('New report')
);
const trimLimit = 20;
const trimToLimit = label => {
if (!label || label.length < trimLimit) {
return label;
}
return `${(label || '').substring(0, trimLimit).trim()}...`;
};
return {
key: report.id,
label: trimmedLabel
? trimToLimit(getOptionLabel(report))
: getOptionLabel(report),
description: getOptionDescription(report),
model: report
};
};
const makeReportsOptionsList = reports =>
reports.map(report => reportToSelectItem(report));
const getSelectedReport = (selectedReport, reports) => (
selectedReport && selectedReport.id
? selectedReport
: reports[0]
);
const TabId = {
New: 'new',
Existing: 'existing'
};
const ReportConfigurationTabs = ({
report, onChange, children, reportsSource, onCreateReport
}) => {
const [canCreateReports] =
usePermissions('JetBrains.YouTrack.CREATE_REPORT');
const [selectedTab, onChangeSelectedTab] =
useState(getActiveTab(report, canCreateReports));
const [reports, onLoadReports] =
useState([]);
const [reportDraft, onUpdateDraft] = useState(onCreateReport());
const [selectedExistingReport, onSelectExistingReport] =
useState(null);
const onSelectTab = useCallback(tab => {
if (tab !== selectedTab) {
const nextReport = tab === TabId.New
? reportDraft
: (selectedExistingReport || reportDraft);
onChange(nextReport);
onChangeSelectedTab(nextReport.id ? TabId.Existing : TabId.New);
}
}, [selectedTab, onChange, reportDraft, selectedExistingReport]);
const onSelectExistingReportOption = useCallback(selected => {
const selectedReport = selected.model;
if (selectedReport) {
onChange(selectedReport);
onSelectExistingReport(getSelectedReport(selectedReport, reports));
}
}, [onChange, reports]);
useEffect(() => {
let subscribed = true;
const tab = canCreateReports ? getActiveTab(report) : TabId.Existing;
onSelectTab(tab);
const reportId = (report || {}).id;
if (reportId || !selectedExistingReport) {
(async () => {
const loadedReports = await reportsSource();
if (subscribed) {
onLoadReports(loadedReports);
const newSelectedExistingReport =
getSelectedReport(report, loadedReports);
onSelectExistingReport(newSelectedExistingReport);
onChange(tab === TabId.New ? reportDraft : newSelectedExistingReport);
}
})();
} else if (!reportId) {
onUpdateDraft(report || reportDraft);
}
return () => {
subscribed = false;
};
}, [report, canCreateReports, reportsSource, selectedExistingReport]);
useEffect(() => {
onSelectExistingReport(null);
onLoadReports([]);
}, [reportsSource]);
const newReportTabTitle = (
<span>{i18n('Create new report')}</span>
);
const existingReportTabTitle = (
<span>
<span>{i18n('Display existing report')}</span>
<span>
<Select
data={makeReportsOptionsList(reports)}
selected={reportToSelectItem(selectedExistingReport, true)}
onSelect={onSelectExistingReportOption}
filter={true}
label={i18n('Select report')}
type={Select.Type.INLINE}
/>
</span>
</span>
);
return (
<Tabs
selected={selectedTab}
onSelect={onSelectTab}
>
{
canCreateReports &&
<Tab
id={TabId.New}
title={newReportTabTitle}
>
{children}
</Tab>
}
{
(reports && reports.length) &&
<Tab
id={TabId.Existing}
title={existingReportTabTitle}
href="/"
>
{children}
</Tab>
}
</Tabs>
);
function getActiveTab(currentReport) {
return (currentReport && currentReport.id) ? TabId.Existing : TabId.New;
}
};
ReportConfigurationTabs.propTypes = {
report: PropTypes.object,
reportsSource: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onCreateReport: PropTypes.func.isRequired,
children: PropTypes.node
};
export default ReportConfigurationTabs;