feat: добавил поле организация во все заявки, а также расширил компонет выбора даты для ui-kit
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
@import '../../../../../styles/design-tokens';
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $sp-1;
|
||||
}
|
||||
|
||||
// Read-only «карточка» на организацию — тот же радиус/паддинг, что у TextInput
|
||||
// ($r-sm, 11px/13px из @tnsu/ui-kit), но приглушённый фон/рамка (как в
|
||||
// readonly-field) — сигнал «подставлено автоматически, не редактируется».
|
||||
.line {
|
||||
box-sizing: border-box;
|
||||
padding: 11px 13px;
|
||||
border: 1px solid $gray-200;
|
||||
border-radius: $r-sm;
|
||||
background: $gray-50;
|
||||
font-family: $font-sans;
|
||||
font-size: 13.5px;
|
||||
color: $gray-700;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import * as React from 'react';
|
||||
import styles from './OrganizationField.module.scss';
|
||||
import { FormField } from '@tnsu/ui-kit';
|
||||
|
||||
interface IOrganizationFieldProps {
|
||||
/** `\n`-joined «Компания — должность» на организацию (см. formatEmployeeOrganizations). */
|
||||
value: string;
|
||||
/**
|
||||
* Подпись поля. По умолчанию «Организация» — переопределяют формы, где
|
||||
* секция описывает ДРУГОГО человека (напр. нового сотрудника), чтобы не
|
||||
* читалось как «организация того, о ком заявка».
|
||||
*/
|
||||
label?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Организации сотрудника — read-only, подтягивается автоматически по e-mail
|
||||
* (см. shared/dictionary/employeeOrganizations.service.ts), руками не
|
||||
* редактируется. Сотрудник может состоять сразу в НЕСКОЛЬКИХ организациях —
|
||||
* тогда строк несколько. Пока не резолвилось (сотрудник не выбран/не найден) —
|
||||
* ничего не рендерим, а не пустой блок.
|
||||
*/
|
||||
export const OrganizationField: React.FC<IOrganizationFieldProps> = ({ value, label = 'Организация' }) => {
|
||||
const lines = value ? value.split('\n') : [];
|
||||
if (lines.length === 0) return null;
|
||||
|
||||
return (
|
||||
<FormField label={label} full>
|
||||
<div className={styles.list}>
|
||||
{lines.map((line) => (
|
||||
<div key={line} className={styles.line}>
|
||||
{line}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</FormField>
|
||||
);
|
||||
};
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import { PeoplePicker, PrincipalType } from '@pnp/spfx-controls-react/lib/PeoplePicker';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { buildPickerContext, pickedLogin, IPickedUser } from './pickerContext';
|
||||
import { peoplePickerStyles } from './peoplePickerStyles';
|
||||
import { useFormReadOnly } from '@tnsu/ui-kit';
|
||||
|
||||
interface IPeopleFieldProps {
|
||||
@@ -34,6 +35,7 @@ export const PeopleField: React.FC<IPeopleFieldProps> = ({ context, value, onCha
|
||||
disabled={effectiveReadOnly}
|
||||
placeholder={placeholder}
|
||||
onChange={handleChange}
|
||||
styles={peoplePickerStyles}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import { PeoplePicker, PrincipalType } from '@pnp/spfx-controls-react/lib/PeoplePicker';
|
||||
import { WebPartContext } from '@microsoft/sp-webpart-base';
|
||||
import { buildPickerContext, pickedLogin, IPickedUser } from './pickerContext';
|
||||
import { peoplePickerStyles } from './peoplePickerStyles';
|
||||
import { useFormReadOnly } from '@tnsu/ui-kit';
|
||||
|
||||
interface IPeopleFieldMultiProps {
|
||||
@@ -43,6 +44,7 @@ export const PeopleFieldMulti: React.FC<IPeopleFieldMultiProps> = ({
|
||||
disabled={effectiveReadOnly}
|
||||
placeholder={placeholder}
|
||||
onChange={handleChange}
|
||||
styles={peoplePickerStyles}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { IBasePickerStyles } from '@fluentui/react/lib/Pickers';
|
||||
|
||||
/**
|
||||
* PeoplePicker — сторонний Fluent-контрол (@pnp/spfx-controls-react), а не наш
|
||||
* @tnsu/ui-kit: у него нет своего CSS-модуля и без этих стилей он выглядит
|
||||
* дефолтным Fluent-полем — другой border-radius, другие паддинги, другой цвет
|
||||
* рамки, не в тон соседним полям формы (TextInput и т.п.). Стилизуется через
|
||||
* fluent-проп `styles` (IBasePickerStyles), а не через className/CSS-модуль,
|
||||
* поэтому значения ниже — те же токены, что в styles/_design-tokens.scss
|
||||
* ($gray-300, $gold-500, $r-sm, TextInput.module.scss), но продублированы как
|
||||
* значения: Fluent styles-проп не умеет импортировать SCSS-переменные.
|
||||
*/
|
||||
export const peoplePickerStyles: Partial<IBasePickerStyles> = {
|
||||
text: {
|
||||
boxSizing: 'border-box',
|
||||
padding: '9px 12px',
|
||||
border: '1px solid #D1D5DB', // $gray-300
|
||||
borderRadius: 6, // $r-sm
|
||||
background: '#fff',
|
||||
fontFamily: "'Inter', -apple-system, 'Segoe UI', sans-serif",
|
||||
fontSize: 13.5,
|
||||
transition: '.18s',
|
||||
selectors: {
|
||||
// Фокус — на самом input внутри .text, подсветку показываем на всей рамке.
|
||||
':focus-within': {
|
||||
borderColor: '#D4A01E', // $gold-500
|
||||
boxShadow: '0 0 0 3px rgba(212,160,30,.12)'
|
||||
}
|
||||
}
|
||||
},
|
||||
input: {
|
||||
padding: 0,
|
||||
fontFamily: "'Inter', -apple-system, 'Segoe UI', sans-serif",
|
||||
fontSize: 13.5,
|
||||
color: '#111827', // $gray-900
|
||||
selectors: {
|
||||
'::placeholder': { color: '#9CA3AF' } // $gray-400
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -38,6 +38,7 @@ export { EMPTY_LINE_ITEM } from './ItemsTable/ILineItem';
|
||||
export { parseExcelRows } from './ItemsTable/parseExcelRows';
|
||||
export { PeopleField } from './PeopleField/PeopleField';
|
||||
export { PeopleFieldMulti } from './PeopleField/PeopleFieldMulti';
|
||||
export { OrganizationField } from './OrganizationField/OrganizationField';
|
||||
export { ErrorOverlay } from './ErrorOverlay/ErrorOverlay';
|
||||
export { SubmitActions } from './SubmitActions/SubmitActions';
|
||||
export { InitiatorLine } from './InitiatorLine/InitiatorLine';
|
||||
|
||||
Reference in New Issue
Block a user