fix: внес изменения в заявках рекрутинга от 22.09.2026
Tests / frontend-test (push) Successful in 1m19s
Tests / frontend-test (push) Successful in 1m19s
This commit is contained in:
@@ -1,10 +1,34 @@
|
||||
import * as React from 'react';
|
||||
import { Button, Icon, FormActions } from '@tnsu/ui-kit';
|
||||
import { Button, Icon, FormActions, Alert } from '@tnsu/ui-kit';
|
||||
import { IRequestSubmit } from '../useRequestSubmit';
|
||||
import { isCurrentUserTester } from './testerGroupAccess';
|
||||
|
||||
/**
|
||||
* ВРЕМЕННАЯ ЗАМОРОЗКА (включена 2026-09-21 по просьбе Тимура Городецкого):
|
||||
* приём заявок отключён на ВСЕХ формах портала — и черновик, и отправка на
|
||||
* согласование заблокированы независимо от заполненности полей. Единая точка
|
||||
* отключения — здесь, а не по формам, чтобы снять заморозку можно было одной
|
||||
* правкой (вернуть в false) и не забыть ни одну форму.
|
||||
*
|
||||
* Исключение — участники SharePoint-группы «Тестирование» (см.
|
||||
* testerGroupAccess.ts, добавлено 2026-09-22): для них заморозка не действует,
|
||||
* чтобы можно было проверять формы, пока для всех остальных приём закрыт.
|
||||
*
|
||||
* TODO: снять заморозку (вернуть false), когда будет команда — см. память
|
||||
* request-portal-submission-freeze.
|
||||
*/
|
||||
const SUBMISSION_FROZEN = true;
|
||||
|
||||
export interface ISubmitActionsProps {
|
||||
submit: IRequestSubmit;
|
||||
isValid: boolean;
|
||||
/**
|
||||
* Доп. условие для кнопки «Отправить», когда у отправки более строгие
|
||||
* требования, чем у черновика (например, поля обязательные только при
|
||||
* отправке на согласование). Не задано — отправка гейтится тем же isValid,
|
||||
* что и черновик (поведение по умолчанию для всех остальных форм).
|
||||
*/
|
||||
submitValid?: boolean;
|
||||
/** Заявка в нередактируемом статусе (На согласовании/…): сохранять нельзя. */
|
||||
readOnly: boolean;
|
||||
onCancel: () => void;
|
||||
@@ -21,6 +45,7 @@ export interface ISubmitActionsProps {
|
||||
export const SubmitActions: React.FC<ISubmitActionsProps> = ({
|
||||
submit,
|
||||
isValid,
|
||||
submitValid,
|
||||
readOnly,
|
||||
onCancel,
|
||||
onSaveDraft,
|
||||
@@ -28,21 +53,43 @@ export const SubmitActions: React.FC<ISubmitActionsProps> = ({
|
||||
submitLabel = 'Отправить на согласование',
|
||||
}) => {
|
||||
const { saving, kind } = submit;
|
||||
const locked = saving || readOnly;
|
||||
// false, пока не пришёл ответ о членстве в группе, — безопасный дефолт: не
|
||||
// мигать разблокированными кнопками до подтверждения, что это тестировщик.
|
||||
const [isTester, setIsTester] = React.useState<boolean>(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!SUBMISSION_FROZEN) return;
|
||||
let alive = true;
|
||||
isCurrentUserTester()
|
||||
.then((v) => {
|
||||
if (alive) setIsTester(v);
|
||||
})
|
||||
.catch(() => undefined);
|
||||
return () => {
|
||||
alive = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const frozen = SUBMISSION_FROZEN && !isTester;
|
||||
const locked = saving || readOnly || frozen;
|
||||
const canSubmit = submitValid ?? isValid;
|
||||
|
||||
return (
|
||||
<FormActions>
|
||||
<Button variant="secondary" onClick={onCancel} disabled={saving}>
|
||||
Отмена
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onSaveDraft} disabled={!isValid || locked}>
|
||||
<Icon name="document" size="sm" />
|
||||
Сохранить черновик
|
||||
</Button>
|
||||
<Button variant="accent" onClick={onSubmit} disabled={!isValid || locked}>
|
||||
<Icon name="send" size="sm" />
|
||||
{saving && kind === 'submit' ? 'Отправка…' : submitLabel}
|
||||
</Button>
|
||||
</FormActions>
|
||||
<>
|
||||
{frozen && !readOnly && <Alert variant="warn">Подача заявок временно недоступна.</Alert>}
|
||||
<FormActions>
|
||||
<Button variant="secondary" onClick={onCancel} disabled={saving}>
|
||||
Отмена
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={onSaveDraft} disabled={!isValid || locked}>
|
||||
<Icon name="document" size="sm" />
|
||||
Сохранить черновик
|
||||
</Button>
|
||||
<Button variant="accent" onClick={onSubmit} disabled={!canSubmit || locked}>
|
||||
<Icon name="send" size="sm" />
|
||||
{saving && kind === 'submit' ? 'Отправка…' : submitLabel}
|
||||
</Button>
|
||||
</FormActions>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { getSP } from '../../pnp/pnpjs';
|
||||
|
||||
/**
|
||||
* SharePoint-группа «Тестирование» на сайте данных (/sites/requests) — её
|
||||
* участники исключены из портальной заморозки подачи (см. SUBMISSION_FROZEN в
|
||||
* SubmitActions.tsx): могут сохранять черновик и отправлять заявки, пока для
|
||||
* всех остальных это заблокировано. Id группы, а не Title — Title можно
|
||||
* переименовать в SharePoint без последствий для кода.
|
||||
*/
|
||||
const TESTER_GROUP_ID = 124;
|
||||
|
||||
// Кешируем на весь сеанс — группа тестировщиков не меняется настолько часто,
|
||||
// чтобы перезапрашивать её на каждый ремонт SubmitActions (переключение вкладок
|
||||
// заявок и т.п.). Ошибку не кешируем — временный сбой не должен «залипнуть».
|
||||
let cached: Promise<boolean> | undefined;
|
||||
|
||||
async function fetchIsTester(): Promise<boolean> {
|
||||
const groups = await getSP().web.currentUser.groups();
|
||||
return groups.some((g) => g.Id === TESTER_GROUP_ID);
|
||||
}
|
||||
|
||||
/** Состоит ли ТЕКУЩИЙ пользователь в группе «Тестирование» (см. описание выше). */
|
||||
export function isCurrentUserTester(): Promise<boolean> {
|
||||
if (!cached) {
|
||||
cached = fetchIsTester().catch((e) => {
|
||||
cached = undefined;
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
Reference in New Issue
Block a user