новая форма
This commit is contained in:
@@ -70,17 +70,19 @@ const ClearanceForm: React.FC<IRequestFormProps> = ({ requestType, context, onCa
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [editId]);
|
}, [editId]);
|
||||||
|
|
||||||
// Выбор увольняемого сотрудника подтягивает его текущую должность — это только
|
// Должность/подразделение больше не вводятся вручную — подтягиваются из
|
||||||
// отправная точка для поля «Должность» (её можно поправить вручную, например
|
// SharePoint User Profile (SPS-JobTitle/SPS-Department) при выборе сотрудника.
|
||||||
// если человек занимал руководящую должность до перевода), а не жёсткая связь.
|
// Если профиль не синхронизирован и поле там пусто — пока просто остаётся
|
||||||
|
// пустым (TODO: фолбэк на справочник api.tnsu.kz, если это окажется частой
|
||||||
|
// проблемой на практике).
|
||||||
const handleEmployeeChange = (login: string): void => {
|
const handleEmployeeChange = (login: string): void => {
|
||||||
setData((prev) => ({ ...prev, Employee: login }));
|
setData((prev) => ({ ...prev, Employee: login, Position: '', Department: '' }));
|
||||||
if (!login) {
|
if (!login) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
approval
|
approval
|
||||||
.getJobTitle(login)
|
.getProfileFields(login)
|
||||||
.then((title) => setData((prev) => ({ ...prev, Position: title || prev.Position })))
|
.then((profile) => setData((prev) => ({ ...prev, Position: profile.jobTitle, Department: profile.department })))
|
||||||
.catch(() => undefined);
|
.catch(() => undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import * as React from 'react';
|
|||||||
import { CollapseSection, FormField, TextInput, MoneyInput, Toggle, PeopleField } from '../../../shared/ui';
|
import { CollapseSection, FormField, TextInput, MoneyInput, Toggle, PeopleField } from '../../../shared/ui';
|
||||||
import { ISectionProps, EMPLOYEE_PLACEHOLDER } from '../model';
|
import { ISectionProps, EMPLOYEE_PLACEHOLDER } from '../model';
|
||||||
|
|
||||||
|
// Должность/подразделение подтягиваются автоматически при выборе сотрудника
|
||||||
|
// (см. ClearanceForm.handleEmployeeChange — SharePoint User Profile) —
|
||||||
|
// свободный ввод здесь намеренно убран, чтобы не расходиться с профилем.
|
||||||
|
const NOOP = (): void => undefined;
|
||||||
|
|
||||||
/** Единственная секция формы «Обходной лист»: увольняемый, должность, подразделение, даты, карты, обучение. */
|
/** Единственная секция формы «Обходной лист»: увольняемый, должность, подразделение, даты, карты, обучение. */
|
||||||
export const RequestSection: React.FC<ISectionProps> = ({ data, set, context, onEmployeeChange }) => (
|
export const RequestSection: React.FC<ISectionProps> = ({ data, set, context, onEmployeeChange }) => (
|
||||||
<CollapseSection title="Обходной лист" icon="people">
|
<CollapseSection title="Обходной лист" icon="people">
|
||||||
@@ -14,10 +19,22 @@ export const RequestSection: React.FC<ISectionProps> = ({ data, set, context, on
|
|||||||
/>
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Должность" htmlFor="Position" required>
|
<FormField label="Должность" htmlFor="Position" required>
|
||||||
<TextInput id="Position" value={data.Position} onChange={(v) => set('Position', v)} />
|
<TextInput
|
||||||
|
id="Position"
|
||||||
|
value={data.Position}
|
||||||
|
onChange={NOOP}
|
||||||
|
readOnly
|
||||||
|
placeholder="Подставится автоматически по выбранному сотруднику"
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Подразделение" htmlFor="Department">
|
<FormField label="Подразделение" htmlFor="Department">
|
||||||
<TextInput id="Department" value={data.Department} onChange={(v) => set('Department', v)} />
|
<TextInput
|
||||||
|
id="Department"
|
||||||
|
value={data.Department}
|
||||||
|
onChange={NOOP}
|
||||||
|
readOnly
|
||||||
|
placeholder="Подставится автоматически по выбранному сотруднику"
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Дата расторжения договора" htmlFor="TerminationDate" required>
|
<FormField label="Дата расторжения договора" htmlFor="TerminationDate" required>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|||||||
@@ -301,7 +301,15 @@ export class ApprovalListService {
|
|||||||
// сотрудника отдаёт именно e-mail (см. pickedLogin), а getPropertiesFor ждёт
|
// сотрудника отдаёт именно e-mail (см. pickedLogin), а getPropertiesFor ждёт
|
||||||
// account name — приводим e-mail к клеймовому виду так же, как ensure().
|
// account name — приводим e-mail к клеймовому виду так же, как ensure().
|
||||||
public async getJobTitle(loginName: string): Promise<string> {
|
public async getJobTitle(loginName: string): Promise<string> {
|
||||||
if (!loginName) return '';
|
return (await this.getProfileFields(loginName)).jobTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Должность + подразделение из профиля SharePoint (SPS-JobTitle/SPS-Department)
|
||||||
|
// ОДНИМ запросом — используется там, где нужны оба поля (напр. предзаполнение
|
||||||
|
// «Обходного листа»), чтобы не дёргать getPropertiesFor дважды подряд.
|
||||||
|
// '' по каждому полю, если недоступно/профиль не синхронизирован.
|
||||||
|
public async getProfileFields(loginName: string): Promise<{ jobTitle: string; department: string }> {
|
||||||
|
if (!loginName) return { jobTitle: '', department: '' };
|
||||||
const account = loginName.indexOf('|') >= 0 ? loginName : `i:0#.f|membership|${loginName}`;
|
const account = loginName.indexOf('|') >= 0 ? loginName : `i:0#.f|membership|${loginName}`;
|
||||||
try {
|
try {
|
||||||
const props = (await getSP().profiles.getPropertiesFor(account)) as {
|
const props = (await getSP().profiles.getPropertiesFor(account)) as {
|
||||||
@@ -313,9 +321,9 @@ export class ApprovalListService {
|
|||||||
: ((raw as { results?: Array<{ Key: string; Value: string }> })?.results ?? []);
|
: ((raw as { results?: Array<{ Key: string; Value: string }> })?.results ?? []);
|
||||||
const map: Record<string, string> = {};
|
const map: Record<string, string> = {};
|
||||||
for (const p of list) map[p.Key] = p.Value;
|
for (const p of list) map[p.Key] = p.Value;
|
||||||
return map['SPS-JobTitle'] || map.Title || '';
|
return { jobTitle: map['SPS-JobTitle'] || map.Title || '', department: map['SPS-Department'] || '' };
|
||||||
} catch {
|
} catch {
|
||||||
return '';
|
return { jobTitle: '', department: '' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user