@evergis/react 4.0.136 → 4.0.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/components/Dashboard/componentTypes.d.ts +10 -1
  2. package/dist/components/Dashboard/containers/AttachmentContainer/constants.d.ts +1 -0
  3. package/dist/components/Dashboard/containers/AttachmentContainer/utils/saveBlobAsFile.d.ts +7 -0
  4. package/dist/components/Dashboard/containers/VoteContainer/components/VoteCreateForm.d.ts +3 -0
  5. package/dist/components/Dashboard/containers/VoteContainer/components/VoteResults.d.ts +3 -0
  6. package/dist/components/Dashboard/containers/VoteContainer/components/VoteScreen.d.ts +9 -0
  7. package/dist/components/Dashboard/containers/VoteContainer/components/VoteShare.d.ts +3 -0
  8. package/dist/components/Dashboard/containers/VoteContainer/constants.d.ts +46 -0
  9. package/dist/components/Dashboard/containers/VoteContainer/hooks/useVoteActions.d.ts +26 -0
  10. package/dist/components/Dashboard/containers/VoteContainer/hooks/useVoteContainer.d.ts +25 -0
  11. package/dist/components/Dashboard/containers/VoteContainer/hooks/useVoteData.d.ts +22 -0
  12. package/dist/components/Dashboard/containers/VoteContainer/hooks/useVoteForm.d.ts +17 -0
  13. package/dist/components/Dashboard/containers/VoteContainer/hooks/useVoteUser.d.ts +14 -0
  14. package/dist/components/Dashboard/containers/VoteContainer/index.d.ts +11 -0
  15. package/dist/components/Dashboard/containers/VoteContainer/styled.d.ts +31 -0
  16. package/dist/components/Dashboard/containers/VoteContainer/types.d.ts +88 -0
  17. package/dist/components/Dashboard/containers/VoteContainer/utils.d.ts +38 -0
  18. package/dist/components/Dashboard/containers/index.d.ts +1 -0
  19. package/dist/components/Dashboard/containers/registry.d.ts +1 -0
  20. package/dist/components/Dashboard/hooks/index.d.ts +1 -0
  21. package/dist/components/Dashboard/hooks/useAttachmentDownload.d.ts +9 -0
  22. package/dist/components/Dashboard/types.d.ts +16 -2
  23. package/dist/index.js +1205 -406
  24. package/dist/index.js.map +1 -1
  25. package/dist/react.esm.js +1206 -409
  26. package/dist/react.esm.js.map +1 -1
  27. package/package.json +3 -3
@@ -503,6 +503,14 @@ export interface UploadContainerConfig extends Omit<ConfigContainerChild, "optio
503
503
  export interface UploadContainerProps extends Omit<ContainerProps, "elementConfig"> {
504
504
  elementConfig?: UploadContainerConfig;
505
505
  }
506
+ export type VoteContainerOptions = Pick<ConfigOptions, "categoryDataSource" | "questionDataSource" | "variantDataSource" | "answerDataSource" | "expandable" | "expanded"> & ContainerBoxOptions;
507
+ export interface VoteContainerConfig extends Omit<ConfigContainerChild, "options" | "templateName"> {
508
+ templateName?: ContainerTemplate.Vote;
509
+ options?: VoteContainerOptions;
510
+ }
511
+ export interface VoteContainerProps extends Omit<ContainerProps, "elementConfig"> {
512
+ elementConfig?: VoteContainerConfig;
513
+ }
506
514
  export type DashboardDefaultHeaderOptions = Pick<ConfigOptions, "url">;
507
515
  export interface DashboardDefaultHeaderConfig extends Omit<ConfigContainerHeader, "options" | "templateName"> {
508
516
  templateName?: HeaderTemplate.Default;
@@ -532,7 +540,7 @@ export interface FeatureCardSlideshowHeaderConfig extends Omit<ConfigContainerHe
532
540
  * Поскольку оба поля помечены как опциональные (`?`), значения **без** дискриминатора по-прежнему
533
541
  * приемлемы для любой ветви — это переходная мягкая совместимость с legacy-конфигами.
534
542
  */
535
- export type DashboardChild = ElementButtonConfig | ElementCameraConfig | ElementChartConfig | ElementChipsConfig | ElementControlConfig | ElementIconConfig | ElementImageConfig | ElementLegendConfig | ElementLinkConfig | ElementMarkdownConfig | ElementModalConfig | ElementSlideshowConfig | ElementSvgConfig | ElementTableConfig | ElementTooltipConfig | ElementUploaderConfig | AddFeatureContainerConfig | AttachmentContainerConfig | CameraContainerConfig | ChartContainerConfig | ContainersGroupContainerConfig | DataSourceContainerConfig | DataSourceProgressContainerConfig | DefaultAttributesContainerConfig | DividerContainerElementConfig | EditContainerConfig | EditGroupContainerConfig | EditBooleanContainerConfig | EditStringContainerConfig | EditNumberContainerConfig | EditDropdownContainerConfig | EditChipsContainerConfig | EditCheckboxContainerConfig | EditDateContainerConfig | EditAttachmentContainerConfig | ExportPdfContainerConfig | FiltersContainerConfig | GridRowContainerConfig | IconContainerConfig | ImageContainerConfig | LayersContainerConfig | OneColumnContainerConfig | ProgressContainerConfig | RoundedBackgroundContainerConfig | SlideshowContainerConfig | StructuredDataContainerConfig | TabsContainerConfig | TaskContainerConfig | TitleContainerConfig | TwoColumnContainerConfig | UploadContainerConfig;
543
+ export type DashboardChild = ElementButtonConfig | ElementCameraConfig | ElementChartConfig | ElementChipsConfig | ElementControlConfig | ElementIconConfig | ElementImageConfig | ElementLegendConfig | ElementLinkConfig | ElementMarkdownConfig | ElementModalConfig | ElementSlideshowConfig | ElementSvgConfig | ElementTableConfig | ElementTooltipConfig | ElementUploaderConfig | AddFeatureContainerConfig | AttachmentContainerConfig | CameraContainerConfig | ChartContainerConfig | ContainersGroupContainerConfig | DataSourceContainerConfig | DataSourceProgressContainerConfig | DefaultAttributesContainerConfig | DividerContainerElementConfig | EditContainerConfig | EditGroupContainerConfig | EditBooleanContainerConfig | EditStringContainerConfig | EditNumberContainerConfig | EditDropdownContainerConfig | EditChipsContainerConfig | EditCheckboxContainerConfig | EditDateContainerConfig | EditAttachmentContainerConfig | ExportPdfContainerConfig | FiltersContainerConfig | GridRowContainerConfig | IconContainerConfig | ImageContainerConfig | LayersContainerConfig | OneColumnContainerConfig | ProgressContainerConfig | RoundedBackgroundContainerConfig | SlideshowContainerConfig | StructuredDataContainerConfig | TabsContainerConfig | TaskContainerConfig | TitleContainerConfig | TwoColumnContainerConfig | UploadContainerConfig | VoteContainerConfig;
536
544
  /**
537
545
  * Строгий authoring-тип узла конфига. В отличие от мягкого {@link ConfigContainerChild}
538
546
  * (`id?` — опционален ради legacy-совместимости), здесь `id` **обязателен** и рекурсивно
@@ -615,6 +623,7 @@ export type ContainerTemplateToProps = {
615
623
  [ContainerTemplate.Title]: TitleContainerProps;
616
624
  [ContainerTemplate.TwoColumn]: TwoColumnContainerProps;
617
625
  [ContainerTemplate.Upload]: UploadContainerProps;
626
+ [ContainerTemplate.Vote]: VoteContainerProps;
618
627
  };
619
628
  /**
620
629
  * Карта `type` → `<Name>ElementProps` для регистра элементов из `elements/registry.ts`.
@@ -14,6 +14,7 @@ export declare const SHP_MIME_TYPE = "application/octet-stream";
14
14
  export declare const KML_MIME_TYPE = "application/octet-stream";
15
15
  export declare const ZIP_MIME_TYPE = "application/zip";
16
16
  export declare const PYTHON_MIME_TYPES: string[];
17
+ export declare const DOWNLOAD_ERROR_DURATION = 5000;
17
18
  export declare enum AddAttachmentSource {
18
19
  Pc = "pc",
19
20
  Catalog = "catalog",
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Отдаёт браузеру уже загруженный файл под именем `fileName`.
3
+ *
4
+ * Адрес отзывается не сразу: часть браузеров дочитывает поток уже после клика, и мгновенный
5
+ * `revokeObjectURL` обрывает сохранение.
6
+ */
7
+ export declare const saveBlobAsFile: (blob: Blob, fileName: string) => void;
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+ import { VoteCreateFormProps } from '../types';
3
+ export declare const VoteCreateForm: FC<VoteCreateFormProps>;
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+ import { VoteResultsProps } from '../types';
3
+ export declare const VoteResults: FC<VoteResultsProps>;
@@ -0,0 +1,9 @@
1
+ import { FC } from 'react';
2
+ import { VoteScreenProps } from '../types';
3
+ /**
4
+ * Тело контейнера: выбирает экран по вью-модели голосования.
5
+ *
6
+ * Живёт отдельно от `VoteContainer`, потому что тот отвечает за корень контейнера — размеры,
7
+ * фон и заголовок — и не должен раздуваться ветвлением по состояниям.
8
+ */
9
+ export declare const VoteScreen: FC<VoteScreenProps>;
@@ -0,0 +1,3 @@
1
+ import { FC } from 'react';
2
+ /** Блок «Поделиться в соцсетях» — пока только вёрстка, без рабочих ссылок. */
3
+ export declare const VoteShare: FC;
@@ -0,0 +1,46 @@
1
+ /** Имена полей таблиц голосования. */
2
+ export declare const VOTE_FIELDS: {
3
+ readonly category: {
4
+ readonly id: "id";
5
+ readonly name: "name";
6
+ };
7
+ readonly question: {
8
+ readonly id: "id";
9
+ readonly text: "text";
10
+ readonly categoryId: "category_id";
11
+ readonly userName: "user_name";
12
+ readonly multiSelect: "multi_select";
13
+ };
14
+ readonly variant: {
15
+ readonly id: "id";
16
+ readonly questionId: "question_id";
17
+ readonly text: "text";
18
+ };
19
+ readonly answer: {
20
+ readonly id: "id";
21
+ readonly questionId: "question_id";
22
+ readonly userName: "user_name";
23
+ readonly variantId: "variant_id";
24
+ };
25
+ };
26
+ /** Минимальное число вариантов ответа в голосовании. */
27
+ export declare const MIN_VARIANTS = 2;
28
+ /** Лимит при чтении списков (вариантов/ответов/категорий). */
29
+ export declare const VOTE_FETCH_LIMIT = 10000;
30
+ /** База для перевода доли голосов в проценты. */
31
+ export declare const PERCENT_BASE = 100;
32
+ /** Namespace переводов потребляющего приложения (подписи берутся через `t` с defaultValue). */
33
+ export declare const VOTE_NS = "dashboard";
34
+ /**
35
+ * Имя публичного (анонимного) аккаунта портала.
36
+ *
37
+ * Под ним сервер отдаёт `getUserInfo()` любому неавторизованному посетителю шаренного проекта,
38
+ * поэтому «кто уже голосовал» по нему не считается: первый же голос закрыл бы голосование всем
39
+ * сразу. Такой посетитель для контейнера — неавторизованный, ему доступны только результаты.
40
+ *
41
+ * Признака анонима в API нет (`UserInfoDc` — это `username` + `roles`), поэтому имя приходится
42
+ * знать по конвенции портала: оно же стоит ролью в ACL публичных ресурсов.
43
+ */
44
+ export declare const PUBLIC_USER_NAME = "public_user";
45
+ /** Социальные сети для блока «Поделиться». */
46
+ export declare const VOTE_SOCIALS: string[];
@@ -0,0 +1,26 @@
1
+ import { FeatureDc } from '@evergis/api';
2
+ import { VoteDataSources, VoteFormValues, VoteQuestion, VoteVariant } from '../types';
3
+ interface UseVoteActionsProps {
4
+ dataSources: VoteDataSources;
5
+ attributeName: string;
6
+ featureId?: string;
7
+ featureLayerName?: string;
8
+ username: string;
9
+ question: VoteQuestion | null;
10
+ variants: VoteVariant[];
11
+ answers: FeatureDc[];
12
+ onQuestionIdChange: (questionId: string) => void;
13
+ reload: () => void;
14
+ }
15
+ /**
16
+ * Операции записи контейнера: создание голосования, отправка ответа, редактирование и удаление.
17
+ * Все операции доступны только авторизованному пользователю.
18
+ */
19
+ export declare const useVoteActions: ({ dataSources, attributeName, featureId, featureLayerName, username, question, variants, answers, onQuestionIdChange, reload, }: UseVoteActionsProps) => {
20
+ submitting: boolean;
21
+ createVote: (values: VoteFormValues) => Promise<void>;
22
+ submitAnswer: (variantIds: string[]) => Promise<void>;
23
+ editVote: (values: VoteFormValues) => Promise<void>;
24
+ deleteVote: () => Promise<void>;
25
+ };
26
+ export {};
@@ -0,0 +1,25 @@
1
+ import { VoteContainerConfig } from '../../../componentTypes';
2
+ import { VoteFormValues, VoteScreen } from '../types';
3
+ /**
4
+ * Вью-модель контейнера голосования: определяет текущий экран и собирает данные/действия.
5
+ * Привязка к объекту карты — через `elementConfig.attributeName` (хранит `question_id`).
6
+ */
7
+ export declare const useVoteContainer: (elementConfig?: VoteContainerConfig) => {
8
+ submitting: boolean;
9
+ createVote: (values: VoteFormValues) => Promise<void>;
10
+ submitAnswer: (variantIds: string[]) => Promise<void>;
11
+ editVote: (values: VoteFormValues) => Promise<void>;
12
+ deleteVote: () => Promise<void>;
13
+ configured: boolean;
14
+ screen: VoteScreen;
15
+ categories: import('../types').VoteCategory[];
16
+ question: import('../types').VoteQuestion;
17
+ category: import('../types').VoteCategory;
18
+ results: import('../types').VoteVariantResult[];
19
+ totalVotes: number;
20
+ isOwner: boolean;
21
+ hasAnswers: boolean;
22
+ isEditing: boolean;
23
+ setIsEditing: import('react').Dispatch<import('react').SetStateAction<boolean>>;
24
+ editInitialValues: VoteFormValues;
25
+ };
@@ -0,0 +1,22 @@
1
+ import { FeatureDc } from '@evergis/api';
2
+ import { VoteCategory, VoteDataSources, VoteQuestion, VoteVariant } from '../types';
3
+ interface UseVoteDataProps {
4
+ dataSources: VoteDataSources;
5
+ questionId: string;
6
+ reloadToken: number;
7
+ }
8
+ /**
9
+ * Загружает справочник категорий, а по `questionId` — само голосование, его варианты и ответы.
10
+ * Перечитывается при смене `questionId` или `reloadToken` (после создания/голосования/правки).
11
+ */
12
+ export declare const useVoteData: ({ dataSources, questionId, reloadToken }: UseVoteDataProps) => {
13
+ categories: VoteCategory[];
14
+ question: VoteQuestion;
15
+ variants: VoteVariant[];
16
+ answers: FeatureDc[];
17
+ results: import('../types').VoteVariantResult[];
18
+ totalVotes: number;
19
+ loading: boolean;
20
+ error: boolean;
21
+ };
22
+ export {};
@@ -0,0 +1,17 @@
1
+ import { VoteFormValues, VoteFormVariant } from '../types';
2
+ /** Локальное состояние формы создания/редактирования голосования (категория, вопрос, чипсы-варианты). */
3
+ export declare const useVoteForm: (initialValues?: VoteFormValues) => {
4
+ categoryId: string;
5
+ setCategoryId: import('react').Dispatch<import('react').SetStateAction<string>>;
6
+ text: string;
7
+ setText: import('react').Dispatch<import('react').SetStateAction<string>>;
8
+ multiSelect: boolean;
9
+ setMultiSelect: import('react').Dispatch<import('react').SetStateAction<boolean>>;
10
+ variants: VoteFormVariant[];
11
+ addVariant: () => void;
12
+ removeVariant: (index: number) => void;
13
+ draft: string;
14
+ setDraft: import('react').Dispatch<import('react').SetStateAction<string>>;
15
+ isValid: boolean;
16
+ values: VoteFormValues;
17
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Текущий пользователь для контейнера голосования. Авторизация обязательна — неавторизованный
3
+ * пользователь видит только результаты. Источник — `api.account.getUserInfo()`; ошибка/отсутствие
4
+ * `username` трактуются как «не авторизован».
5
+ *
6
+ * Публичный аккаунт портала (`PUBLIC_USER_NAME` в `username` или в ролях) авторизацией не
7
+ * считается: под ним ходят ВСЕ анонимные посетители шаренного проекта, поэтому и «мой голос»,
8
+ * и владение голосованием опознались бы у них общими на всех.
9
+ */
10
+ export declare const useVoteUser: () => {
11
+ username: string;
12
+ isAuthenticated: boolean;
13
+ loading: boolean;
14
+ };
@@ -0,0 +1,11 @@
1
+ import { FC } from 'react';
2
+ import { VoteContainerProps } from '../../componentTypes';
3
+ /**
4
+ * Контейнер «Голосование»: привязывает опрос к объекту карты через `attributeName`
5
+ * и показывает один из экранов — создание, голосование, после голосования
6
+ * или (для неавторизованных) только результаты.
7
+ *
8
+ * Корнем владеет сам (`useContainerRoot`), поэтому шаблон записан в `ROOT_OWNING_TEMPLATES`:
9
+ * размеры, авторский `style`, фон и заголовок живут на одном узле, без внешней обёртки.
10
+ */
11
+ export declare const VoteContainer: FC<VoteContainerProps>;
@@ -0,0 +1,31 @@
1
+ import { RadioGroup } from '@evergis/uilib-gl';
2
+ export declare const VoteWrapper: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
3
+ export declare const VoteHeading: import('styled-components').StyledComponent<"div", any, {}, never>;
4
+ export declare const VoteQuestionText: import('styled-components').StyledComponent<"div", any, {}, never>;
5
+ export declare const VoteCategoryLabel: import('styled-components').StyledComponent<"div", any, {}, never>;
6
+ export declare const VoteSectionLabel: import('styled-components').StyledComponent<"div", any, {}, never>;
7
+ export declare const VoteChipList: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
8
+ export declare const VoteChip: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
9
+ /**
10
+ * Список вариантов ответа.
11
+ *
12
+ * Обёртка — именно `RadioGroup`: `Radio` из uilib читает его legacy-контекст и без него бросает
13
+ * `Radio must be controlled with RadioGroup context.` — даже когда `checked` и `onChange` заданы
14
+ * на самом контроле. Группа стоит всегда, а не только в режиме одиночного выбора: лишнего она не
15
+ * рисует, зато контекст не может пропасть при смене экрана.
16
+ *
17
+ * Подпись у `Radio` своя, но текст варианта рисует строка — он делит место со счётчиком и
18
+ * прогресс-баром. Поэтому пустой узел подписи и отступ кружка до него снимаются.
19
+ */
20
+ export declare const VoteVariantList: import('styled-components').StyledComponent<typeof RadioGroup, any, {}, never>;
21
+ export declare const VoteVariantRow: import('styled-components').StyledComponent<"div", any, {}, never>;
22
+ export declare const VoteVariantHead: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
23
+ export declare const VoteVariantText: import('styled-components').StyledComponent<"span", any, {}, never>;
24
+ export declare const VoteVariantCount: import('styled-components').StyledComponent<"span", any, {}, never>;
25
+ export declare const VoteAcceptedBadge: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
26
+ export declare const VoteAuthHint: import('styled-components').StyledComponent<"div", any, {}, never>;
27
+ export declare const VoteEditLink: import('styled-components').StyledComponent<"button", any, {}, never>;
28
+ export declare const VoteShareBlock: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
29
+ export declare const VoteShareChips: import('styled-components').StyledComponent<"div", any, import('@evergis/uilib-gl').FlexProps, never>;
30
+ export declare const VoteShareChip: import('styled-components').StyledComponent<"div", any, {}, never>;
31
+ export declare const VoteError: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,88 @@
1
+ import { VoteContainerOptions } from '../../componentTypes';
2
+ /** Экран, который показывает контейнер голосования. */
3
+ export type VoteScreen = "loading" | "create" | "voting" | "voted" | "unauthenticated";
4
+ export interface VoteCategory {
5
+ id: string;
6
+ name: string;
7
+ }
8
+ export interface VoteQuestion {
9
+ id: string;
10
+ text: string;
11
+ categoryId: string;
12
+ userName: string;
13
+ multiSelect: boolean;
14
+ }
15
+ export interface VoteVariant {
16
+ id: string;
17
+ text: string;
18
+ }
19
+ /** Вариант ответа с подсчитанными результатами. `percent` — доля от всех голосов (0..100). */
20
+ export interface VoteVariantResult extends VoteVariant {
21
+ count: number;
22
+ percent: number;
23
+ }
24
+ /** Полезная нагрузка формы создания/редактирования. */
25
+ export interface VoteFormValues {
26
+ categoryId: string;
27
+ text: string;
28
+ multiSelect: boolean;
29
+ variants: VoteFormVariant[];
30
+ }
31
+ /** Вариант в форме: для существующих — с `id` из БД, для новых — `id` пустой. */
32
+ export interface VoteFormVariant {
33
+ id?: string;
34
+ text: string;
35
+ }
36
+ /**
37
+ * Имена слоёв-таблиц голосования, гарантированно непустые.
38
+ *
39
+ * Берутся из `options` контейнера, но отдельно от остальных его опций: размеры и заголовок
40
+ * к данным отношения не имеют, а `Required<VoteContainerOptions>` потребовал бы и их.
41
+ */
42
+ export type VoteDataSources = Required<Pick<VoteContainerOptions, "categoryDataSource" | "questionDataSource" | "variantDataSource" | "answerDataSource">>;
43
+ export interface VoteCreateFormProps {
44
+ categories: VoteCategory[];
45
+ initialValues?: VoteFormValues;
46
+ isEditing: boolean;
47
+ canDelete: boolean;
48
+ submitting: boolean;
49
+ onSubmit: (values: VoteFormValues) => void;
50
+ onDelete?: () => void;
51
+ onCancel?: () => void;
52
+ }
53
+ export interface VoteResultsProps {
54
+ question: VoteQuestion;
55
+ category?: VoteCategory;
56
+ results: VoteVariantResult[];
57
+ totalVotes: number;
58
+ screen: VoteScreen;
59
+ isOwner: boolean;
60
+ hasAnswers: boolean;
61
+ submitting: boolean;
62
+ onSubmit: (variantIds: string[]) => void;
63
+ onEdit?: () => void;
64
+ }
65
+ /**
66
+ * Вью-модель голосования, которую контейнер отдаёт в тело (`VoteScreen`).
67
+ *
68
+ * Это ровно результат `useVoteContainer` без `configured`: признак настроенности разбирает сам
69
+ * контейнер — он решает, рисовать тело или ошибку блока, и до экранов этот флаг не доходит.
70
+ */
71
+ export interface VoteScreenProps {
72
+ screen: VoteScreen;
73
+ categories: VoteCategory[];
74
+ question: VoteQuestion | null;
75
+ category?: VoteCategory;
76
+ results: VoteVariantResult[];
77
+ totalVotes: number;
78
+ isOwner: boolean;
79
+ hasAnswers: boolean;
80
+ isEditing: boolean;
81
+ setIsEditing: (isEditing: boolean) => void;
82
+ editInitialValues?: VoteFormValues;
83
+ submitting: boolean;
84
+ createVote: (values: VoteFormValues) => Promise<void>;
85
+ submitAnswer: (variantIds: string[]) => Promise<void>;
86
+ editVote: (values: VoteFormValues) => Promise<void>;
87
+ deleteVote: () => Promise<void>;
88
+ }
@@ -0,0 +1,38 @@
1
+ import { FeatureDc } from '@evergis/api';
2
+ import { VoteCategory, VoteFormVariant, VoteQuestion, VoteVariant, VoteVariantResult } from './types';
3
+ /** Приводит значение атрибута к строке-идентификатору (id приходят числами/строками). */
4
+ export declare const toId: (value: unknown) => string;
5
+ /**
6
+ * Условие равенства по числовому полю для `conditions` слоя: `field == value`.
7
+ *
8
+ * Двойное равенство — форма, которой написаны условия во всех конфигах проекта; лексер языка
9
+ * условий принимает и одиночное `=`, но расходиться с авторскими конфигами незачем.
10
+ */
11
+ export declare const eqCondition: (field: string, value: string | number) => string;
12
+ export declare const mapCategories: (features: FeatureDc[]) => VoteCategory[];
13
+ export declare const mapQuestion: (feature: FeatureDc) => VoteQuestion;
14
+ export declare const mapVariants: (features: FeatureDc[]) => VoteVariant[];
15
+ /** Список `variant_id` из ответов конкретного пользователя. */
16
+ export declare const getUserVariantIds: (answers: FeatureDc[], userName: string) => string[];
17
+ /** Id записей-ответов конкретного пользователя (для замены ответа при переголосовании). */
18
+ export declare const getUserAnswerIds: (answers: FeatureDc[], userName: string) => string[];
19
+ /**
20
+ * Считает голоса по вариантам. `percent` — доля голосов варианта от общего числа голосов
21
+ * по голосованию.
22
+ */
23
+ export declare const computeResults: (variants: VoteVariant[], answers: FeatureDc[]) => {
24
+ results: VoteVariantResult[];
25
+ totalVotes: number;
26
+ };
27
+ /**
28
+ * Сравнивает варианты из формы с существующими в БД и раскладывает на наборы операций:
29
+ * создать (новые без id), обновить (изменился текст) и удалить (исчезли из формы).
30
+ */
31
+ export declare const diffVariants: (existing: VoteVariant[], next: VoteFormVariant[]) => {
32
+ toCreate: string[];
33
+ toUpdate: Array<{
34
+ id: string;
35
+ text: string;
36
+ }>;
37
+ toDeleteIds: string[];
38
+ };
@@ -23,3 +23,4 @@ export * from './TabsContainer';
23
23
  export * from './TitleContainer';
24
24
  export * from './TwoColumnContainer';
25
25
  export * from './UploadContainer';
26
+ export * from './VoteContainer';
@@ -57,6 +57,7 @@ export declare const getContainerComponents: () => {
57
57
  readonly EditAttachment: FC<import('../componentTypes').EditAttachmentContainerProps>;
58
58
  readonly Attachment: FC<import('../componentTypes').AttachmentContainerProps>;
59
59
  readonly EditGroup: FC<import('../componentTypes').EditGroupContainerProps>;
60
+ readonly Vote: FC<import('../componentTypes').VoteContainerProps>;
60
61
  readonly ContainersGroup: FC<import('../componentTypes').ContainersGroupContainerProps>;
61
62
  readonly GridRow: FC<import('../componentTypes').GridRowContainerProps>;
62
63
  readonly StructuredData: FC<import('../componentTypes').StructuredDataContainerProps>;
@@ -1,3 +1,4 @@
1
+ export * from './useAttachmentDownload';
1
2
  export * from './useAttachmentItems';
2
3
  export * from './useAttachmentPreviewImages';
3
4
  export * from './useAutoCompleteControl';
@@ -0,0 +1,9 @@
1
+ import { Attachment } from '../containers/AttachmentContainer/types';
2
+ /**
3
+ * Скачивание вложения по требованию — файл запрашивается в момент клика, а не заранее.
4
+ *
5
+ * Свой файл лежит за авторизацией (`Authorization: Bearer`), поэтому ссылкой его не отдать:
6
+ * он тянется через api и сохраняется из памяти. Чужой открывается ссылкой — кросс-доменный
7
+ * `download` браузер всё равно игнорирует.
8
+ */
9
+ export declare const useAttachmentDownload: (items: Attachment[]) => ((index: number) => void);
@@ -440,6 +440,19 @@ export interface ConfigEntityRefOptions {
440
440
  parentResourceId?: string;
441
441
  downloadById?: string;
442
442
  }
443
+ /**
444
+ * Опции контейнера «Голосование» (`ContainerTemplate.Vote`).
445
+ *
446
+ * Каждое поле — имя DataSource-таблицы проекта, к которой обращается runtime контейнера:
447
+ * категории, голосования, варианты ответов и ответы пользователей. `question_id` созданного
448
+ * голосования пишется в атрибут объекта карты (см. {@link ConfigContainerChild.attributeName}).
449
+ */
450
+ export interface ConfigVoteOptions {
451
+ categoryDataSource?: string;
452
+ questionDataSource?: string;
453
+ variantDataSource?: string;
454
+ answerDataSource?: string;
455
+ }
443
456
  /** Прочее — поля без явного домена, обычно широкого назначения. */
444
457
  export interface ConfigMiscOptions {
445
458
  innerTemplateName?: ContainerTemplate;
@@ -463,7 +476,7 @@ export interface ConfigMiscOptions {
463
476
  * `Pick<ConfigOptions, ...>`, продолжают работать. Для нового кода предпочтительно делать
464
477
  * `Pick<Config<Domain>Options, ...>` — это лучше документирует, к какому домену относится опция.
465
478
  */
466
- export interface ConfigOptions extends ConfigLayoutOptions, ConfigTypographyOptions, ConfigExpandableOptions, ConfigDataSourceBindingOptions, ConfigChartOptions, ConfigVisualOptions, ConfigTextDisplayOptions, ConfigCollectionOptions, ConfigMapLayerOptions, ConfigEditOptions, ConfigMiscOptions {
479
+ export interface ConfigOptions extends ConfigLayoutOptions, ConfigTypographyOptions, ConfigExpandableOptions, ConfigDataSourceBindingOptions, ConfigChartOptions, ConfigVisualOptions, ConfigTextDisplayOptions, ConfigCollectionOptions, ConfigMapLayerOptions, ConfigEditOptions, ConfigVoteOptions, ConfigMiscOptions {
467
480
  }
468
481
  /**
469
482
  * Настройки атрибута источника данных, заданные в конфиге.
@@ -733,7 +746,8 @@ export declare enum ContainerTemplate {
733
746
  EditAttachment = "EditAttachment",
734
747
  Attachment = "Attachment",
735
748
  Divider = "Divider",
736
- StructuredData = "StructuredData"
749
+ StructuredData = "StructuredData",
750
+ Vote = "Vote"
737
751
  }
738
752
  export declare enum HeaderTemplate {
739
753
  Default = "Default",