fix: нейтральный текст при пустом маршруте в заявке 1С
Tests / frontend-test (push) Successful in 1m19s
Tests / frontend-test (push) Successful in 1m19s
This commit is contained in:
@@ -8,8 +8,8 @@ import {
|
||||
Select,
|
||||
PeopleField,
|
||||
PeopleFieldMulti,
|
||||
MultiChoiceField,
|
||||
} from "../../../shared/ui";
|
||||
import { MultiChoiceField } from "./MultiChoiceField";
|
||||
import {
|
||||
ISectionProps,
|
||||
PERSON_PLACEHOLDER,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { CollapseSection, FormField, TextInput, TextArea, Select } from '../../../shared/ui';
|
||||
import { CollapseSection, FormField, TextInput, TextArea, Select, MultiChoiceField } from '../../../shared/ui';
|
||||
import { PositionPicker } from '../../../shared/dictionary';
|
||||
import { LanguagesField } from './LanguagesField';
|
||||
import { MultiChoiceField } from './MultiChoiceField';
|
||||
import {
|
||||
ISectionProps,
|
||||
EMPLOYMENT_TYPE_OPTIONS,
|
||||
|
||||
@@ -226,7 +226,7 @@ const Ticket1CForm: React.FC<IRequestFormProps> = ({
|
||||
data.TaskName.trim() &&
|
||||
data.WorkType &&
|
||||
data.Organization &&
|
||||
data.DB1C &&
|
||||
data.DB1C.length > 0 &&
|
||||
data.Question.trim()
|
||||
);
|
||||
const validate = (): string | undefined => {
|
||||
@@ -412,7 +412,10 @@ const Ticket1CForm: React.FC<IRequestFormProps> = ({
|
||||
<ApprovalMatrix
|
||||
editor={matrixEditor}
|
||||
search={(q) => approval.searchUsers(q)}
|
||||
emptyText="Маршрут для этого вида работ пока не настроен — обратитесь к администратору маршрутов согласования."
|
||||
// Пустой маршрут — штатная ситуация: для части видов работ согласование
|
||||
// не нужно, заявка сразу уходит в Planner. Сбой загрузки маршрута
|
||||
// показывается отдельно (matrix.error) и блокирует отправку.
|
||||
emptyText="Для этого вида работ согласование не требуется — заявка сразу поступит в отдел 1С."
|
||||
/>
|
||||
|
||||
<SubmitActions
|
||||
|
||||
@@ -68,7 +68,7 @@ function buildPlannerNotes(
|
||||
lines.push(`Телефон: ${data.Phone}`);
|
||||
lines.push(`Отдел: ${data.Department}`);
|
||||
lines.push(`Должность: ${data.Position}`);
|
||||
lines.push(`База 1С: ${data.DB1C}`);
|
||||
lines.push(`База 1С: ${data.DB1C.join(', ')}`);
|
||||
lines.push(`Виды работ: ${data.WorkType}`);
|
||||
lines.push('');
|
||||
lines.push('Вопрос:');
|
||||
|
||||
@@ -3,10 +3,24 @@ import { dataListTitle } from '../../shared/listTitles';
|
||||
import { FORM_ID, IFormData, EMPTY_DATA } from './model';
|
||||
|
||||
// TaskName пишется/читается через системную колонку Title (см. provisioning.json/titleColumnName).
|
||||
// DB1C — отдельно, это множественный выбор (см. toStringArray).
|
||||
const SCALAR_FIELDS: (keyof IFormData)[] = [
|
||||
'WorkType', 'Organization', 'DB1C', 'FIO', 'Email', 'Phone', 'Department', 'Position', 'Manager', 'Question',
|
||||
'WorkType', 'Organization', 'FIO', 'Email', 'Phone', 'Department', 'Position', 'Manager', 'Question',
|
||||
];
|
||||
|
||||
/**
|
||||
* Значение колонки множественного выбора → string[]. Строка — заявки, сохранённые,
|
||||
* пока «База 1С» была одиночным выбором (или колонку ещё не переключили);
|
||||
* { results } — ответ в verbose-формате OData.
|
||||
*/
|
||||
function toStringArray(raw: unknown): string[] {
|
||||
if (Array.isArray(raw)) return raw.filter((v): v is string => typeof v === 'string' && v !== '');
|
||||
if (raw && typeof raw === 'object' && Array.isArray((raw as { results?: unknown }).results)) {
|
||||
return toStringArray((raw as { results: unknown[] }).results);
|
||||
}
|
||||
return typeof raw === 'string' && raw !== '' ? [raw] : [];
|
||||
}
|
||||
|
||||
export interface ILoadedRequest {
|
||||
data: IFormData;
|
||||
status: string;
|
||||
@@ -26,7 +40,7 @@ export async function loadTicketRequest(itemId: number, listId?: string): Promis
|
||||
const list = listId ? getSP().web.getList(listId) : getSP().web.lists.getByTitle(dataListTitle(FORM_ID));
|
||||
const item = (await list
|
||||
.items.getById(itemId)
|
||||
.select(...SCALAR_FIELDS, 'Title', 'RequestStatus', 'RequestUniqueCode')()) as Record<string, unknown>;
|
||||
.select(...SCALAR_FIELDS, 'DB1C', 'Title', 'RequestStatus', 'RequestUniqueCode')()) as Record<string, unknown>;
|
||||
|
||||
const data: IFormData = { ...EMPTY_DATA };
|
||||
const writable = data as unknown as Record<string, string>;
|
||||
@@ -36,6 +50,7 @@ export async function loadTicketRequest(itemId: number, listId?: string): Promis
|
||||
writable[key] = value === null || value === undefined ? '' : String(value);
|
||||
});
|
||||
data.TaskName = (item.Title as string) || '';
|
||||
data.DB1C = toStringArray(item.DB1C);
|
||||
|
||||
return {
|
||||
data,
|
||||
|
||||
@@ -16,7 +16,8 @@ export interface IFormData {
|
||||
TaskName: string;
|
||||
WorkType: string;
|
||||
Organization: string;
|
||||
DB1C: string;
|
||||
/** Базы 1С — множественный выбор (колонка MultiChoice), минимум одна. */
|
||||
DB1C: string[];
|
||||
FIO: string;
|
||||
Email: string;
|
||||
Phone: string;
|
||||
@@ -45,7 +46,7 @@ export const EMPTY_DATA: IFormData = {
|
||||
TaskName: '',
|
||||
WorkType: '',
|
||||
Organization: '',
|
||||
DB1C: '',
|
||||
DB1C: [],
|
||||
FIO: '',
|
||||
Email: '',
|
||||
Phone: '',
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"ОСН Беркут",
|
||||
"CT Global"
|
||||
] },
|
||||
{ "internalName": "DB1C", "title": "База 1С", "type": "Choice", "required": true, "choices": [
|
||||
{ "internalName": "DB1C", "title": "База 1С", "type": "Choice", "allowMultiple": true, "required": true, "choices": [
|
||||
"1С: Зарплата и управление персоналом (ЗУП)",
|
||||
"1С: Документооборот (ДО)",
|
||||
"1С: Автотранспортное предприятие (АТП)",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { CollapseSection, FormField, Select, TextArea, TextInput, ISelectOption } from '../../../shared/ui';
|
||||
import { CollapseSection, FormField, MultiChoiceField, Select, TextArea, TextInput, ISelectOption } from '../../../shared/ui';
|
||||
import { ISectionProps } from '../model';
|
||||
import { WORK_TYPE_OPTIONS, ORGANIZATION_OPTIONS, DB1C_OPTIONS, QUESTION_MAX } from '../config';
|
||||
|
||||
@@ -32,13 +32,12 @@ export const RequestSection: React.FC<ISectionProps> = ({ data, set }) => (
|
||||
placeholder="— выберите —"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label="База 1С" htmlFor="DB1C" required>
|
||||
<Select
|
||||
id="DB1C"
|
||||
<FormField label="База 1С" fieldKey="DB1C" required>
|
||||
<MultiChoiceField
|
||||
value={data.DB1C}
|
||||
onChange={(v) => set('DB1C', v)}
|
||||
options={DB1C_SELECT_OPTIONS}
|
||||
placeholder="— выберите —"
|
||||
placeholder="Выберите одну или несколько баз"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField label={`Вопрос (${data.Question.length}/${QUESTION_MAX})`} htmlFor="Question" required full>
|
||||
|
||||
@@ -38,7 +38,10 @@ export interface IColumnDef {
|
||||
lookupShowField?: string;
|
||||
/** Для type === 'User': кого можно выбирать. По умолчанию — как в SharePoint. */
|
||||
userSelectionMode?: 'PeopleOnly' | 'PeopleAndGroups';
|
||||
/** Для type === 'User': разрешить выбор нескольких (создаётся колонка UserMulti). */
|
||||
/**
|
||||
* Разрешить выбор нескольких: для type === 'User' создаётся колонка UserMulti,
|
||||
* для type === 'Choice' — MultiChoice (значение в коде — string[]).
|
||||
*/
|
||||
allowMultiple?: boolean;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import styles from './MultiChoiceField.module.scss';
|
||||
import { useFormReadOnly, ISelectOption } from '../../../shared/ui';
|
||||
import { useFormReadOnly, ISelectOption } from '@tnsu/ui-kit';
|
||||
|
||||
export interface IMultiChoiceFieldProps {
|
||||
value: string[];
|
||||
@@ -36,6 +36,7 @@ export type { ISelectOption, IConfirmOptions } from '@tnsu/ui-kit';
|
||||
export { FormField } from './FormField/FormField';
|
||||
export { FieldChangesProvider } from './FieldChanges/FieldChangesContext';
|
||||
export { FieldChangesBanner } from './FieldChanges/FieldChangesBanner';
|
||||
export { MultiChoiceField } from './MultiChoiceField/MultiChoiceField';
|
||||
export { ItemsTable } from './ItemsTable/ItemsTable';
|
||||
export type { IItemsTableProps } from './ItemsTable/ItemsTable';
|
||||
export type { ILineItem } from './ItemsTable/ILineItem';
|
||||
|
||||
Reference in New Issue
Block a user