Compare commits
2 Commits
88ce1d498e
...
b1060433d0
| Author | SHA1 | Date | |
|---|---|---|---|
| b1060433d0 | |||
| cf039f4d08 |
@@ -207,28 +207,6 @@ export const LANGUAGE_LEVEL_OPTIONS: ISelectOption[] = [
|
||||
{ value: 'Свободный', label: 'Свободный' }
|
||||
];
|
||||
|
||||
/**
|
||||
* Программы (ПО) — ВРЕМЕННЫЙ список, пока нет справочника в API. Используется в
|
||||
* мультивыборе «Необходимые знания в программах». Меняется здесь одним местом.
|
||||
*/
|
||||
export const SOFTWARE_OPTIONS: ISelectOption[] = [
|
||||
{ value: '1С:Предприятие', label: '1С:Предприятие' },
|
||||
{ value: 'MS Word', label: 'MS Word' },
|
||||
{ value: 'MS Excel', label: 'MS Excel' },
|
||||
{ value: 'MS PowerPoint', label: 'MS PowerPoint' },
|
||||
{ value: 'MS Outlook', label: 'MS Outlook' },
|
||||
{ value: 'MS Project', label: 'MS Project' },
|
||||
{ value: 'AutoCAD', label: 'AutoCAD' },
|
||||
{ value: 'Autodesk Forma', label: 'Autodesk Forma' },
|
||||
{ value: 'BIM', label: 'BIM' },
|
||||
{ value: 'Revit', label: 'Revit' },
|
||||
{ value: 'ArchiCAD', label: 'ArchiCAD' },
|
||||
{ value: 'Компас-3D', label: 'Компас-3D' },
|
||||
{ value: 'Primavera', label: 'Primavera' },
|
||||
{ value: 'SAP', label: 'SAP' },
|
||||
{ value: 'Adobe Photoshop', label: 'Adobe Photoshop' }
|
||||
];
|
||||
|
||||
/** Категории «Обеспечение рабочего места» (+ «Другое» через allowOther). */
|
||||
export const WORKPLACE_PROVISION_OPTIONS: ISelectOption[] = [
|
||||
{ value: 'Оргтехника', label: 'Оргтехника' },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { CollapseSection, FormField, TextInput, TextArea, Select, MultiChoiceField } from '../../../shared/ui';
|
||||
import { PositionPicker } from '../../../shared/dictionary';
|
||||
import { PositionPicker, SOFTWARE_OPTIONS } from '../../../shared/dictionary';
|
||||
import { LanguagesField } from './LanguagesField';
|
||||
import {
|
||||
ISectionProps,
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
EDUCATION_OPTIONS,
|
||||
WORK_EXPERIENCE_OPTIONS,
|
||||
RESIDENCE_OPTIONS,
|
||||
SOFTWARE_OPTIONS,
|
||||
OTHER_VALUE
|
||||
} from '../model';
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
**первого** шага согласования и это текущий пользователь; сохраняются кнопкой
|
||||
«Сохранить» и автоматически при «Согласовать» (`updateReviewFields`,
|
||||
`DecisionPanel.onBeforeDecide`). Остальная форма при этом read-only.
|
||||
- **Необходимое ПО** — мультивыбор из общего списка `shared/dictionary/software.ts`
|
||||
(тот же, что в подборе) + своё значение. В SP и в маршрут — по-прежнему ТЕКСТОМ
|
||||
в колонке `Software` через запятую (`softwareList.ts`): условия «Software содержит
|
||||
AutoCAD» и старые заявки со свободным текстом работают как раньше.
|
||||
- **Мебель** — мультивыбор (`FURNITURE_OPTIONS`); при «Другое» появляется поле
|
||||
своего значения. В SP — `WorkplaceFurnitureJson` (JSON-массив) и
|
||||
`WorkplaceFurnitureOther`. Необязательная. Уходит в маршрут как
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { CollapseSection, FormField, TextArea, Toggle } from '../../../shared/ui';
|
||||
import { CollapseSection, FormField, FormModeProvider, MultiChoiceField, TextArea, Toggle } from '../../../shared/ui';
|
||||
import { SOFTWARE_OPTIONS } from '../../../shared/dictionary';
|
||||
import { ISectionProps } from '../model';
|
||||
import { formatSoftware, parseSoftware } from '../softwareList';
|
||||
|
||||
interface IEquipmentSectionProps extends ISectionProps {
|
||||
/** Согласующий-руководитель на этапе согласования может править ПО и доступы,
|
||||
@@ -13,13 +15,25 @@ export const EquipmentSection: React.FC<IEquipmentSectionProps> = ({ data, set,
|
||||
// берёт значение из FormMode (в форме подачи редактируемо, в просмотре — нет).
|
||||
const fieldReadOnly = approverEditable ? false : undefined;
|
||||
|
||||
const software = (
|
||||
<MultiChoiceField
|
||||
value={parseSoftware(data.Software)}
|
||||
onChange={(items) => set('Software', formatSoftware(items))}
|
||||
options={SOFTWARE_OPTIONS}
|
||||
allowOther
|
||||
placeholder="Выберите программу или введите свою"
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<CollapseSection title="Оборудование и доступы" icon="monitor">
|
||||
<FormField label="Нужна ли техника" fieldKey="NeedsEquipment">
|
||||
<Toggle checked={data.NeedsEquipment} onChange={(v) => set('NeedsEquipment', v)} onLabel="Да" />
|
||||
</FormField>
|
||||
<FormField label="Необходимое ПО" htmlFor="Software" full>
|
||||
<TextArea id="Software" value={data.Software} onChange={(v) => set('Software', v)} readOnly={fieldReadOnly} />
|
||||
<FormField label="Необходимое ПО" fieldKey="Software" full>
|
||||
{/* У MultiChoiceField нет своего readOnly — право руководителя даём вложенным
|
||||
провайдером режима, как в FurnitureSection. */}
|
||||
{approverEditable ? <FormModeProvider readOnly={false}>{software}</FormModeProvider> : software}
|
||||
</FormField>
|
||||
<FormField label="Доступы" htmlFor="AccessRights" full>
|
||||
<TextArea id="AccessRights" value={data.AccessRights} onChange={(v) => set('AccessRights', v)} readOnly={fieldReadOnly} />
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { formatSoftware, parseSoftware } from './softwareList';
|
||||
|
||||
describe('parseSoftware', () => {
|
||||
it('разбирает сохранённый список', () => {
|
||||
expect(parseSoftware('AutoCAD, MS Excel, Revit')).toEqual(['AutoCAD', 'MS Excel', 'Revit']);
|
||||
});
|
||||
|
||||
it('пустой текст — пустой список', () => {
|
||||
expect(parseSoftware('')).toEqual([]);
|
||||
expect(parseSoftware(' , \n ')).toEqual([]);
|
||||
});
|
||||
|
||||
it('старый свободный текст с переносами строк — тоже чипами', () => {
|
||||
expect(parseSoftware('AutoCAD\nКорпоративная почта')).toEqual(['AutoCAD', 'Корпоративная почта']);
|
||||
});
|
||||
|
||||
it('убирает повторы', () => {
|
||||
expect(parseSoftware('SAP, SAP, Revit')).toEqual(['SAP', 'Revit']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatSoftware', () => {
|
||||
it('склеивает через запятую — формат, который ждут условия маршрута', () => {
|
||||
expect(formatSoftware(['AutoCAD', 'Revit'])).toBe('AutoCAD, Revit');
|
||||
});
|
||||
|
||||
it('туда и обратно — без потерь', () => {
|
||||
const items = ['1С:Предприятие', 'MS Word', 'Своя программа'];
|
||||
expect(parseSoftware(formatSoftware(items))).toEqual(items);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* «Необходимое ПО» — мультивыбор на экране, но в SP и в маршруте это ТЕКСТ в
|
||||
* колонке Software (условия вида «Software содержит AutoCAD» заведены по нему).
|
||||
* Поэтому модель хранит строку, а раздел переводит её в список и обратно.
|
||||
*/
|
||||
|
||||
const SEPARATOR = ', ';
|
||||
|
||||
/**
|
||||
* Текст колонки → список для мультивыбора. Делим по запятым и переносам строк:
|
||||
* у старых заявок ПО написано свободным текстом — так он тоже ляжет чипами.
|
||||
* Повторы убираем: чип с тем же значением был бы дублем.
|
||||
*/
|
||||
export function parseSoftware(text: string): string[] {
|
||||
const items = text
|
||||
.split(/[,\n]/)
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
return items.filter((s, i) => items.indexOf(s) === i);
|
||||
}
|
||||
|
||||
/** Список из мультивыбора → текст для колонки Software. */
|
||||
export function formatSoftware(items: string[]): string {
|
||||
return items.join(SEPARATOR);
|
||||
}
|
||||
@@ -50,3 +50,4 @@ export {
|
||||
parseOrganizationLine
|
||||
} from './organizationLines';
|
||||
export type { IOrganizationLine } from './organizationLines';
|
||||
export { SOFTWARE_OPTIONS } from './software';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { ISelectOption } from '@tnsu/ui-kit';
|
||||
|
||||
/**
|
||||
* Программы (ПО) — ВРЕМЕННЫЙ список, пока нет справочника в API. Общий для форм:
|
||||
* «Заявка на подбор» (3.8 Необходимые знания в программах) и «Организация
|
||||
* рабочего места» (Необходимое ПО). Пункт добавляется здесь — появляется в обеих.
|
||||
*
|
||||
* Значения уходят в условия маршрута как текст («Software содержит AutoCAD»),
|
||||
* поэтому существующие значения не переименовывать без правки условий в админке.
|
||||
*/
|
||||
export const SOFTWARE_OPTIONS: ISelectOption[] = [
|
||||
{ value: '1С:Предприятие', label: '1С:Предприятие' },
|
||||
{ value: 'MS Word', label: 'MS Word' },
|
||||
{ value: 'MS Excel', label: 'MS Excel' },
|
||||
{ value: 'MS PowerPoint', label: 'MS PowerPoint' },
|
||||
{ value: 'MS Outlook', label: 'MS Outlook' },
|
||||
{ value: 'MS Project', label: 'MS Project' },
|
||||
{ value: 'AutoCAD', label: 'AutoCAD' },
|
||||
{ value: 'Autodesk Forma', label: 'Autodesk Forma' },
|
||||
{ value: 'BIM', label: 'BIM' },
|
||||
{ value: 'Revit', label: 'Revit' },
|
||||
{ value: 'ArchiCAD', label: 'ArchiCAD' },
|
||||
{ value: 'Компас-3D', label: 'Компас-3D' },
|
||||
{ value: 'Primavera', label: 'Primavera' },
|
||||
{ value: 'SAP', label: 'SAP' },
|
||||
{ value: 'Adobe Photoshop', label: 'Adobe Photoshop' }
|
||||
];
|
||||
Reference in New Issue
Block a user