This commit is contained in:
@@ -10,7 +10,7 @@ interface IOrgLetterheadProps {
|
||||
|
||||
/**
|
||||
* Брендированная плашка над FormCard — логотип организации, выбранной в
|
||||
* PrintOrgSelect (видна и на экране, и в печати). Название компании — часть
|
||||
* PrintSplitButton (видна и на экране, и в печати). Название компании — часть
|
||||
* строки до « — должность» (см. formatEmployeeOrganizations). Если логотипа
|
||||
* для этой компании нет (shared/orgLogos.ts) — ничего не рендерим.
|
||||
*/
|
||||
|
||||
@@ -12,11 +12,11 @@ interface IOrganizationFieldProps {
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* Индекс строки, которая остаётся в печатной версии (см. PrintOrgSelect в
|
||||
* тулбаре *View.tsx) — остальные строки помечаются `rp-no-print` и PrintButton
|
||||
* вырезает их из клона перед печатью (shared/ui/PrintButton живёт в
|
||||
* @tnsu/ui-kit). На экране видны ВСЕ строки независимо от выбора — это только
|
||||
* для печати. Не передан → печатаются все организации как раньше.
|
||||
* Индекс строки, которая остаётся в печатной версии (см. shared/ui/PrintSplitButton
|
||||
* в тулбаре *View.tsx) — остальные строки помечаются `rp-no-print` и printRoot
|
||||
* (@tnsu/ui-kit) вырезает их из клона перед печатью. На экране видны ВСЕ строки
|
||||
* независимо от выбора — это только для печати. Не передан → печатаются все
|
||||
* организации как раньше.
|
||||
*/
|
||||
printIndex?: number;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
@import '../../../../../styles/design-tokens';
|
||||
|
||||
.wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $sp-2;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
flex: none;
|
||||
font-family: $font-sans;
|
||||
font-size: $fs-sm;
|
||||
color: $gray-500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import styles from './PrintOrgSelect.module.scss';
|
||||
import { Select, ISelectOption } from '@tnsu/ui-kit';
|
||||
|
||||
interface IPrintOrgSelectProps {
|
||||
/** `\n`-joined «Компания — должность», как в data.Organization. */
|
||||
value: string;
|
||||
selectedIndex: number;
|
||||
onChange: (index: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выбор организации для печати — сотрудник может состоять сразу в нескольких
|
||||
* (см. shared/ui/OrganizationField), а печатный документ должен ссылаться на
|
||||
* одну конкретную. Живёт в тулбаре рядом с PrintButton, помечен `rp-no-print`
|
||||
* самим тулбаром — сам в печать не идёт. Рендерится, только если организаций
|
||||
* больше одной, иначе выбирать не из чего.
|
||||
*/
|
||||
export const PrintOrgSelect: React.FC<IPrintOrgSelectProps> = ({ value, selectedIndex, onChange }) => {
|
||||
const lines = value ? value.split('\n') : [];
|
||||
if (lines.length <= 1) return null;
|
||||
|
||||
const options: ISelectOption[] = lines.map((line, i) => ({ value: String(i), label: line }));
|
||||
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<span className={styles.label}>Организация для печати</span>
|
||||
<Select value={String(selectedIndex)} onChange={(v) => onChange(Number(v))} options={options} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
import * as React from 'react';
|
||||
import { DropdownButton, Icon, PrintButton, printRoot } from '@tnsu/ui-kit';
|
||||
|
||||
interface IPrintSplitButtonProps {
|
||||
/** `\n`-joined «Компания — должность», как в data.Organization. */
|
||||
value: string;
|
||||
selectedIndex: number;
|
||||
onChange: (index: number) => void;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Кнопка «Печать» для форм с несколькими организациями сотрудника: вместо
|
||||
* отдельных select + кнопки — одна кнопка с выпадающим списком организаций,
|
||||
* выбор сразу печатает документ для неё. Если организация одна — рендерит
|
||||
* обычный PrintButton (выбирать не из чего, см. OrganizationField.printIndex).
|
||||
*/
|
||||
export const PrintSplitButton: React.FC<IPrintSplitButtonProps> = ({
|
||||
value,
|
||||
selectedIndex,
|
||||
onChange,
|
||||
label = 'Печать'
|
||||
}) => {
|
||||
const [pendingPrint, setPendingPrint] = React.useState(false);
|
||||
const lines = value ? value.split('\n') : [];
|
||||
|
||||
// onChange(index) обновляет printIndex у родителя (перекрашивает rp-no-print
|
||||
// на строках OrganizationField/OrgLetterhead) в ТОМ ЖЕ цикле обновления, что
|
||||
// и setPendingPrint — печать запускаем эффектом после коммита, чтобы DOM уже
|
||||
// отражал выбранную организацию.
|
||||
React.useEffect(() => {
|
||||
if (!pendingPrint) return;
|
||||
setPendingPrint(false);
|
||||
printRoot();
|
||||
}, [pendingPrint]);
|
||||
|
||||
if (lines.length <= 1) {
|
||||
return <PrintButton label={label} />;
|
||||
}
|
||||
|
||||
const options = lines.map((line, i) => ({ value: String(i), label: line }));
|
||||
|
||||
return (
|
||||
<DropdownButton
|
||||
options={options}
|
||||
value={String(selectedIndex)}
|
||||
onSelect={(v) => {
|
||||
onChange(Number(v));
|
||||
setPendingPrint(true);
|
||||
}}
|
||||
>
|
||||
<Icon name="document" size="sm" />
|
||||
{label}
|
||||
</DropdownButton>
|
||||
);
|
||||
};
|
||||
@@ -39,7 +39,7 @@ export { parseExcelRows } from './ItemsTable/parseExcelRows';
|
||||
export { PeopleField } from './PeopleField/PeopleField';
|
||||
export { PeopleFieldMulti } from './PeopleField/PeopleFieldMulti';
|
||||
export { OrganizationField } from './OrganizationField/OrganizationField';
|
||||
export { PrintOrgSelect } from './PrintOrgSelect/PrintOrgSelect';
|
||||
export { PrintSplitButton } from './PrintSplitButton/PrintSplitButton';
|
||||
export { OrgLetterhead } from './OrgLetterhead/OrgLetterhead';
|
||||
export { LinkField } from './LinkField/LinkField';
|
||||
export { ErrorOverlay } from './ErrorOverlay/ErrorOverlay';
|
||||
|
||||
Reference in New Issue
Block a user