@datawheel/bespoke 0.3.22 → 0.4.1

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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useMantineTheme, List, Text, Group, Modal, Button, Input, MantineProvider, Box, Navbar, ScrollArea, Stack, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Flex, packSx, Menu, Card, Center, Space, Badge, Title, TextInput, Code, Divider, SegmentedControl, Select, ActionIcon, Textarea, Paper, Alert, Loader, Container, Grid, Tooltip, MultiSelect, Anchor, Checkbox, MediaQuery, Affix, rem, Popover, Radio, Switch, Drawer, Overlay, Autocomplete, Image, NumberInput, Header, px, Notification, Accordion, Tabs, FileInput, SimpleGrid, Burger, Collapse, HoverCard, CopyButton, Col } from '@mantine/core';
1
+ import { useMantineTheme, List, Text, Group, Modal, Button, Input, MantineProvider, Box, Navbar, ScrollArea, Stack, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Flex, packSx, Menu, Card, Center, Space, Badge, Title, Tabs, TextInput, Code, Loader, Divider, SegmentedControl, Select, ActionIcon, Textarea, Paper, Alert, Container, Grid, Tooltip, MultiSelect, Anchor, Checkbox, MediaQuery, Affix, rem, Popover, Radio, Switch, Drawer, Overlay, NumberInput, Autocomplete, Image, Header, px, Notification, Accordion, FileInput, SimpleGrid, Burger, Collapse, HoverCard, CopyButton, Col } from '@mantine/core';
2
2
  import React, { forwardRef, useState, useCallback, useRef, useEffect, createContext, useContext, useMemo, Fragment as Fragment$1, memo, createElement } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import axios from 'axios';
@@ -21,8 +21,8 @@ import { HYDRATE, createWrapper } from 'next-redux-wrapper';
21
21
  import { Notifications, notifications } from '@mantine/notifications';
22
22
  import { useDispatch, useSelector } from 'react-redux';
23
23
  import Router, { useRouter } from 'next/router';
24
- import { useClickOutside, useDisclosure, useDebouncedValue, useSetState, useHotkeys, useMediaQuery, useFullscreen, getHotkeyHandler } from '@mantine/hooks';
25
- import { IconDice, IconBoxMultiple, IconEyeOff, IconChevronDown, IconBallpen, IconDatabase, IconMathFunction, IconUsers, IconLogout, IconHeading, IconApi, IconPercentage, IconChartBar, IconAlignLeft, IconSelector, IconPhoto, IconUserCircle, IconEdit, IconCircleDashed, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconTrash, IconCircleX, IconFlag, IconPlus, IconFileAnalytics, IconHome, IconSearch, IconX, IconRefresh, IconAlignCenter, IconAlignRight, IconDownload, IconSettingsFilled, IconEye, IconWorldUpload, IconBraces, IconClockHour2, IconAugmentedReality, IconGitMerge, IconGripHorizontal, IconChevronLeft, IconChevronRight, IconPolaroid, IconCircleMinus, IconTable, IconCamera, IconShare, IconCirclePlus, IconLogin, IconWorld, IconLock, IconBinaryTree, IconVariable, IconArrowRightCircle, IconInfoCircle, IconPhotoFilled, IconFileUpload, IconIndentIncrease, IconCodeDots, IconUpload, IconCodePlus, IconLink, IconSparkles, IconClipboardCheck, IconClipboardCopy, IconExternalLink, IconFileTypeCsv, IconFileTypeJs, IconFileTypeXls, IconTemplate, IconCode, IconPalette, IconSettings, IconMinimize, IconMaximize, IconRss, IconGlobe, IconLinkOff } from '@tabler/icons-react';
24
+ import { useClickOutside, useDisclosure, useDebouncedValue, useSetState, useHotkeys, getHotkeyHandler, useMediaQuery, useFullscreen } from '@mantine/hooks';
25
+ import { IconDice, IconBoxMultiple, IconEyeOff, IconChevronDown, IconBallpen, IconDatabase, IconMathFunction, IconUsers, IconLogout, IconHeading, IconApi, IconPercentage, IconChartBar, IconAlignLeft, IconSelector, IconPhoto, IconUserCircle, IconEdit, IconCircleDashed, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconTrash, IconCircleX, IconFlag, IconPlus, IconFileAnalytics, IconHome, IconSearch, IconX, IconRefresh, IconAlignCenter, IconAlignRight, IconDownload, IconSettingsFilled, IconEye, IconWorldUpload, IconBraces, IconClockHour2, IconAugmentedReality, IconGitMerge, IconGripHorizontal, IconChevronLeft, IconChevronRight, IconListCheck, IconPolaroid, IconCircleMinus, IconTable, IconCamera, IconShare, IconQuestionMark, IconCirclePlus, IconLogin, IconWorld, IconLock, IconBinaryTree, IconVariable, IconArrowRightCircle, IconInfoCircle, IconPhotoFilled, IconFileUpload, IconIndentIncrease, IconCodeDots, IconUpload, IconCodePlus, IconLink, IconSparkles, IconClipboardCheck, IconClipboardCopy, IconExternalLink, IconFileTypeCsv, IconFileTypeJs, IconFileTypeXls, IconTemplate, IconCode, IconPalette, IconSettings, IconMinimize, IconMaximize, IconRss, IconGlobe, IconLinkOff } from '@tabler/icons-react';
26
26
  import Link from 'next/link';
27
27
  import parse2, { Element, domToReact, Text as Text$1 } from 'html-react-parser';
28
28
  import { UserProvider, withPageAuthRequired, useUser } from '@auth0/nextjs-auth0/client';
@@ -30,7 +30,7 @@ import { dataConcat, dataLoad } from 'd3plus-viz';
30
30
  import * as d3plus from 'd3plus-react';
31
31
  import dynamic from 'next/dynamic';
32
32
  import { Prism } from '@mantine/prism';
33
- import { DataTable } from 'mantine-datatable';
33
+ import { MantineReactTable } from 'mantine-react-table';
34
34
  import slugifyFn from 'slugify';
35
35
  import JSZip from 'jszip';
36
36
  import { saveAs } from 'file-saver';
@@ -297,8 +297,8 @@ var init_lib = __esm({
297
297
  // api/http/image/imageSave.ts
298
298
  function httpImageSaveFactory(axios9, provider) {
299
299
  return (params) => http(axios9, {
300
- method: "GET",
301
- url: `search/images/${provider}`,
300
+ method: "POST",
301
+ url: `images/save/${provider}`,
302
302
  params: { prompt: params.prompt, provider }
303
303
  });
304
304
  }
@@ -313,8 +313,8 @@ var init_imageSave = __esm({
313
313
  function httpImageSearchFactory(axios9, provider) {
314
314
  return (params) => http(axios9, {
315
315
  method: "GET",
316
- url: `search/images/${provider}`,
317
- params: { prompt: params.prompt, provider }
316
+ url: `images/search/${provider}`,
317
+ params: { prompt: params.prompt, page: params.page, provider }
318
318
  });
319
319
  }
320
320
  var init_imageSearch = __esm({
@@ -384,7 +384,7 @@ function apiFactory(baseURL) {
384
384
  validateVariantSlug: httpGET(axios9, "validate/variant"),
385
385
  readMember: httpGET(axios9, "read/members", transformReadMembers),
386
386
  readMemberImage: httpGET(axios9, {
387
- url: "member/image.png",
387
+ url: "member/image",
388
388
  responseType: "blob"
389
389
  }),
390
390
  searchMember: httpGET(axios9, "search/members"),
@@ -396,6 +396,8 @@ function apiFactory(baseURL) {
396
396
  imageUnsplashSearch: httpImageSearchFactory(axios9, "unsplash"),
397
397
  imageUnsplashSave: httpImageSaveFactory(axios9, "unsplash"),
398
398
  imageUploadSave: httpImageSaveFactory(axios9, "upload"),
399
+ imageAdobeSearch: httpImageSearchFactory(axios9, "adobe"),
400
+ imageAdobeSave: httpImageSaveFactory(axios9, "adobe"),
399
401
  readMetadata: httpGET(axios9, "read/metadata"),
400
402
  regenerateSearch: httpPOST(axios9, "search/regenerate"),
401
403
  urlProxy: httpGET(axios9, "url/proxy"),
@@ -3300,7 +3302,7 @@ function ExploreTile({ profile, profilePrefix, onSelect, reportTile }) {
3300
3302
  id: m.id,
3301
3303
  variant: m.metadata.variant.name,
3302
3304
  image: {
3303
- src: `/api/cms/member/image.png?member=${m.id}&size=thumb`,
3305
+ src: `/api/cms/member/image?member=${m.id}&size=thumb`,
3304
3306
  alt: m.name
3305
3307
  }
3306
3308
  }));
@@ -3647,7 +3649,7 @@ function BespokeSearch({
3647
3649
  id: m.id,
3648
3650
  variant: m.metadata.variant.name,
3649
3651
  image: {
3650
- src: `/api/cms/member/image.png?member=${m.id}&size=thumb`,
3652
+ src: `/api/cms/member/image?member=${m.id}&size=thumb`,
3651
3653
  alt: m.name
3652
3654
  }
3653
3655
  }))
@@ -4290,7 +4292,7 @@ function useOnChangeSelector(blockId, section, selectorIdentifier, asComparison
4290
4292
  const querySelectors = asComparison && comparison.active ? Object.fromEntries(
4291
4293
  Object.entries(query).filter(([key]) => key.match(compareRegex2)).map(([key, value]) => [key.replace("Compare", ""), value])
4292
4294
  ) : Object.fromEntries(
4293
- Object.entries(query).filter(([key]) => key.match(compareRegex2)).map(([key, value]) => [key.replace("Compare", ""), value])
4295
+ Object.entries(query).filter(([key]) => key.match(selectorRegex)).map(([key, value]) => [key.replace("Compare", ""), value])
4294
4296
  );
4295
4297
  const callback = useCallback(
4296
4298
  (value) => {
@@ -4347,7 +4349,7 @@ function useOnChangeSelector(blockId, section, selectorIdentifier, asComparison
4347
4349
  );
4348
4350
  return callback;
4349
4351
  }
4350
- var compareRegex2;
4352
+ var compareRegex2, selectorRegex;
4351
4353
  var init_useOnChangeSelector = __esm({
4352
4354
  "frontend/hooks/useOnChangeSelector.ts"() {
4353
4355
  init_esm_shims();
@@ -4360,6 +4362,7 @@ var init_useOnChangeSelector = __esm({
4360
4362
  init_useReadMemberFn();
4361
4363
  init_ComparisonProvider();
4362
4364
  compareRegex2 = /\w*Compare\b/;
4365
+ selectorRegex = /selector\d+id/;
4363
4366
  }
4364
4367
  });
4365
4368
  function Selector(config) {
@@ -4866,7 +4869,7 @@ function RelatedView(props) {
4866
4869
  id: report.content_id,
4867
4870
  variant: report.variant_name,
4868
4871
  image: {
4869
- src: `/api/cms/member/image.png?member=${report.content_id}&size=thumb`,
4872
+ src: `/api/cms/member/image?member=${report.content_id}&size=thumb`,
4870
4873
  alt: report.name
4871
4874
  }
4872
4875
  }];
@@ -7450,7 +7453,7 @@ var init_section2 = __esm({
7450
7453
  function SectionBackground({ previews }) {
7451
7454
  const images = previews.map((member, ix) => ({
7452
7455
  key: member ? `bg-${member.content_id}` : `bg-${ix}`,
7453
- src: member ? `/api/cms/member/image.png?member=${member.content_id}&size=splash` : ""
7456
+ src: member ? `/api/cms/member/image?member=${member.content_id}&size=splash` : ""
7454
7457
  }));
7455
7458
  return /* @__PURE__ */ jsxs(Fragment, { children: [
7456
7459
  /* @__PURE__ */ jsx(
@@ -7500,71 +7503,45 @@ var init_SectionBackground = __esm({
7500
7503
  init_esm_shims();
7501
7504
  }
7502
7505
  });
7503
- function SortableTable({ data, customIdAccessor = "id" }) {
7504
- const [records, setRecords] = useState();
7505
- const [sortStatus, setSortStatus] = useState();
7506
+ function SortableTable({ data }) {
7506
7507
  const keys = data && Array.isArray(data) && data[0] ? Object.keys(data[0]) : [];
7507
- const idAccessor = keys.includes(customIdAccessor) ? customIdAccessor : defaultIdAccessor;
7508
7508
  const fields = keys.filter((k) => !k.startsWith("_"));
7509
7509
  const columns = fields.map((field) => ({
7510
- accessor: field,
7511
- title: field,
7512
- sortable: true,
7513
- render: (r) => `${r[field]}`
7514
- }));
7515
- const getSortedData = (sortField) => {
7516
- let dataTemp = [...data];
7517
- dataTemp = dataTemp.map((item, ix) => {
7518
- const newItem = { ...item };
7519
- fields.forEach((f) => {
7520
- if (typeof newItem[f] === "object") {
7521
- newItem[f] = JSON.stringify(item[f]);
7522
- }
7523
- });
7524
- if (idAccessor === defaultIdAccessor) {
7525
- newItem._key = `i-${ix}`;
7510
+ accessorKey: field,
7511
+ header: field,
7512
+ enableSorting: true,
7513
+ mantineTableBodyCellProps: {
7514
+ sx: {
7515
+ textWrap: "wrap"
7526
7516
  }
7527
- return newItem;
7528
- });
7529
- if (sortField) {
7530
- dataTemp = dataTemp.sort((a, b) => {
7531
- if (isNaN(a[sortField.columnAccessor])) {
7532
- return a[sortField.columnAccessor].localeCompare(b[sortField.columnAccessor]);
7533
- } else {
7534
- return a[sortField.columnAccessor] > b[sortField.columnAccessor] ? 1 : -1;
7535
- }
7536
- });
7537
7517
  }
7538
- return sortField && sortField.direction === "desc" ? dataTemp.reverse() : dataTemp;
7539
- };
7540
- useEffect(() => {
7541
- if (sortStatus) {
7542
- setRecords(getSortedData(sortStatus));
7543
- }
7544
- }, [sortStatus]);
7545
- useEffect(() => {
7546
- setSortStatus(void 0);
7547
- setRecords(getSortedData(void 0));
7548
- }, [data]);
7518
+ }));
7549
7519
  return /* @__PURE__ */ jsx(
7550
- DataTable,
7520
+ MantineReactTable,
7551
7521
  {
7552
- withBorder: true,
7553
- withColumnBorders: true,
7554
- records,
7555
7522
  columns,
7556
- sortStatus,
7557
- onSortStatusChange: setSortStatus,
7558
- idAccessor,
7559
- minHeight: 100
7523
+ data,
7524
+ enableBottomToolbar: false,
7525
+ enableColumnActions: false,
7526
+ enablePagination: false,
7527
+ enableSorting: true,
7528
+ enableTopToolbar: false,
7529
+ initialState: {
7530
+ density: "xs"
7531
+ },
7532
+ layoutMode: "grid",
7533
+ mantineTableContainerProps: {
7534
+ sx: {
7535
+ minHeight: 100,
7536
+ maxHeight: 350
7537
+ }
7538
+ }
7560
7539
  }
7561
7540
  );
7562
7541
  }
7563
- var defaultIdAccessor;
7564
7542
  var init_SortableTable = __esm({
7565
7543
  "components/SortableTable.tsx"() {
7566
7544
  init_esm_shims();
7567
- defaultIdAccessor = "_key";
7568
7545
  }
7569
7546
  });
7570
7547
 
@@ -9927,7 +9904,7 @@ init_store2();
9927
9904
  function VariantCard({ for: variant, onEdit }) {
9928
9905
  const theme = useMantineTheme();
9929
9906
  const { newConfirmation } = useDialog();
9930
- const secondaryColor = theme.colorScheme === "dark" ? theme.colors.dark[1] : theme.colors.gray[7];
9907
+ theme.colorScheme === "dark" ? theme.colors.dark[1] : theme.colors.gray[7];
9931
9908
  const maybeEdit = useCallback(async () => {
9932
9909
  try {
9933
9910
  await newConfirmation({
@@ -9953,8 +9930,7 @@ function VariantCard({ for: variant, onEdit }) {
9953
9930
  slug
9954
9931
  ] })
9955
9932
  ] }),
9956
- /* @__PURE__ */ jsx(Text, { size: "sm", style: { color: secondaryColor, lineHeight: 2 }, children: "Description of variant will go here" }),
9957
- /* @__PURE__ */ jsx(Space, { w: "xs" }),
9933
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
9958
9934
  /* @__PURE__ */ jsxs(Group, { position: "apart", children: [
9959
9935
  /* @__PURE__ */ jsx(Button, { onClick: () => maybeEdit(), leftIcon: /* @__PURE__ */ jsx(IconPencil, {}), compact: true, children: "Edit" }),
9960
9936
  /* @__PURE__ */ jsx(
@@ -9997,138 +9973,608 @@ function DrawerContentWithScroll({ content, buttons, size }) {
9997
9973
  /* @__PURE__ */ jsx(Group, { mt: "xs", grow: true, style: { height: 45 }, children: buttons })
9998
9974
  ] });
9999
9975
  }
10000
- function VariantEditor({ for: variant, onClose: closeHandler }) {
10001
- const dispatch = useAppDispatch();
10002
- const localeDefault10 = useAppSelector((state) => state.status.localeDefault);
10003
- const locales4 = useAppSelector((state) => state.status.locales);
10004
- const localesItems = locales4.map((locale) => ({ value: locale, label: locale.toUpperCase() }));
10005
- const [sample, setSample] = useState();
10006
- const [selectedLocale, setSelectedLocale] = useState(localeDefault10);
10007
- const [variantConfig, setVariantConfig] = useState(variant);
10008
- const [loading, setLoading] = useState(false);
10009
- const [loadingFetch, setLoadingFetch] = useState(false);
10010
- const [loadingValidSlug, setLoadingValidSlug] = useState(false);
10011
- const [validSlug, setValidSlug] = useState({ valid: false, suggestion: "" });
10012
- const [payload, setPayload] = useState();
10013
- const [accessors, setAccessors] = useState([]);
10014
- const getMembers = (path) => {
10015
- setLoadingFetch(true);
10016
- dispatch(actions_exports.urlProxy(path)).then((resp) => {
10017
- setPayload(resp);
10018
- setLoadingFetch(false);
10019
- }).catch((e) => {
10020
- console.error(e);
10021
- setLoadingFetch(false);
10022
- });
10023
- };
10024
- const setConfigFromSample = (sample2, accessor = "") => {
10025
- if (sample2) {
10026
- const sampleKeys = Object.keys(sample2);
10027
- const guessId = sampleKeys.find((d) => d.toLowerCase().includes("id")) || sampleKeys[0];
10028
- const guessName = sampleKeys.find((d) => !d.toLowerCase().includes("id")) || sampleKeys[0];
10029
- setVariantConfig({
10030
- ...variantConfig,
10031
- config: {
10032
- ...variantConfig.config,
10033
- [selectedLocale]: {
10034
- ...variantConfig.config[selectedLocale],
10035
- idKey: variantConfig.config[selectedLocale].idKey || guessId,
10036
- labelKey: variantConfig.config[selectedLocale].labelKey || guessName,
10037
- accessor
10038
- }
10039
- }
10040
- });
10041
- }
10042
- setSample(sample2);
9976
+
9977
+ // api/endpoints/member.ts
9978
+ init_esm_shims();
9979
+ init_getLocales();
9980
+ init_stripHTML();
9981
+ init_lib3();
9982
+
9983
+ // api/endpoints/lib.ts
9984
+ init_esm_shims();
9985
+ init_lib3();
9986
+ function parseFiniteNumber(value) {
9987
+ const num = Number.parseInt(`${value || ""}`, 10);
9988
+ if (Number.isNaN(num) || !Number.isFinite(num)) {
9989
+ throw new BackendError(400, `Invalid numeric parameter: ${value}`);
9990
+ }
9991
+ return num;
9992
+ }
9993
+ function normalizeList(value) {
9994
+ if (value == null || value === "") {
9995
+ return [];
9996
+ }
9997
+ if (Array.isArray(value)) {
9998
+ return value;
9999
+ }
10000
+ return value.toString().split(",");
10001
+ }
10002
+
10003
+ // api/endpoints/member.ts
10004
+ var { localeDefault: localeDefault9 } = getLocales_default();
10005
+ function parseReadMemberParams(query) {
10006
+ const locale = normalizeList(query.locale)[0] || localeDefault9 || "en";
10007
+ const all = locale === "all" || yn4(query.all);
10008
+ const mode = normalizeList(query.mode)[0];
10009
+ const outputParam = normalizeList(query.output)[0] || "full";
10010
+ const output = outputParam === "lite" ? "lite" : "full";
10011
+ const relatedLimit = parseInt(normalizeList(query.related)[0], 10) || 5;
10012
+ let variant = normalizeList(query.variant).map(parseFiniteNumber);
10013
+ if (variant.length === 0) {
10014
+ variant = normalizeList(query["variant[]"]).map(parseFiniteNumber);
10015
+ }
10016
+ if (mode === "ids") {
10017
+ return {
10018
+ all,
10019
+ mode,
10020
+ variant,
10021
+ output,
10022
+ locale: all ? localeDefault9 : stripHTML(locale),
10023
+ ids: normalizeList(query.ids || query["ids[]"])
10024
+ };
10025
+ }
10026
+ if (mode === "content_ids") {
10027
+ return {
10028
+ all,
10029
+ mode,
10030
+ variant,
10031
+ output,
10032
+ locale: all ? localeDefault9 : stripHTML(locale),
10033
+ content_ids: normalizeList(query.content_ids || query["content_ids[]"]).map(parseFiniteNumber)
10034
+ };
10035
+ }
10036
+ if (mode === "slugs") {
10037
+ return {
10038
+ all,
10039
+ mode,
10040
+ variant,
10041
+ output,
10042
+ locale: all ? localeDefault9 : stripHTML(locale),
10043
+ slugs: normalizeList(query.slugs || query["slugs[]"]).map((token) => {
10044
+ const [variantSlug, memberSlug] = token.split("/");
10045
+ return { variantSlug, memberSlug };
10046
+ })
10047
+ };
10048
+ }
10049
+ if (mode === "related") {
10050
+ return {
10051
+ all,
10052
+ mode,
10053
+ locale: all ? localeDefault9 : stripHTML(locale),
10054
+ related: relatedLimit,
10055
+ current_ids: normalizeList(query.current_ids || query["current_ids[]"]).map(parseFiniteNumber),
10056
+ report_ids: normalizeList(query.report_ids || query["report_ids[]"]).map(parseFiniteNumber),
10057
+ dimension_ids: normalizeList(query.dimension_ids || query["dimension_ids[]"]).map(parseFiniteNumber),
10058
+ variant_ids: normalizeList(query.variant_ids || query["variant_ids[]"]).map(parseFiniteNumber),
10059
+ output
10060
+ };
10061
+ }
10062
+ throw new BackendError(400, `Invalid mode: '${mode}'`);
10063
+ }
10064
+ function parseSearchMemberParams(query) {
10065
+ const locale = normalizeList(query.locale)[0] || localeDefault9 || "en";
10066
+ const localeIsAll = locale === "all";
10067
+ const format2 = normalizeList(query.format)[0];
10068
+ const formatIsNested = format2 ? format2 === "nested" : localeIsAll;
10069
+ let variant = normalizeList(query.variant).map(parseFiniteNumber);
10070
+ if (variant.length === 0) {
10071
+ variant = normalizeList(query["variant[]"]).map(parseFiniteNumber);
10072
+ }
10073
+ let dimension = normalizeList(query.dimension).map(parseFiniteNumber);
10074
+ if (dimension.length === 0) {
10075
+ dimension = normalizeList(query["dimension[]"]).map(parseFiniteNumber);
10076
+ }
10077
+ let report = normalizeList(query.report).map(parseFiniteNumber);
10078
+ if (report.length === 0) {
10079
+ report = normalizeList(query["report[]"]).map(parseFiniteNumber);
10080
+ }
10081
+ return {
10082
+ query: normalizeList(query.query || query.q)[0] || "",
10083
+ locale: localeIsAll ? localeDefault9 : locale,
10084
+ limit: normalizeList(query.limit).map(parseFiniteNumber)[0] ?? 5,
10085
+ format: formatIsNested ? "nested" : "plain",
10086
+ includes: yn4(query.includes, { default: true }),
10087
+ visible: yn4(query.visible, { default: true }),
10088
+ noImage: yn4(query.noImage, { default: false }),
10089
+ variant,
10090
+ dimension,
10091
+ report,
10092
+ all: localeIsAll,
10093
+ sort: normalizeList(query.sort)[0],
10094
+ direction: normalizeList(query.direction)[0]
10043
10095
  };
10096
+ }
10097
+
10098
+ // components/metadata/MembersTable.tsx
10099
+ init_esm_shims();
10100
+
10101
+ // views/ImagePreview.tsx
10102
+ init_esm_shims();
10103
+ function ImagePreview3({
10104
+ member,
10105
+ height = "auto",
10106
+ width = "100%",
10107
+ size = "thumb",
10108
+ forceRefreshTimestamp = false
10109
+ }) {
10110
+ let extraParam = "";
10111
+ if (forceRefreshTimestamp) {
10112
+ extraParam = `&t=${( new Date()).getTime()}`;
10113
+ }
10114
+ const imageUrl = member && member.image_id ? `/api/cms/member/image?member=${member.content_id}&size=${size}${extraParam}` : "https://placehold.jp/cccccc/ffffff/900x600.png?text=None";
10115
+ return /* @__PURE__ */ jsx(Image, { alt: `Image for ${member.id}`, height, width, radius: "md", src: imageUrl });
10116
+ }
10117
+ var ImagePreview_default = ImagePreview3;
10118
+
10119
+ // components/metadata/MembersTable.tsx
10120
+ init_store2();
10121
+ function MembersTable({ members, onClickEdit, onSort, colsToRender = [], dataTableProps = {} }) {
10122
+ const [sortStatus, setSortStatus] = useState([]);
10123
+ const [records, setRecords] = useState([]);
10124
+ const { state, ...tableProps } = dataTableProps;
10044
10125
  useEffect(() => {
10045
- if (!variantConfig.config[selectedLocale]) {
10046
- setVariantConfig({
10047
- ...variantConfig,
10048
- config: {
10049
- ...variantConfig.config,
10050
- [selectedLocale]: { attributes: [] }
10051
- }
10052
- });
10053
- }
10054
- if (variantConfig.config[selectedLocale] && variantConfig.config[selectedLocale].path) {
10055
- getMembers(variantConfig.config[selectedLocale].path);
10126
+ if (typeof onSort !== "undefined" && sortStatus && sortStatus.length) {
10127
+ onSort(sortStatus);
10056
10128
  }
10057
- }, []);
10129
+ }, [sortStatus]);
10058
10130
  useEffect(() => {
10059
- setPayload(void 0);
10060
- let attributesList = [];
10061
- if (selectedLocale !== localeDefault10) {
10062
- const defaultAttributes = variantConfig.config[localeDefault10] ? [...variantConfig.config[localeDefault10].attributes].map((item) => {
10063
- const newItem = { ...item };
10064
- newItem.value = "";
10065
- return newItem;
10066
- }) : [];
10067
- if (variantConfig.config[selectedLocale] && variantConfig.config[selectedLocale].attributes) {
10068
- attributesList = defaultAttributes.map((da) => {
10069
- const item = variantConfig.config[selectedLocale].attributes.find((sa) => da.name === sa.name);
10070
- if (item) {
10071
- da.value = item.value;
10072
- }
10073
- return da;
10074
- });
10075
- } else {
10076
- attributesList = defaultAttributes;
10077
- }
10078
- setVariantConfig({
10079
- ...variantConfig,
10080
- config: {
10081
- ...variantConfig.config,
10082
- [selectedLocale]: {
10083
- ...variantConfig.config[selectedLocale],
10084
- attributes: attributesList
10131
+ setRecords(members);
10132
+ }, [members]);
10133
+ useEffect(() => {
10134
+ setRecords(members);
10135
+ }, []);
10136
+ const localeDefault10 = useAppSelector((state2) => state2.status.localeDefault);
10137
+ const none = /* @__PURE__ */ jsx(Badge, { color: "gray", children: "None" });
10138
+ const cols = [
10139
+ {
10140
+ header: "",
10141
+ accessorKey: "visible",
10142
+ enableResizing: false,
10143
+ enableSorting: false,
10144
+ size: 10,
10145
+ Cell: ({ row }) => /* @__PURE__ */ jsx(Fragment, { children: !row.original.visible ? /* @__PURE__ */ jsx(Tooltip, { label: "Visible: false", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconEyeOff, { size: 20 }) }) }) : /* @__PURE__ */ jsx("span", {}) })
10146
+ },
10147
+ {
10148
+ header: "ID",
10149
+ accessorKey: "id",
10150
+ enableSorting: typeof onSort !== "undefined" ? true : false,
10151
+ mantineTableHeadCellProps: {
10152
+ align: "right",
10153
+ sx: {
10154
+ "& .mantine-TableHeadCell-Content-Labels": {
10155
+ flexDirection: "row"
10085
10156
  }
10086
10157
  }
10087
- });
10088
- }
10089
- if (variantConfig.config[selectedLocale] && variantConfig.config[selectedLocale].path) {
10090
- getMembers(variantConfig.config[selectedLocale].path);
10091
- }
10092
- }, [selectedLocale]);
10093
- useEffect(() => {
10094
- if (payload) {
10095
- const keys2 = arrayFinder(payload);
10096
- setAccessors(keys2);
10097
- if (variantConfig.config[selectedLocale].accessor && payload[variantConfig.config[selectedLocale].accessor]) {
10098
- setConfigFromSample(
10099
- payload[variantConfig.config[selectedLocale].accessor][0],
10100
- variantConfig.config[selectedLocale].accessor
10101
- );
10102
- } else if (keys2.length === 0) {
10103
- if (payload && payload[0])
10104
- setConfigFromSample(payload[0]);
10105
- }
10106
- }
10107
- }, [payload]);
10108
- useEffect(() => {
10109
- if (variantConfig.slug) {
10110
- setLoadingValidSlug(true);
10111
- dispatch(actions_exports.variantValidateSlug(variantConfig.dimension_id, variantConfig.slug)).then(setValidSlug).then(() => {
10112
- setLoadingValidSlug(false);
10113
- }, (err) => {
10114
- console.error(err);
10115
- });
10116
- }
10117
- }, [variantConfig.slug]);
10118
- const onChangeAccessor = (accessor) => {
10119
- const dataArray = keyDiver(payload, accessor);
10120
- if (dataArray[0]) {
10121
- setConfigFromSample(dataArray[0], accessor);
10122
- }
10123
- };
10158
+ },
10159
+ mantineTableBodyCellProps: {
10160
+ align: "right"
10161
+ },
10162
+ size: 100
10163
+ },
10164
+ {
10165
+ header: "Report",
10166
+ accessorKey: "report.name",
10167
+ enableSorting: false,
10168
+ size: 100
10169
+ },
10170
+ {
10171
+ header: "Dimension",
10172
+ accessorKey: "dimension.name",
10173
+ enableSorting: false,
10174
+ size: 100
10175
+ },
10176
+ {
10177
+ header: "Variant",
10178
+ accessorKey: "variant.name",
10179
+ enableSorting: false,
10180
+ size: 100
10181
+ },
10182
+ {
10183
+ header: "Relevance",
10184
+ accessorKey: "zvalue",
10185
+ enableSorting: typeof onSort !== "undefined" ? true : false,
10186
+ size: 100
10187
+ },
10188
+ {
10189
+ header: "Slug",
10190
+ accessorKey: "slug",
10191
+ Cell: ({ row }) => /* @__PURE__ */ jsxs("span", { children: [
10192
+ "/",
10193
+ row.original.variant.slug,
10194
+ "/",
10195
+ row.original.slug
10196
+ ] }),
10197
+ enableSorting: false
10198
+ },
10199
+ {
10200
+ header: `Name ${localeDefault10.toUpperCase()}`,
10201
+ accessorKey: "name",
10202
+ enableSorting: typeof onSort !== "undefined" ? true : false,
10203
+ Cell: ({ row }) => {
10204
+ const defaultLocalized = row.original.contentByLocale.find((item) => item.locale === localeDefault10);
10205
+ const othersLocalized = row.original.contentByLocale.filter((item) => item.locale !== localeDefault10);
10206
+ const nameTooltipContent = othersLocalized.reduce((acc, item) => {
10207
+ const extraName = `${item.locale.toUpperCase()}: ${item.name}`;
10208
+ const newLine2 = acc !== "" ? "\n" : "";
10209
+ return `${acc}${newLine2}${extraName}`;
10210
+ }, "");
10211
+ return /* @__PURE__ */ jsxs(Group, { children: [
10212
+ /* @__PURE__ */ jsx("span", { children: defaultLocalized?.name || none }),
10213
+ othersLocalized.length > 0 && /* @__PURE__ */ jsx(Tooltip, { label: nameTooltipContent, children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", color: "pink", radius: "xl", children: [
10214
+ "+",
10215
+ othersLocalized.length
10216
+ ] }) })
10217
+ ] });
10218
+ }
10219
+ },
10220
+ {
10221
+ header: `Keywords ${localeDefault10.toUpperCase()}`,
10222
+ accessorKey: "keywords",
10223
+ Cell: ({ row }) => {
10224
+ const defaultLocalized = row.original.contentByLocale.find((item) => item.locale === localeDefault10);
10225
+ const othersLocalized = row.original.contentByLocale.filter((item) => item.locale !== localeDefault10);
10226
+ const keywords = (defaultLocalized.keywords ? defaultLocalized.keywords : []).map((k) => /* @__PURE__ */ jsx(Badge, { children: k }, k));
10227
+ const keywordsTooltipContent = othersLocalized.reduce((acc, item) => {
10228
+ const otherKeywords = item.keywords || [];
10229
+ const extraKeywords = `${item.locale.toUpperCase()}: ${otherKeywords.length > 0 ? otherKeywords.join(",") : "None"}`;
10230
+ const newLine2 = acc !== "" ? "\n" : "";
10231
+ return `${acc}${newLine2}${extraKeywords}`;
10232
+ }, "");
10233
+ return /* @__PURE__ */ jsxs(Group, { children: [
10234
+ /* @__PURE__ */ jsx("span", { children: keywords.length > 0 ? keywords : none }),
10235
+ othersLocalized.length > 0 && /* @__PURE__ */ jsx(Tooltip, { label: keywordsTooltipContent, children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", color: "pink", radius: "xl", children: [
10236
+ "+",
10237
+ othersLocalized.length
10238
+ ] }) })
10239
+ ] });
10240
+ },
10241
+ enableSorting: false,
10242
+ size: 100
10243
+ },
10244
+ {
10245
+ header: "Image",
10246
+ accessorKey: "image",
10247
+ Cell: ({ row }) => /* @__PURE__ */ jsx(ImagePreview_default, { member: row.original, height: "50px", forceRefreshTimestamp: true }),
10248
+ enableSorting: false,
10249
+ size: 80
10250
+ },
10251
+ {
10252
+ header: "",
10253
+ accessorKey: "actions",
10254
+ Cell: ({ row }) => /* @__PURE__ */ jsx(
10255
+ ActionIcon,
10256
+ {
10257
+ onClick: () => onClickEdit ? onClickEdit(row.original) : false,
10258
+ children: /* @__PURE__ */ jsx(IconPencil, { size: 20 })
10259
+ },
10260
+ "edit"
10261
+ ),
10262
+ enableResizing: false,
10263
+ enableSorting: false,
10264
+ size: 50,
10265
+ mantineTableHeadCellProps: {
10266
+ align: "center"
10267
+ },
10268
+ mantineTableBodyCellProps: {
10269
+ align: "center"
10270
+ }
10271
+ }
10272
+ ];
10273
+ return /* @__PURE__ */ jsx(
10274
+ MantineReactTable,
10275
+ {
10276
+ columns: cols.filter((col) => colsToRender && colsToRender.length === 0 || colsToRender.includes(col.accessorKey)),
10277
+ data: records,
10278
+ enableBottomToolbar: false,
10279
+ enableColumnActions: false,
10280
+ enableColumnResizing: true,
10281
+ enablePagination: false,
10282
+ enableStickyHeader: true,
10283
+ enableTopToolbar: false,
10284
+ initialState: {
10285
+ density: "xs"
10286
+ },
10287
+ layoutMode: "grid",
10288
+ mantineTableContainerProps: {
10289
+ sx: {
10290
+ minHeight: 150,
10291
+ maxHeight: "95vh"
10292
+ }
10293
+ },
10294
+ mantineTableProps: {
10295
+ striped: true
10296
+ },
10297
+ manualSorting: true,
10298
+ onSortingChange: setSortStatus,
10299
+ state: {
10300
+ sorting: sortStatus,
10301
+ ...state
10302
+ },
10303
+ ...tableProps
10304
+ }
10305
+ );
10306
+ }
10307
+
10308
+ // libs/settings/variant.tsx
10309
+ init_esm_shims();
10310
+ var getVariantSettingsDefaults = (settings) => ({
10311
+ overrideNames: settings && typeof settings.overrideNames !== "undefined" ? settings.overrideNames : false,
10312
+ overrideRelevance: settings && typeof settings.overrideRelevance !== "undefined" ? settings.overrideRelevance : false,
10313
+ regenerateSlugs: settings && typeof settings.regenerateSlugs !== "undefined" ? settings.regenerateSlugs : false,
10314
+ keepOldMembers: settings && typeof settings.keepOldMembers !== "undefined" ? settings.keepOldMembers : true,
10315
+ doIngest: settings && typeof settings.doIngest !== "undefined" ? settings.doIngest : false,
10316
+ overrideAttributes: settings && typeof settings.overrideAttributes !== "undefined" ? settings.overrideAttributes : false
10317
+ });
10318
+
10319
+ // components/builder/components/SwitchWithTooltip.tsx
10320
+ init_esm_shims();
10321
+ function SwitchWithTooltip({ switchProps, yesText, noText }) {
10322
+ const finalSwitchProps = {
10323
+ size: "md",
10324
+ onLabel: "YES",
10325
+ offLabel: "NO",
10326
+ label: "Switch Label",
10327
+ my: "xs",
10328
+ checked: false,
10329
+ onChange: (event) => console.log(event.currentTarget.checked),
10330
+ ...switchProps
10331
+ };
10332
+ return /* @__PURE__ */ jsxs(Group, { children: [
10333
+ /* @__PURE__ */ jsx(Switch, { ...finalSwitchProps }),
10334
+ /* @__PURE__ */ jsx(
10335
+ Tooltip,
10336
+ {
10337
+ label: finalSwitchProps.checked ? yesText : noText,
10338
+ withArrow: true,
10339
+ multiline: true,
10340
+ width: 200,
10341
+ children: /* @__PURE__ */ jsx(ActionIcon, { variant: "filled", radius: "50%", size: "xs", children: /* @__PURE__ */ jsx(IconQuestionMark, { size: "xs" }) })
10342
+ }
10343
+ )
10344
+ ] });
10345
+ }
10346
+ var SwitchWithTooltip_default = SwitchWithTooltip;
10347
+
10348
+ // libs/js/isURL.ts
10349
+ init_esm_shims();
10350
+ function isURL(url) {
10351
+ try {
10352
+ new URL(url);
10353
+ return true;
10354
+ } catch (error) {
10355
+ return false;
10356
+ }
10357
+ }
10358
+ function VariantEditor({ for: variant, onClose: closeHandler }) {
10359
+ const dispatch = useAppDispatch();
10360
+ const localeDefault10 = useAppSelector((state) => state.status.localeDefault);
10361
+ const locales4 = useAppSelector((state) => state.status.locales);
10362
+ const localesItems = locales4.map((locale) => ({ value: locale, label: locale.toUpperCase() }));
10363
+ const [sample, setSample] = useState();
10364
+ const [selectedLocale, setSelectedLocale] = useState(localeDefault10);
10365
+ const [variantConfig, setVariantConfig] = useState(() => {
10366
+ const hydratedVariant = { ...variant };
10367
+ locales4.forEach((l) => {
10368
+ hydratedVariant.config = {
10369
+ ...hydratedVariant.config,
10370
+ [l]: {
10371
+ ...{
10372
+ attributes: [],
10373
+ idKey: "",
10374
+ labelKey: "",
10375
+ accessor: "",
10376
+ path: ""
10377
+ },
10378
+ ...hydratedVariant.config[l] || {}
10379
+ }
10380
+ };
10381
+ });
10382
+ return hydratedVariant;
10383
+ });
10384
+ const [loading, setLoading] = useState(false);
10385
+ const [loadingFetch, setLoadingFetch] = useState(false);
10386
+ const [fetchError, setFetchError] = useState(false);
10387
+ const [loadingValidSlug, setLoadingValidSlug] = useState(false);
10388
+ const [validSlug, setValidSlug] = useState({ valid: false, suggestion: "" });
10389
+ const [payload, setPayload] = useState();
10390
+ const [accessors, setAccessors] = useState([]);
10391
+ const [loadingSearch, setLoadingSearch] = useState(false);
10392
+ const [membersSearch, setMembersSearch] = useState([]);
10393
+ const getMembers = (path) => {
10394
+ if (isURL(path)) {
10395
+ setLoadingFetch(true);
10396
+ dispatch(actions_exports.urlProxy(path)).then((resp) => {
10397
+ setPayload(resp);
10398
+ if (resp) {
10399
+ const keys2 = arrayFinder(resp);
10400
+ setAccessors(keys2);
10401
+ if (variantConfig.config[selectedLocale].accessor && resp[variantConfig.config[selectedLocale].accessor]) {
10402
+ setConfigFromSample(
10403
+ resp[variantConfig.config[selectedLocale].accessor][0],
10404
+ variantConfig.config[selectedLocale].accessor
10405
+ );
10406
+ } else if (keys2.length === 0) {
10407
+ if (resp && resp[0])
10408
+ setConfigFromSample(resp[0]);
10409
+ }
10410
+ }
10411
+ setFetchError(false);
10412
+ setLoadingFetch(false);
10413
+ }).catch((e) => {
10414
+ console.error(e);
10415
+ setFetchError(`Fetch error: ${e.message}`);
10416
+ setPayload(void 0);
10417
+ setLoadingFetch(false);
10418
+ });
10419
+ }
10420
+ };
10421
+ const searchIngestedMembers = (variantId) => {
10422
+ setLoadingSearch(true);
10423
+ const searchParams = parseSearchMemberParams({
10424
+ variant: variantId,
10425
+ limit: "5",
10426
+ locale: "all",
10427
+ visible: "true",
10428
+ includes: "true",
10429
+ noImage: "false",
10430
+ format: "plain",
10431
+ all: "true"
10432
+ });
10433
+ dispatch(actions_exports.searchMember(searchParams)).then((resp) => {
10434
+ if (resp && resp.results) {
10435
+ const members = resp.results;
10436
+ setMembersSearch(members);
10437
+ if (members.length === 0) {
10438
+ onChangeSettings("doIngest", true);
10439
+ }
10440
+ }
10441
+ setLoadingSearch(false);
10442
+ }).catch((e) => {
10443
+ console.error(e);
10444
+ setLoadingSearch(false);
10445
+ });
10446
+ };
10447
+ const setConfigFromSample = (sample2, accessor = "") => {
10448
+ if (sample2) {
10449
+ const sampleKeys = Object.keys(sample2);
10450
+ const guessId = sampleKeys.find((d) => d.toLowerCase().includes("id")) || sampleKeys[0];
10451
+ const guessName = sampleKeys.find((d) => !d.toLowerCase().includes("id")) || sampleKeys[0];
10452
+ if (!variantConfig.config[selectedLocale].idKey || variantConfig.config[selectedLocale].idKey === "" || !variantConfig.config[selectedLocale].labelKey || variantConfig.config[selectedLocale].labelKey === "") {
10453
+ setVariantConfig({
10454
+ ...variantConfig,
10455
+ config: {
10456
+ ...variantConfig.config,
10457
+ [selectedLocale]: {
10458
+ ...variantConfig.config[selectedLocale],
10459
+ idKey: guessId,
10460
+ labelKey: guessName,
10461
+ accessor
10462
+ }
10463
+ }
10464
+ });
10465
+ }
10466
+ }
10467
+ setSample(sample2);
10468
+ };
10469
+ useEffect(() => {
10470
+ if (variantConfig.id) {
10471
+ searchIngestedMembers(variantConfig.id);
10472
+ }
10473
+ validateSlug(variantConfig.slug);
10474
+ if (variantConfig.config[selectedLocale] && variantConfig.config[selectedLocale].path) {
10475
+ getMembers(variantConfig.config[selectedLocale].path);
10476
+ }
10477
+ }, []);
10478
+ const onLocaleChange = (newLocale) => {
10479
+ setPayload(void 0);
10480
+ setFetchError(false);
10481
+ let attributesList = [];
10482
+ if (newLocale !== localeDefault10) {
10483
+ const defaultAttributes = variantConfig.config[localeDefault10] ? [...variantConfig.config[localeDefault10].attributes].map((item) => {
10484
+ const newItem = { ...item };
10485
+ newItem.value = "";
10486
+ return newItem;
10487
+ }) : [];
10488
+ if (variantConfig.config[newLocale] && variantConfig.config[newLocale].attributes) {
10489
+ attributesList = defaultAttributes.map((da) => {
10490
+ const item = variantConfig.config[newLocale].attributes.find((sa) => da.name === sa.name);
10491
+ if (item) {
10492
+ da.value = item.value;
10493
+ }
10494
+ return da;
10495
+ });
10496
+ } else {
10497
+ attributesList = defaultAttributes;
10498
+ }
10499
+ const newConfig = {
10500
+ ...variantConfig.config,
10501
+ [newLocale]: {
10502
+ ...variantConfig.config[newLocale],
10503
+ attributes: attributesList
10504
+ }
10505
+ };
10506
+ setVariantConfig({
10507
+ ...variantConfig,
10508
+ config: newConfig
10509
+ });
10510
+ }
10511
+ if (variantConfig.config[newLocale] && variantConfig.config[newLocale].path) {
10512
+ getMembers(variantConfig.config[newLocale].path);
10513
+ }
10514
+ setSelectedLocale(newLocale);
10515
+ };
10516
+ const variantSettings = useMemo(() => getVariantSettingsDefaults(variantConfig.settings), [variantConfig.settings]);
10517
+ const variantSettingsSwitches = useMemo(() => [
10518
+ {
10519
+ label: "Replace names",
10520
+ key: "overrideNames",
10521
+ yesText: "Names from new source will update the previously ingested members.",
10522
+ noText: "Original names will be keep."
10523
+ },
10524
+ {
10525
+ label: "Replace slugs",
10526
+ key: "regenerateSlugs",
10527
+ yesText: "Slugs will be regenerated based on new member's names and updated on previously ingested members.",
10528
+ noText: "Original slugs will be keep.",
10529
+ disabled: !variantSettings.overrideNames
10530
+ },
10531
+ {
10532
+ label: "Replace relevance value",
10533
+ key: "overrideRelevance",
10534
+ yesText: "Relevance index will be recalculated and updated on previously ingested members.",
10535
+ noText: "Original numbers will be keep."
10536
+ },
10537
+ {
10538
+ label: "Replace attributes",
10539
+ key: "overrideAttributes",
10540
+ yesText: "Attributes will be regenerated and override the current ones. Different ones will be kept.",
10541
+ noText: "Original attributes will be keep, ignoring the changes"
10542
+ },
10543
+ {
10544
+ label: "Keep all existing members",
10545
+ key: "keepOldMembers",
10546
+ yesText: "All the the existing members will be keep even if they are not in the new API members list",
10547
+ noText: "Members that are not in the API members list will be deleted, keeping both lists on sync."
10548
+ }
10549
+ ], [variantSettings.overrideNames]);
10550
+ const onChangeAccessor = (accessor) => {
10551
+ const dataArray = keyDiver(payload, accessor);
10552
+ if (dataArray[0]) {
10553
+ setConfigFromSample(dataArray[0], accessor);
10554
+ }
10555
+ };
10556
+ const validateSlug = (slug) => {
10557
+ dispatch(actions_exports.variantValidateSlug(variantConfig.dimension_id, slug)).then(setValidSlug).then(() => {
10558
+ setLoadingValidSlug(false);
10559
+ }, (err) => {
10560
+ console.error(err);
10561
+ });
10562
+ };
10124
10563
  const onChange = (field, value) => {
10125
10564
  let newValue = value;
10126
10565
  if (field === "slug") {
10127
10566
  newValue = slugifyInput_default(value);
10567
+ if (newValue) {
10568
+ setLoadingValidSlug(true);
10569
+ validateSlug(value);
10570
+ }
10128
10571
  }
10129
10572
  setVariantConfig({ ...variantConfig, [field]: newValue });
10130
10573
  };
10131
10574
  const onChangeConfig = (field, value) => {
10575
+ if (field === "path") {
10576
+ setFetchError(false);
10577
+ }
10132
10578
  setVariantConfig({
10133
10579
  ...variantConfig,
10134
10580
  config: {
@@ -10140,6 +10586,18 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
10140
10586
  }
10141
10587
  });
10142
10588
  };
10589
+ const onChangeSettings = (field, value) => {
10590
+ const extraUpdate = field === "overrideNames" && !value ? { regenerateSlugs: false } : {};
10591
+ setVariantConfig({
10592
+ ...variantConfig,
10593
+ //config: configUpdate,
10594
+ settings: {
10595
+ ...variantConfig.settings,
10596
+ ...extraUpdate,
10597
+ [field]: value
10598
+ }
10599
+ });
10600
+ };
10143
10601
  const onSubmit = () => {
10144
10602
  setLoading(true);
10145
10603
  dispatch(actions_exports.updateEntity("variant", variantConfig)).then(() => {
@@ -10163,15 +10621,17 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
10163
10621
  });
10164
10622
  };
10165
10623
  const addAttributes = () => {
10166
- const sampleKeys = Object.keys(sample);
10167
- const sampleKey = sampleKeys[0];
10168
- if (sampleKey) {
10169
- const existingAttributes = variantConfig.config[selectedLocale]?.attributes || [];
10170
- const attrCount = existingAttributes.length || 0;
10171
- updateAttributes([
10172
- ...existingAttributes,
10173
- { type: "constant", name: `attr${attrCount + 1}`, value: "" }
10174
- ]);
10624
+ if (sample) {
10625
+ const sampleKeys = Object.keys(sample);
10626
+ const sampleKey = sampleKeys[0];
10627
+ if (sampleKey) {
10628
+ const existingAttributes = variantConfig.config[selectedLocale]?.attributes || [];
10629
+ const attrCount = existingAttributes.length || 0;
10630
+ updateAttributes([
10631
+ ...existingAttributes,
10632
+ { type: "constant", name: `attr${attrCount + 1}`, value: "" }
10633
+ ]);
10634
+ }
10175
10635
  }
10176
10636
  };
10177
10637
  const onChangeAttribute = (key, targetIx, value) => {
@@ -10192,200 +10652,276 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
10192
10652
  };
10193
10653
  const keys = sample ? Object.keys(sample).map((d) => ({ value: d, label: `${d}: ${sample[d]}` })) : [];
10194
10654
  const accessorSelectData = accessors.map((d) => ({ value: d, label: d }));
10655
+ const invalidPath = !isURL(variantConfig.config[selectedLocale].path);
10656
+ const fetchErrorMsg = useMemo(() => {
10657
+ if (fetchError)
10658
+ return fetchError;
10659
+ if (invalidPath && variantConfig.config[selectedLocale].path !== "")
10660
+ return "Format error: Invalid URL.";
10661
+ return false;
10662
+ }, [fetchError, invalidPath, variantConfig.config, selectedLocale]);
10195
10663
  return /* @__PURE__ */ jsx(
10196
10664
  DrawerContentWithScroll,
10197
10665
  {
10198
10666
  content: /* @__PURE__ */ jsxs(Fragment, { children: [
10199
10667
  /* @__PURE__ */ jsx(Title, { order: 2, children: `Editing Variant: ${variantConfig.name}` }),
10200
10668
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
10201
- /* @__PURE__ */ jsx(TextInput, { value: variantConfig.name, label: "Name", onChange: (e) => onChange("name", e.target.value) }),
10202
- /* @__PURE__ */ jsx(Space, { h: "xs" }),
10203
- /* @__PURE__ */ jsx(
10204
- TextInput,
10205
- {
10206
- value: variantConfig.slug,
10207
- icon: !loadingValidSlug && !validSlug.valid ? /* @__PURE__ */ jsx(IconAlertCircle, {}) : /* @__PURE__ */ jsx(IconCircleCheck, {}),
10208
- label: "Slug",
10209
- description: loadingValidSlug ? "Validating slug..." : validSlug.valid ? "Valid slug." : "Invalid slug.",
10210
- error: !loadingValidSlug && !validSlug.valid ? /* @__PURE__ */ jsxs(Text, { children: [
10211
- "Duplicated slug. Suggestion:",
10212
- /* @__PURE__ */ jsx(
10213
- Code,
10214
- {
10215
- onClick: () => onChange("slug", validSlug.suggestion),
10216
- style: { cursor: "pointer" },
10217
- children: validSlug.suggestion
10218
- }
10219
- )
10220
- ] }) : false,
10221
- onChange: (e) => onChange("slug", e.target.value)
10222
- }
10223
- ),
10224
- /* @__PURE__ */ jsx(Divider, { my: "lg" }),
10225
- /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: "Members data" }),
10226
- /* @__PURE__ */ jsx(Space, { h: "xs" }),
10227
- /* @__PURE__ */ jsx(
10228
- SegmentedControl,
10229
- {
10230
- value: selectedLocale,
10231
- fullWidth: true,
10232
- onChange: setSelectedLocale,
10233
- data: localesItems
10234
- }
10235
- ),
10236
- variantConfig.config[selectedLocale] && /* @__PURE__ */ jsxs(Fragment, { children: [
10237
- /* @__PURE__ */ jsx(Space, { h: "lg" }),
10238
- /* @__PURE__ */ jsxs(Group, { grow: true, align: "flex-end", children: [
10669
+ /* @__PURE__ */ jsxs(Tabs, { defaultValue: "variant", children: [
10670
+ /* @__PURE__ */ jsxs(Tabs.List, { grow: true, children: [
10671
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "variant", children: "Variant" }),
10672
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "members", children: "Members" })
10673
+ ] }),
10674
+ /* @__PURE__ */ jsxs(Tabs.Panel, { value: "variant", py: "md", children: [
10675
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Variant Settings" }),
10676
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
10239
10677
  /* @__PURE__ */ jsx(
10240
10678
  TextInput,
10241
10679
  {
10242
- onChange: (e) => onChangeConfig("path", e.target.value),
10243
- title: "Api endpoint",
10244
- description: "Enter the url to retrieve a member list to ingest. (JSON) and click Fetch.",
10245
- value: variantConfig.config[selectedLocale].path
10680
+ value: variantConfig.name,
10681
+ label: "Name",
10682
+ onChange: (e) => onChange("name", e.target.value)
10246
10683
  }
10247
10684
  ),
10685
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
10248
10686
  /* @__PURE__ */ jsx(
10249
- Button,
10687
+ TextInput,
10250
10688
  {
10251
- disabled: loadingFetch,
10252
- onClick: () => getMembers(variantConfig.config[selectedLocale].path),
10253
- loading: loadingFetch,
10254
- leftIcon: /* @__PURE__ */ jsx(IconPlayerPlay, {}),
10255
- children: loadingFetch ? "Fetching" : "Fetch"
10689
+ value: variantConfig.slug,
10690
+ icon: !loadingValidSlug && !validSlug.valid ? /* @__PURE__ */ jsx(IconAlertCircle, {}) : /* @__PURE__ */ jsx(IconCircleCheck, {}),
10691
+ label: "Slug",
10692
+ description: loadingValidSlug ? "Validating slug..." : validSlug.valid ? "Valid slug." : "Invalid slug.",
10693
+ error: !loadingValidSlug && !validSlug.valid ? /* @__PURE__ */ jsxs(Text, { children: [
10694
+ "Duplicated slug. Suggestion:",
10695
+ /* @__PURE__ */ jsx(
10696
+ Code,
10697
+ {
10698
+ onClick: () => onChange("slug", validSlug.suggestion),
10699
+ style: { cursor: "pointer" },
10700
+ children: validSlug.suggestion
10701
+ }
10702
+ )
10703
+ ] }) : false,
10704
+ onChange: (e) => onChange("slug", e.target.value)
10256
10705
  }
10257
10706
  )
10258
10707
  ] }),
10259
- payload && /* @__PURE__ */ jsxs("div", { children: [
10260
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10261
- /* @__PURE__ */ jsx(
10262
- Select,
10263
- {
10264
- value: variantConfig.config[selectedLocale].accessor,
10265
- label: "Elements",
10266
- description: "Choose the key that returns the array of elements that \n are going to be ingested as members.",
10267
- data: accessorSelectData,
10268
- disabled: accessorSelectData.length === 0,
10269
- placeholder: accessorSelectData.length === 0 ? "Root is an array" : "",
10270
- onChange: (e) => onChangeAccessor(e)
10271
- }
10272
- ),
10273
- /* @__PURE__ */ jsx(Divider, { label: "First element preview", labelPosition: "center" }),
10274
- payload[variantConfig.config[selectedLocale].accessor] && !Array.isArray(payload) && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[variantConfig.config[selectedLocale].accessor][0] }),
10275
- Array.isArray(payload) && payload[0] && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[0] }),
10276
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10277
- /* @__PURE__ */ jsx(
10278
- Select,
10279
- {
10280
- value: variantConfig.config[selectedLocale].idKey,
10281
- label: "Unique identificator",
10282
- description: "Choose the field that is a unique identification for a single member.",
10283
- data: keys,
10284
- onChange: (e) => onChangeConfig("idKey", e)
10285
- }
10286
- ),
10287
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10288
- /* @__PURE__ */ jsx(
10289
- Select,
10290
- {
10291
- value: variantConfig.config[selectedLocale].labelKey,
10292
- label: "Members' name",
10293
- description: "Choose the field that contains the members name.",
10294
- data: keys,
10295
- onChange: (e) => onChangeConfig("labelKey", e)
10296
- }
10297
- ),
10298
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10708
+ /* @__PURE__ */ jsxs(Tabs.Panel, { value: "members", py: "md", children: [
10709
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Members Settings" }),
10710
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Members, once ingested, become pages for this variant." }),
10299
10711
  /* @__PURE__ */ jsx(
10300
- Select,
10712
+ SwitchWithTooltip_default,
10301
10713
  {
10302
- value: variantConfig.config[selectedLocale].zValueKey || "",
10303
- label: "Member's relevance (optional)",
10304
- description: "Choose a field that will be converted to a number and \n normalized from 0 to 1 to determine the member's relevance.",
10305
- data: [
10306
- { value: "null", label: "None" },
10307
- ...keys
10308
- ],
10309
- onChange: (e) => onChangeConfig("zValueKey", e)
10714
+ switchProps: {
10715
+ label: `${!loadingSearch && membersSearch.length > 0 ? "Re-" : ""}Ingest members`,
10716
+ checked: variantSettings.doIngest,
10717
+ onChange: (event) => onChangeSettings("doIngest", event.currentTarget.checked)
10718
+ },
10719
+ yesText: `Run the ingestion process and save the variant details.
10720
+ Remember include the ingestion information for all the locales.`,
10721
+ noText: "Ingestion is not going to run and the current members are not going to suffer any change."
10310
10722
  }
10311
10723
  ),
10312
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10313
- /* @__PURE__ */ jsx(Title, { order: 3, size: "h5", children: "Attributes" }),
10314
- /* @__PURE__ */ jsx(Text, { size: "sm", children: "Attributes are properties to be ingested as metadata with the member element. Could be constants (same value for every member) or dynamic (based on a property of the data)" }),
10315
- /* @__PURE__ */ jsx(Space, { h: "xs" }),
10316
- variantConfig.config[selectedLocale].attributes && variantConfig.config[selectedLocale].attributes.map((attr, ix) => /* @__PURE__ */ jsxs(Group, { align: "end", grow: true, children: [
10317
- /* @__PURE__ */ jsx(
10318
- Select,
10724
+ variantSettings.doIngest && !loadingSearch && membersSearch.length > 0 && /* @__PURE__ */ jsxs(Box, { ml: "lg", children: [
10725
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Settings that are going to be applied for members reingestions and for all available languages, matching by unique identificator. All new members are going to be ingested. Images and tags for existing members will be safe." }),
10726
+ variantSettingsSwitches.map((vs) => /* @__PURE__ */ jsx(
10727
+ SwitchWithTooltip_default,
10319
10728
  {
10320
- value: variantConfig.config[selectedLocale].attributes[ix].type,
10321
- label: "Type",
10322
- data: [{ value: "variable", label: "Data based" }, { value: "constant", label: "Constant" }],
10323
- readOnly: selectedLocale !== localeDefault10,
10324
- disabled: selectedLocale !== localeDefault10,
10325
- onChange: (e) => onChangeAttribute("type", ix, e)
10326
- }
10327
- ),
10729
+ switchProps: {
10730
+ disabled: vs.disabled,
10731
+ label: vs.label,
10732
+ checked: variantSettings[vs.key],
10733
+ onChange: (event) => onChangeSettings(vs.key, event.currentTarget.checked)
10734
+ },
10735
+ yesText: vs.yesText,
10736
+ noText: vs.noText
10737
+ },
10738
+ vs.key
10739
+ ))
10740
+ ] }),
10741
+ !variantSettings.doIngest && /* @__PURE__ */ jsxs(Fragment, { children: [
10742
+ /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: "Ingested members preview" }),
10743
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
10744
+ /* @__PURE__ */ jsxs(Stack, { spacing: 0, justify: "center", children: [
10745
+ loadingSearch && /* @__PURE__ */ jsx(Loader, { m: "0 auto" }),
10746
+ !loadingSearch && membersSearch.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
10747
+ /* @__PURE__ */ jsx(
10748
+ MembersTable,
10749
+ {
10750
+ members: membersSearch,
10751
+ colsToRender: ["id", "name", "slug"]
10752
+ }
10753
+ ),
10754
+ /* @__PURE__ */ jsx(Link, { href: "metadata", passHref: true, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", align: "center", td: "underline", size: "xs", children: "See the full list in Metadata View" }) })
10755
+ ] })
10756
+ ] }),
10757
+ !loadingSearch && membersSearch.length === 0 && /* @__PURE__ */ jsx(Text, { c: "dimmed", align: "center", children: "No members ingested yet." }),
10758
+ /* @__PURE__ */ jsx(Space, { h: "xs" })
10759
+ ] }),
10760
+ variantSettings.doIngest && /* @__PURE__ */ jsxs(Fragment, { children: [
10761
+ /* @__PURE__ */ jsx(Divider, { my: "sm" }),
10762
+ /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: "Members ingestion" }),
10763
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
10328
10764
  /* @__PURE__ */ jsx(
10329
- TextInput,
10330
- {
10331
- value: variantConfig.config[selectedLocale].attributes[ix].name,
10332
- label: "Name",
10333
- readOnly: selectedLocale !== localeDefault10,
10334
- disabled: selectedLocale !== localeDefault10,
10335
- onChange: (e) => onChangeAttribute("name", ix, e.target.value)
10336
- }
10337
- ),
10338
- attr.type === "variable" && /* @__PURE__ */ jsx(
10339
- Select,
10765
+ SegmentedControl,
10340
10766
  {
10341
- value: variantConfig.config[selectedLocale].attributes[ix].value,
10342
- label: "Value",
10343
- data: keys,
10344
- onChange: (e) => onChangeAttribute("value", ix, e)
10767
+ value: selectedLocale,
10768
+ fullWidth: true,
10769
+ onChange: onLocaleChange,
10770
+ data: localesItems,
10771
+ disabled: loadingFetch
10345
10772
  }
10346
10773
  ),
10347
- attr.type === "constant" && /* @__PURE__ */ jsx(
10348
- TextInput,
10349
- {
10350
- value: variantConfig.config[selectedLocale].attributes[ix].value,
10351
- label: "Value",
10352
- onChange: (e) => onChangeAttribute("value", ix, e.target.value)
10353
- }
10354
- ),
10355
- /* @__PURE__ */ jsx(
10356
- ActionIcon,
10357
- {
10358
- color: "red",
10359
- onClick: () => deleteAttribute(ix),
10360
- disabled: selectedLocale !== localeDefault10,
10361
- children: /* @__PURE__ */ jsx(IconTrash, { size: 20 })
10362
- }
10363
- )
10364
- ] }, ix)),
10365
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10366
- /* @__PURE__ */ jsx(
10367
- Button,
10368
- {
10369
- onClick: addAttributes,
10370
- leftIcon: "+",
10371
- disabled: loading || selectedLocale !== localeDefault10,
10372
- children: "Add Attribute"
10373
- }
10374
- )
10774
+ variantConfig.config[selectedLocale] && /* @__PURE__ */ jsxs(Fragment, { children: [
10775
+ /* @__PURE__ */ jsx(Space, { h: "lg" }),
10776
+ /* @__PURE__ */ jsx(Group, { children: /* @__PURE__ */ jsx(
10777
+ TextInput,
10778
+ {
10779
+ onChange: (e) => onChangeConfig("path", e.target.value),
10780
+ title: "Api endpoint",
10781
+ description: "Enter the url to retrieve a member list to ingest. (JSON) and click Fetch.",
10782
+ value: variantConfig.config[selectedLocale].path,
10783
+ error: fetchErrorMsg,
10784
+ rightSectionWidth: "105px",
10785
+ w: "100%",
10786
+ rightSection: loadingFetch ? /* @__PURE__ */ jsxs(Group, { align: "center", children: [
10787
+ /* @__PURE__ */ jsx(Loader, { size: "xs" }),
10788
+ /* @__PURE__ */ jsx(Text, { span: true, variant: "subtle", size: "xs", children: "Fetching..." })
10789
+ ] }) : /* @__PURE__ */ jsx(
10790
+ Button,
10791
+ {
10792
+ disabled: loadingFetch || invalidPath,
10793
+ onClick: () => getMembers(variantConfig.config[selectedLocale].path),
10794
+ leftIcon: /* @__PURE__ */ jsx(IconPlayerPlay, {}),
10795
+ children: "Fetch"
10796
+ }
10797
+ ),
10798
+ readOnly: loadingFetch
10799
+ }
10800
+ ) }),
10801
+ payload && /* @__PURE__ */ jsxs("div", { children: [
10802
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10803
+ /* @__PURE__ */ jsx(
10804
+ Select,
10805
+ {
10806
+ value: variantConfig.config[selectedLocale].accessor,
10807
+ label: "Elements",
10808
+ description: "Choose the key that returns the array of elements that \n are going to be ingested as members.",
10809
+ data: accessorSelectData,
10810
+ disabled: accessorSelectData.length === 0,
10811
+ placeholder: accessorSelectData.length === 0 ? "Root is an array" : "",
10812
+ onChange: (e) => onChangeAccessor(e)
10813
+ }
10814
+ ),
10815
+ /* @__PURE__ */ jsx(Divider, { label: "First element preview", labelPosition: "center" }),
10816
+ payload[variantConfig.config[selectedLocale].accessor] && !Array.isArray(payload) && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[variantConfig.config[selectedLocale].accessor][0] }),
10817
+ Array.isArray(payload) && payload[0] && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[0] }),
10818
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10819
+ /* @__PURE__ */ jsx(
10820
+ Select,
10821
+ {
10822
+ value: variantConfig.config[selectedLocale].idKey,
10823
+ label: "Unique identificator",
10824
+ description: "Choose the field that is a unique identification for a single member.",
10825
+ data: keys,
10826
+ onChange: (e) => onChangeConfig("idKey", e)
10827
+ }
10828
+ ),
10829
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10830
+ /* @__PURE__ */ jsx(
10831
+ Select,
10832
+ {
10833
+ value: variantConfig.config[selectedLocale].labelKey,
10834
+ label: "Members' name",
10835
+ description: "Choose the field that contains the members name.",
10836
+ data: keys,
10837
+ onChange: (e) => onChangeConfig("labelKey", e)
10838
+ }
10839
+ ),
10840
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10841
+ /* @__PURE__ */ jsx(
10842
+ Select,
10843
+ {
10844
+ value: variantConfig.config[selectedLocale].zValueKey || "",
10845
+ label: "Member's relevance (optional)",
10846
+ description: "Choose a field that will be converted to a number and \n normalized from 0 to 1 to determine the member's relevance.",
10847
+ data: [
10848
+ { value: "null", label: "None" },
10849
+ ...keys
10850
+ ],
10851
+ onChange: (e) => onChangeConfig("zValueKey", e)
10852
+ }
10853
+ ),
10854
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10855
+ /* @__PURE__ */ jsx(Title, { order: 3, size: "h5", children: "Attributes" }),
10856
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Attributes are properties to be ingested as metadata with the member element. Could be constants (same value for every member) or dynamic (based on a property of the data)" }),
10857
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
10858
+ variantConfig.config[selectedLocale].attributes && variantConfig.config[selectedLocale].attributes.map((attr, ix) => /* @__PURE__ */ jsxs(Group, { align: "end", grow: true, children: [
10859
+ /* @__PURE__ */ jsx(
10860
+ Select,
10861
+ {
10862
+ value: variantConfig.config[selectedLocale].attributes[ix].type,
10863
+ label: "Type",
10864
+ data: [
10865
+ { value: "variable", label: "Data based" },
10866
+ { value: "constant", label: "Constant" }
10867
+ ],
10868
+ readOnly: selectedLocale !== localeDefault10,
10869
+ disabled: selectedLocale !== localeDefault10,
10870
+ onChange: (e) => onChangeAttribute("type", ix, e)
10871
+ }
10872
+ ),
10873
+ /* @__PURE__ */ jsx(
10874
+ TextInput,
10875
+ {
10876
+ value: variantConfig.config[selectedLocale].attributes[ix].name,
10877
+ label: "Name",
10878
+ readOnly: selectedLocale !== localeDefault10,
10879
+ disabled: selectedLocale !== localeDefault10,
10880
+ onChange: (e) => onChangeAttribute("name", ix, e.target.value)
10881
+ }
10882
+ ),
10883
+ attr.type === "variable" && /* @__PURE__ */ jsx(
10884
+ Select,
10885
+ {
10886
+ value: variantConfig.config[selectedLocale].attributes[ix].value,
10887
+ label: "Value",
10888
+ data: keys,
10889
+ onChange: (e) => onChangeAttribute("value", ix, e)
10890
+ }
10891
+ ),
10892
+ attr.type === "constant" && /* @__PURE__ */ jsx(
10893
+ TextInput,
10894
+ {
10895
+ value: variantConfig.config[selectedLocale].attributes[ix].value,
10896
+ label: "Value",
10897
+ onChange: (e) => onChangeAttribute("value", ix, e.target.value)
10898
+ }
10899
+ ),
10900
+ /* @__PURE__ */ jsx(
10901
+ ActionIcon,
10902
+ {
10903
+ color: "red",
10904
+ onClick: () => deleteAttribute(ix),
10905
+ disabled: selectedLocale !== localeDefault10,
10906
+ children: /* @__PURE__ */ jsx(IconTrash, { size: 20 })
10907
+ }
10908
+ )
10909
+ ] }, ix)),
10910
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
10911
+ /* @__PURE__ */ jsx(
10912
+ Button,
10913
+ {
10914
+ onClick: addAttributes,
10915
+ leftIcon: "+",
10916
+ disabled: loading || selectedLocale !== localeDefault10,
10917
+ children: "Add Attribute"
10918
+ }
10919
+ )
10920
+ ] })
10921
+ ] }),
10922
+ /* @__PURE__ */ jsx(Space, { h: "md" })
10923
+ ] })
10375
10924
  ] })
10376
- ] }),
10377
- /* @__PURE__ */ jsx(Space, { h: "md" }),
10378
- /* @__PURE__ */ jsxs(Code, { block: true, children: [
10379
- "TO-DO Settings for member ingestion (all languages), checkboxes.",
10380
- /* @__PURE__ */ jsx("br", {}),
10381
- "(x) override names?",
10382
- /* @__PURE__ */ jsx("br", {}),
10383
- "(x) regenerate slugs based on names changes?",
10384
- /* @__PURE__ */ jsx("br", {}),
10385
- "(x) keep old members that doesn't exists?",
10386
- /* @__PURE__ */ jsx("br", {}),
10387
- "(x) keep metadata: tags, images?",
10388
- /* @__PURE__ */ jsx("br", {})
10389
10925
  ] })
10390
10926
  ] }),
10391
10927
  buttons: /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -10404,7 +10940,7 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
10404
10940
  disabled: loading || loadingFetch || !loadingValidSlug && !validSlug.valid,
10405
10941
  loading: loading || loadingFetch,
10406
10942
  onClick: onSubmit,
10407
- children: "Ingest & Save"
10943
+ children: `${variantSettings.doIngest ? `${!loadingSearch && membersSearch.length > 0 ? "Re-" : ""}Ingest & ` : ""}Save`
10408
10944
  }
10409
10945
  )
10410
10946
  ] }),
@@ -10459,12 +10995,12 @@ function DimensionEditor({ id, onClose: closeHandler }) {
10459
10995
  ),
10460
10996
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
10461
10997
  /* @__PURE__ */ jsx(
10462
- TextInput,
10998
+ NumberInput,
10463
10999
  {
10464
- value: config.ordering,
11000
+ value: config.ordering ? parseInt(config.ordering, 10) : 0,
10465
11001
  type: "number",
10466
11002
  label: "Order",
10467
- onChange: (e) => onChange("ordering", e.target.value)
11003
+ onChange: (value) => onChange("ordering", value)
10468
11004
  }
10469
11005
  ),
10470
11006
  /* @__PURE__ */ jsx(Divider, { my: "xl" }),
@@ -10571,129 +11107,6 @@ init_store2();
10571
11107
 
10572
11108
  // components/builder/DimensionAutocomplete.tsx
10573
11109
  init_esm_shims();
10574
-
10575
- // api/endpoints/member.ts
10576
- init_esm_shims();
10577
- init_getLocales();
10578
- init_stripHTML();
10579
- init_lib3();
10580
-
10581
- // api/endpoints/lib.ts
10582
- init_esm_shims();
10583
- init_lib3();
10584
- function parseFiniteNumber(value) {
10585
- const num = Number.parseInt(`${value || ""}`, 10);
10586
- if (Number.isNaN(num) || !Number.isFinite(num)) {
10587
- throw new BackendError(400, `Invalid numeric parameter: ${value}`);
10588
- }
10589
- return num;
10590
- }
10591
- function normalizeList(value) {
10592
- if (value == null || value === "") {
10593
- return [];
10594
- }
10595
- if (Array.isArray(value)) {
10596
- return value;
10597
- }
10598
- return value.toString().split(",");
10599
- }
10600
-
10601
- // api/endpoints/member.ts
10602
- var { localeDefault: localeDefault9 } = getLocales_default();
10603
- function parseReadMemberParams(query) {
10604
- const locale = normalizeList(query.locale)[0] || localeDefault9 || "en";
10605
- const all = locale === "all" || yn4(query.all);
10606
- const mode = normalizeList(query.mode)[0];
10607
- const outputParam = normalizeList(query.output)[0] || "full";
10608
- const output = outputParam === "lite" ? "lite" : "full";
10609
- const relatedLimit = parseInt(normalizeList(query.related)[0], 10) || 5;
10610
- let variant = normalizeList(query.variant).map(parseFiniteNumber);
10611
- if (variant.length === 0) {
10612
- variant = normalizeList(query["variant[]"]).map(parseFiniteNumber);
10613
- }
10614
- if (mode === "ids") {
10615
- return {
10616
- all,
10617
- mode,
10618
- variant,
10619
- output,
10620
- locale: all ? localeDefault9 : stripHTML(locale),
10621
- ids: normalizeList(query.ids || query["ids[]"])
10622
- };
10623
- }
10624
- if (mode === "content_ids") {
10625
- return {
10626
- all,
10627
- mode,
10628
- variant,
10629
- output,
10630
- locale: all ? localeDefault9 : stripHTML(locale),
10631
- content_ids: normalizeList(query.content_ids || query["content_ids[]"]).map(parseFiniteNumber)
10632
- };
10633
- }
10634
- if (mode === "slugs") {
10635
- return {
10636
- all,
10637
- mode,
10638
- variant,
10639
- output,
10640
- locale: all ? localeDefault9 : stripHTML(locale),
10641
- slugs: normalizeList(query.slugs || query["slugs[]"]).map((token) => {
10642
- const [variantSlug, memberSlug] = token.split("/");
10643
- return { variantSlug, memberSlug };
10644
- })
10645
- };
10646
- }
10647
- if (mode === "related") {
10648
- return {
10649
- all,
10650
- mode,
10651
- locale: all ? localeDefault9 : stripHTML(locale),
10652
- related: relatedLimit,
10653
- current_ids: normalizeList(query.current_ids || query["current_ids[]"]).map(parseFiniteNumber),
10654
- report_ids: normalizeList(query.report_ids || query["report_ids[]"]).map(parseFiniteNumber),
10655
- dimension_ids: normalizeList(query.dimension_ids || query["dimension_ids[]"]).map(parseFiniteNumber),
10656
- variant_ids: normalizeList(query.variant_ids || query["variant_ids[]"]).map(parseFiniteNumber),
10657
- output
10658
- };
10659
- }
10660
- throw new BackendError(400, `Invalid mode: '${mode}'`);
10661
- }
10662
- function parseSearchMemberParams(query) {
10663
- const locale = normalizeList(query.locale)[0] || localeDefault9 || "en";
10664
- const localeIsAll = locale === "all";
10665
- const format2 = normalizeList(query.format)[0];
10666
- const formatIsNested = format2 ? format2 === "nested" : localeIsAll;
10667
- let variant = normalizeList(query.variant).map(parseFiniteNumber);
10668
- if (variant.length === 0) {
10669
- variant = normalizeList(query["variant[]"]).map(parseFiniteNumber);
10670
- }
10671
- let dimension = normalizeList(query.dimension).map(parseFiniteNumber);
10672
- if (dimension.length === 0) {
10673
- dimension = normalizeList(query["dimension[]"]).map(parseFiniteNumber);
10674
- }
10675
- let report = normalizeList(query.report).map(parseFiniteNumber);
10676
- if (report.length === 0) {
10677
- report = normalizeList(query["report[]"]).map(parseFiniteNumber);
10678
- }
10679
- return {
10680
- query: normalizeList(query.query || query.q)[0] || "",
10681
- locale: localeIsAll ? localeDefault9 : locale,
10682
- limit: normalizeList(query.limit).map(parseFiniteNumber)[0] ?? 5,
10683
- format: formatIsNested ? "nested" : "plain",
10684
- includes: yn4(query.includes, { default: true }),
10685
- visible: yn4(query.visible, { default: true }),
10686
- noImage: yn4(query.noImage, { default: false }),
10687
- variant,
10688
- dimension,
10689
- report,
10690
- all: localeIsAll,
10691
- sort: normalizeList(query.sort)[0],
10692
- direction: normalizeList(query.direction)[0]
10693
- };
10694
- }
10695
-
10696
- // components/builder/DimensionAutocomplete.tsx
10697
11110
  init_store2();
10698
11111
  function DimensionAutocomplete({ id, locale, onSelect, initialSelection = void 0 }) {
10699
11112
  const dispatch = useAppDispatch();
@@ -14403,7 +14816,7 @@ function FormatterForm({ formatterId, onEditEnd }) {
14403
14816
  DrawerContentWithScroll,
14404
14817
  {
14405
14818
  content: /* @__PURE__ */ jsxs(Fragment, { children: [
14406
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: initialLoading, overlayBlur: 2, overlayOpacity: 50 }),
14819
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: initialLoading, overlayBlur: 2, overlayOpacity: 0.5 }),
14407
14820
  error && /* @__PURE__ */ jsx(Alert, { title: "Formatter Form", color: "red", children: "Error, please try again." }),
14408
14821
  formatter && !error && /* @__PURE__ */ jsxs(Stack, { justify: "space-between", children: [
14409
14822
  /* @__PURE__ */ jsxs(Group, { grow: true, align: "flex-start", children: [
@@ -14532,7 +14945,6 @@ var getCastedValue2 = (type, value) => {
14532
14945
  }
14533
14946
  };
14534
14947
  function FormattersTable({ filters, onClickEdit }) {
14535
- const [sortStatus, setSortStatus] = useState();
14536
14948
  const [records, setRecords] = useState([]);
14537
14949
  const formattersList = useFormatterList();
14538
14950
  const formatters2 = !formattersList.isSuccess ? [] : formattersList.data;
@@ -14556,7 +14968,7 @@ function FormattersTable({ filters, onClickEdit }) {
14556
14968
  };
14557
14969
  }), [formatters2]);
14558
14970
  const doSearch = () => {
14559
- let filteredResults = formattersFull.filter(
14971
+ const filteredResults = formattersFull.filter(
14560
14972
  (formatter) => {
14561
14973
  let findQuery = true;
14562
14974
  let findType = true;
@@ -14569,91 +14981,132 @@ function FormattersTable({ filters, onClickEdit }) {
14569
14981
  return findQuery && findType;
14570
14982
  }
14571
14983
  );
14572
- if (sortStatus) {
14573
- const sortIndex = sortStatus.direction === "asc" ? -1 : 1;
14574
- filteredResults = filteredResults.sort((a, b) => a[sortStatus.columnAccessor] > b[sortStatus.columnAccessor] ? 1 * sortIndex : -1 * sortIndex);
14575
- }
14576
14984
  setRecords(filteredResults);
14577
14985
  };
14578
14986
  useEffect(() => {
14579
14987
  doSearch();
14580
- }, [sortStatus, filters, formattersFull]);
14988
+ }, [filters, formattersFull]);
14581
14989
  const cols = [
14582
14990
  {
14583
- title: "ID",
14584
- accessor: "id",
14585
- sortable: true,
14586
- textAlignment: "right"
14991
+ header: "ID",
14992
+ accessorKey: "id",
14993
+ minSize: 55,
14994
+ size: 55,
14995
+ maxSize: 55
14587
14996
  },
14588
14997
  {
14589
- title: "Name",
14590
- accessor: "name",
14591
- sortable: true,
14592
- render: (member) => {
14593
- const icon = member.content.type === FORMATTER_TYPES.FORMATTER ? /* @__PURE__ */ jsx(IconVariable, { size: "1.3em" }) : /* @__PURE__ */ jsx(IconMathFunction, { size: "1.3em" });
14998
+ header: "Name",
14999
+ accessorKey: "name",
15000
+ Cell: ({ row }) => {
15001
+ const icon = row.original.content.type === FORMATTER_TYPES.FORMATTER ? /* @__PURE__ */ jsx(IconVariable, { size: "1.3em" }) : /* @__PURE__ */ jsx(IconMathFunction, { size: "1.3em" });
14594
15002
  return /* @__PURE__ */ jsxs(Group, { noWrap: true, align: "center", spacing: 2, children: [
14595
- /* @__PURE__ */ jsx("span", { children: member.name }),
14596
- /* @__PURE__ */ jsx(Tooltip, { label: FORMATTER_TYPES_NAMES[member.content.type], children: /* @__PURE__ */ jsx("span", { children: icon }) })
15003
+ /* @__PURE__ */ jsx("span", { children: row.original.name }),
15004
+ /* @__PURE__ */ jsx(Tooltip, { label: FORMATTER_TYPES_NAMES[row.original.content.type], children: /* @__PURE__ */ jsx("span", { children: icon }) })
14597
15005
  ] });
14598
- }
15006
+ },
15007
+ minSize: 80,
15008
+ size: 80
14599
15009
  },
14600
15010
  {
14601
- title: "Description",
14602
- accessor: "content.description"
15011
+ header: "Description",
15012
+ accessorKey: "content.description",
15013
+ enableSorting: false,
15014
+ mantineTableBodyCellProps: {
15015
+ sx: {
15016
+ textWrap: "wrap"
15017
+ }
15018
+ },
15019
+ minSize: 100
14603
15020
  },
14604
15021
  {
14605
- title: "Demo",
14606
- accessor: "content.testValue",
14607
- render: (member) => {
14608
- let input = member.content.testValue;
14609
- if (member.content.inputType === FORMATTER_INPUT_TYPES.STRING) {
15022
+ header: "Demo",
15023
+ accessorKey: "content.testValue",
15024
+ Cell: ({ row }) => {
15025
+ let input = row.original.content.testValue;
15026
+ if (row.original.content.inputType === FORMATTER_INPUT_TYPES.STRING) {
14610
15027
  input = `"${input}"`;
14611
15028
  }
14612
- let output = member.result;
14613
- if (typeof member.result === "string") {
15029
+ let output = row.original.result;
15030
+ if (typeof row.original.result === "string") {
14614
15031
  output = `"${output}"`;
14615
15032
  }
14616
15033
  return /* @__PURE__ */ jsxs(Group, { spacing: 2, children: [
14617
- /* @__PURE__ */ jsx(Tooltip, { label: `Input Type: ${FORMATTER_INPUT_TYPES_NAMES[member.content.inputType]}`, children: /* @__PURE__ */ jsx(Code, { color: "blue", children: input }) }),
15034
+ /* @__PURE__ */ jsx(Tooltip, { label: `Input Type: ${FORMATTER_INPUT_TYPES_NAMES[row.original.content.inputType]}`, children: /* @__PURE__ */ jsx(Code, { color: "blue", children: input }) }),
14618
15035
  /* @__PURE__ */ jsx(IconArrowRightCircle, {}),
14619
- /* @__PURE__ */ jsx(Code, { color: member.result && `${member.result}`.includes("ERROR") ? "red" : "teal", children: output })
15036
+ /* @__PURE__ */ jsx(Code, { color: row.original.result && `${row.original.result}`.includes("ERROR") ? "red" : "teal", children: output })
14620
15037
  ] });
14621
- }
15038
+ },
15039
+ enableSorting: false,
15040
+ minSize: 100,
15041
+ size: 100
14622
15042
  },
14623
15043
  {
14624
- title: "Usage",
14625
- accessor: "usageCount",
14626
- textAlignment: "right",
14627
- sortable: true
15044
+ header: "Usage",
15045
+ accessorKey: "usageCount",
15046
+ mantineTableHeadCellProps: {
15047
+ align: "right",
15048
+ sx: {
15049
+ "& .mantine-TableHeadCell-Content-Labels": {
15050
+ flexDirection: "row"
15051
+ }
15052
+ }
15053
+ },
15054
+ mantineTableBodyCellProps: {
15055
+ align: "right"
15056
+ },
15057
+ minSize: 85,
15058
+ size: 85,
15059
+ maxSize: 85
14628
15060
  },
14629
15061
  {
14630
- title: "",
14631
- accessor: "actions",
14632
- render: (member) => /* @__PURE__ */ jsxs(Group, { position: "center", spacing: "xs", noWrap: true, children: [
14633
- /* @__PURE__ */ jsx(ActionIcon, { onClick: () => onClickEdit(member), children: /* @__PURE__ */ jsx(IconPencil, { size: 20 }) }, "edit"),
15062
+ header: "Actions",
15063
+ accessorKey: "actions",
15064
+ Cell: ({ row }) => /* @__PURE__ */ jsxs(Group, { position: "center", spacing: "xs", noWrap: true, children: [
15065
+ /* @__PURE__ */ jsx(ActionIcon, { onClick: () => onClickEdit(row.original), children: /* @__PURE__ */ jsx(IconPencil, { size: 20 }) }, "edit"),
14634
15066
  /* @__PURE__ */ jsx(
14635
15067
  EntityDeleteButton,
14636
15068
  {
14637
- id: member.id,
15069
+ id: row.original.id,
14638
15070
  type: "formatter",
14639
- disabled: member.usageCount > 0,
14640
- warning: `Delete formatter called "${member.name}" (id:${member.id}) ? It is not used in any block.`
15071
+ disabled: row.original.usageCount > 0,
15072
+ warning: `Delete formatter called "${row.original.name}" (id:${row.original.id}) ? It is not used in any block.`
14641
15073
  }
14642
15074
  )
14643
- ] })
15075
+ ] }),
15076
+ enableSorting: false,
15077
+ minSize: 80,
15078
+ size: 80,
15079
+ maxSize: 80,
15080
+ mantineTableHeadCellProps: {
15081
+ align: "center"
15082
+ },
15083
+ mantineTableBodyCellProps: {
15084
+ align: "center"
15085
+ }
14644
15086
  }
14645
15087
  ];
14646
15088
  return /* @__PURE__ */ jsx(
14647
- DataTable,
15089
+ MantineReactTable,
14648
15090
  {
14649
- striped: true,
14650
- minHeight: 150,
14651
- records,
14652
15091
  columns: cols,
14653
- sortStatus,
14654
- onSortStatusChange: (s) => setSortStatus(s),
14655
- idAccessor: "id",
14656
- withBorder: true
15092
+ data: records,
15093
+ enableBottomToolbar: false,
15094
+ enableColumnActions: false,
15095
+ enableColumnResizing: true,
15096
+ enablePagination: false,
15097
+ enableTopToolbar: false,
15098
+ initialState: {
15099
+ density: "xs"
15100
+ },
15101
+ layoutMode: "grid",
15102
+ mantineTableContainerProps: {
15103
+ sx: {
15104
+ minHeight: 150
15105
+ }
15106
+ },
15107
+ mantineTableProps: {
15108
+ striped: true
15109
+ }
14657
15110
  }
14658
15111
  );
14659
15112
  }
@@ -14913,51 +15366,77 @@ init_store2();
14913
15366
 
14914
15367
  // components/metadata/ImageSelector.tsx
14915
15368
  init_esm_shims();
15369
+ var isProviderAllowed = (ipk) => {
15370
+ const allowedProviderOptions = process.env.NEXT_PUBLIC_IMAGE_PROVIDERS ? process.env.NEXT_PUBLIC_IMAGE_PROVIDERS.split(",") : [];
15371
+ return typeof process.env.NEXT_PUBLIC_IMAGE_PROVIDERS === "undefined" || allowedProviderOptions.indexOf(ipk) > -1 ? true : false;
15372
+ };
14916
15373
  function ImageSelector({ member, onEditEnd }) {
14917
15374
  const initialPrompt = member.contentByLocale && member.contentByLocale[0] ? member.contentByLocale[0].name : "";
14918
- const imageProviders = {
14919
- local: {
14920
- title: "Bespoke",
14921
- key: "local",
14922
- input: "text",
14923
- forceSearch: true,
14924
- getAxiosSearchConfig: (prompt2, image) => ({
14925
- url: "/api/cms/images/search/local",
14926
- method: "get",
14927
- params: { prompt: prompt2 }
14928
- })
14929
- },
14930
- flickr: {
14931
- title: "Flickr",
14932
- key: "flickr",
14933
- input: "text",
14934
- forceSearch: true,
14935
- getAxiosSearchConfig: (prompt2, image) => ({
14936
- url: "/api/cms/images/search/flickr",
14937
- method: "get",
14938
- params: { prompt: prompt2 }
14939
- })
14940
- },
14941
- unsplash: {
14942
- title: "Unsplash",
14943
- key: "unsplash",
14944
- input: "text",
14945
- forceSearch: true,
14946
- getAxiosSearchConfig: (prompt2, image) => ({
14947
- url: "/api/cms/images/search/unsplash",
14948
- method: "get",
14949
- params: { prompt: prompt2 }
14950
- })
14951
- },
14952
- upload: {
14953
- title: "Upload",
14954
- key: "upload",
14955
- input: "file",
14956
- forceSearch: false,
14957
- getAxiosSearchConfig: (prompt2, image) => ({})
14958
- }
14959
- };
14960
- const imageProvidersOptions = Object.keys(imageProviders).map((key) => ({ value: key, label: imageProviders[key].title }));
15375
+ const imageProviders = useMemo(
15376
+ () => ({
15377
+ upload: {
15378
+ title: "Upload",
15379
+ key: "upload",
15380
+ input: "file",
15381
+ forceSearch: false,
15382
+ pagination: false,
15383
+ getAxiosSearchConfig: (_prompt, _image, _page) => ({})
15384
+ },
15385
+ local: {
15386
+ title: "Gallery",
15387
+ key: "local",
15388
+ input: "text",
15389
+ forceSearch: true,
15390
+ pagination: false,
15391
+ getAxiosSearchConfig: (prompt2, _image, page) => ({
15392
+ url: "/api/cms/images/search/local",
15393
+ method: "get",
15394
+ params: { prompt: prompt2, page }
15395
+ })
15396
+ },
15397
+ flickr: {
15398
+ title: "Flickr",
15399
+ key: "flickr",
15400
+ input: "text",
15401
+ forceSearch: true,
15402
+ pagination: true,
15403
+ getAxiosSearchConfig: (prompt2, _image, page) => ({
15404
+ url: "/api/cms/images/search/flickr",
15405
+ method: "get",
15406
+ params: { prompt: prompt2, page }
15407
+ })
15408
+ },
15409
+ unsplash: {
15410
+ title: "Unsplash",
15411
+ key: "unsplash",
15412
+ input: "text",
15413
+ forceSearch: true,
15414
+ pagination: true,
15415
+ getAxiosSearchConfig: (prompt2, _image, page) => ({
15416
+ url: "/api/cms/images/search/unsplash",
15417
+ method: "get",
15418
+ params: { prompt: prompt2, page }
15419
+ })
15420
+ }
15421
+ /* adobe: {
15422
+ title: "Adobe",
15423
+ key: "adobe",
15424
+ input: "text",
15425
+ forceSearch: true,
15426
+ pagination: true,
15427
+ getAxiosSearchConfig: (prompt, _image, page): AxiosRequestConfig => ({
15428
+ url: "/api/cms/images/search/adobe",
15429
+ method: "get",
15430
+ params: {prompt, page},
15431
+ })
15432
+ }*/
15433
+ }),
15434
+ []
15435
+ );
15436
+ const imageProvidersOptions = useMemo(
15437
+ () => Object.values(imageProviders).filter((im) => isProviderAllowed(im.key)).map((im) => ({ value: im.key, label: im.title })),
15438
+ []
15439
+ );
14961
15440
  const [loading, setLoading] = useState(false);
14962
15441
  const [selectedProvider, setSelectedProvider] = useState(Object.values(imageProviders)[0]);
14963
15442
  const [scrollSize, setScrollSize] = useState(500);
@@ -14966,17 +15445,25 @@ function ImageSelector({ member, onEditEnd }) {
14966
15445
  const [results, setResults] = useState([]);
14967
15446
  const [selectedImage, setSelectedImage] = useState();
14968
15447
  const [error, setError] = useState(false);
14969
- const onSearch = async () => {
14970
- setError(false);
14971
- setLoading(true);
14972
- setResults([]);
14973
- const providerAxiosConfig = selectedProvider.getAxiosSearchConfig(prompt, imageToUpload);
14974
- const imageRecords = await axios(providerAxiosConfig).then((response) => response.data.data && response.data.data.results ? response.data.data.results : []).catch((e) => {
14975
- console.error(e);
14976
- setError(true);
14977
- });
14978
- setResults(imageRecords);
14979
- setLoading(false);
15448
+ const [selectedPage, setSelectedPage] = useState(1);
15449
+ const onSearch = async (page = void 0) => {
15450
+ if (page && page !== selectedPage) {
15451
+ setSelectedPage(1);
15452
+ } else {
15453
+ setError(false);
15454
+ setLoading(true);
15455
+ const providerAxiosConfig = selectedProvider.getAxiosSearchConfig(
15456
+ prompt,
15457
+ imageToUpload,
15458
+ page || selectedPage
15459
+ );
15460
+ const imageRecords = await axios(providerAxiosConfig).then((response) => response.data.data && response.data.data.results ? response.data.data.results : []).catch((e) => {
15461
+ console.error(e);
15462
+ setError(true);
15463
+ });
15464
+ setResults(imageRecords);
15465
+ setLoading(false);
15466
+ }
14980
15467
  };
14981
15468
  const onSelect = (img) => {
14982
15469
  setSelectedImage(img);
@@ -15009,25 +15496,26 @@ function ImageSelector({ member, onEditEnd }) {
15009
15496
  setError(false);
15010
15497
  setSelectedProvider(imageProviders[providerKey]);
15011
15498
  setSelectedImage(void 0);
15499
+ setResults([]);
15500
+ setSelectedPage(1);
15012
15501
  };
15013
15502
  useEffect(() => {
15014
15503
  const { innerHeight } = window;
15015
15504
  setScrollSize(innerHeight - 280);
15016
- onSearch();
15017
15505
  }, []);
15018
15506
  useEffect(() => {
15019
- setResults([]);
15020
15507
  if (!loading && selectedProvider.forceSearch) {
15021
15508
  onSearch();
15022
15509
  }
15023
- }, [selectedProvider]);
15510
+ }, [selectedPage, selectedProvider]);
15024
15511
  const noResults = results && results.length === 0 && !loading && selectedProvider.key !== "upload";
15512
+ const callToAction = results && results.length === 0 && !loading && selectedProvider.key === "upload";
15025
15513
  return /* @__PURE__ */ jsx(
15026
15514
  Drawer,
15027
15515
  {
15028
15516
  opened: true,
15029
15517
  onClose: onEditEnd,
15030
- title: `Edit image for ${initialPrompt} (${member.id}) `,
15518
+ title: `Image selection for ${initialPrompt} (${member.id}) `,
15031
15519
  padding: "lg",
15032
15520
  closeOnClickOutside: false,
15033
15521
  closeOnEscape: false,
@@ -15035,7 +15523,7 @@ function ImageSelector({ member, onEditEnd }) {
15035
15523
  size: "50%",
15036
15524
  lockScroll: true,
15037
15525
  withCloseButton: false,
15038
- children: /* @__PURE__ */ jsx("div", { style: { height: "100%" }, children: /* @__PURE__ */ jsxs(Stack, { children: [
15526
+ children: /* @__PURE__ */ jsx("div", { style: { height: "100%" }, children: /* @__PURE__ */ jsxs(Stack, { spacing: "sm", children: [
15039
15527
  /* @__PURE__ */ jsxs(Stack, { spacing: "xs", children: [
15040
15528
  /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, align: "flex-end", children: [
15041
15529
  selectedProvider.input === "text" && /* @__PURE__ */ jsx(
@@ -15044,15 +15532,18 @@ function ImageSelector({ member, onEditEnd }) {
15044
15532
  placeholder: "Search term",
15045
15533
  label: "Search term",
15046
15534
  value: prompt,
15047
- onChange: (e) => setPrompt(e.target.value)
15535
+ onChange: (e) => setPrompt(e.target.value),
15536
+ onKeyDown: getHotkeyHandler([
15537
+ ["Enter", () => onSearch(1)]
15538
+ ])
15048
15539
  }
15049
15540
  ),
15050
15541
  selectedProvider.input === "file" && /* @__PURE__ */ jsx(
15051
15542
  FileInput,
15052
15543
  {
15053
15544
  label: "Upload image",
15054
- placeholder: "Choose a PNG image from your computer",
15055
- accept: "image/png",
15545
+ placeholder: "Choose an image from your computer (png, jpg, jpeg, webp)",
15546
+ accept: "image/png,image/jpeg,image/jpg,image/webp",
15056
15547
  value: imageToUpload,
15057
15548
  onChange: (image) => {
15058
15549
  setSelectedImage(void 0);
@@ -15075,7 +15566,7 @@ function ImageSelector({ member, onEditEnd }) {
15075
15566
  {
15076
15567
  fullWidth: true,
15077
15568
  disabled: loading || !prompt || prompt === "",
15078
- onClick: onSearch,
15569
+ onClick: () => onSearch(1),
15079
15570
  leftIcon: /* @__PURE__ */ jsx(IconPlayerPlay, {}),
15080
15571
  children: "Search"
15081
15572
  }
@@ -15093,23 +15584,37 @@ function ImageSelector({ member, onEditEnd }) {
15093
15584
  )
15094
15585
  ] }),
15095
15586
  /* @__PURE__ */ jsx(Group, { mt: "xs", grow: true, children: /* @__PURE__ */ jsxs(ScrollArea, { offsetScrollbars: true, type: "always", style: { height: scrollSize }, children: [
15096
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 50 }),
15587
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5, overlayColor: "#fff" }),
15097
15588
  error && /* @__PURE__ */ jsx(Alert, { title: `${selectedProvider.title}`, color: "red", children: "Error, please try again." }),
15098
15589
  noResults && /* @__PURE__ */ jsx(Alert, { title: `${selectedProvider.title}`, color: "blue", children: "No results, for try another prompt or provider." }),
15099
- results && results.length > 0 && !loading && /* @__PURE__ */ jsx(SimpleGrid, { cols: 3, children: results.map((img) => /* @__PURE__ */ jsx(
15100
- Image,
15101
- {
15102
- radius: "md",
15103
- src: img.source,
15104
- style: {
15105
- cursor: "pointer",
15106
- borderRadius: 15,
15107
- border: selectedImage && selectedImage.id === img.id ? "5px solid black" : ""
15590
+ callToAction && /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconPhoto, { size: "1rem" }), title: "Welcome to image selector!", color: "blue", children: "Upload an image or select a provider." }),
15591
+ results && results.length > 0 && !loading && /* @__PURE__ */ jsxs(Fragment, { children: [
15592
+ /* @__PURE__ */ jsx(SimpleGrid, { cols: 3, children: results.map((img) => /* @__PURE__ */ jsx(
15593
+ Image,
15594
+ {
15595
+ alt: `${selectedProvider.title}-image-${img.id}`,
15596
+ radius: "md",
15597
+ src: img.source,
15598
+ style: {
15599
+ cursor: "pointer",
15600
+ borderRadius: 15,
15601
+ border: selectedImage && selectedImage.id === img.id ? "5px solid black" : ""
15602
+ },
15603
+ onClick: () => onSelect(img)
15108
15604
  },
15109
- onClick: () => onSelect(img)
15110
- },
15111
- img.id
15112
- )) })
15605
+ img.id
15606
+ )) }),
15607
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
15608
+ selectedProvider.pagination && /* @__PURE__ */ jsx(
15609
+ Button,
15610
+ {
15611
+ variant: "outline",
15612
+ fullWidth: true,
15613
+ onClick: () => setSelectedPage(selectedPage + 1),
15614
+ children: "Load more images"
15615
+ }
15616
+ )
15617
+ ] })
15113
15618
  ] }) }),
15114
15619
  /* @__PURE__ */ jsxs(Group, { mt: "xs", grow: true, style: { height: 45 }, children: [
15115
15620
  /* @__PURE__ */ jsx(
@@ -15137,24 +15642,6 @@ function ImageSelector({ member, onEditEnd }) {
15137
15642
  }
15138
15643
  var ImageSelector_default = ImageSelector;
15139
15644
 
15140
- // views/ImagePreview.tsx
15141
- init_esm_shims();
15142
- function ImagePreview3({
15143
- member,
15144
- height = "auto",
15145
- width = "100%",
15146
- size = "thumb",
15147
- forceRefreshTimestamp = false
15148
- }) {
15149
- let extraParam = "";
15150
- if (forceRefreshTimestamp) {
15151
- extraParam = `&t=${( new Date()).getTime()}`;
15152
- }
15153
- const imageUrl = member && member.image_id ? `/api/cms/member/image.png?member=${member.content_id}&size=${size}${extraParam}` : "https://placehold.jp/cccccc/ffffff/900x600.png?text=None";
15154
- return /* @__PURE__ */ jsx(Image, { height, width, radius: "md", src: imageUrl });
15155
- }
15156
- var ImagePreview_default = ImagePreview3;
15157
-
15158
15645
  // components/metadata/MemberForm.tsx
15159
15646
  init_SortableTable();
15160
15647
  function MemberForm({ memberId, onEditEnd }) {
@@ -15167,6 +15654,10 @@ function MemberForm({ memberId, onEditEnd }) {
15167
15654
  const [loading, setLoading] = useState(true);
15168
15655
  const [showImageSelector, setShowImageSelector] = useState(false);
15169
15656
  const [error, setError] = useState(false);
15657
+ const [activeTab, setActiveTab] = useState("member");
15658
+ const [loadingSearch, setLoadingSearch] = useState(false);
15659
+ const [membersSearch, setMembersSearch] = useState([]);
15660
+ const [selectedRecords, setSelectedRecords] = useState({});
15170
15661
  const mainForm = useForm();
15171
15662
  const localizedForms = locales4.reduce((acc, item) => {
15172
15663
  acc[item] = useForm({});
@@ -15223,6 +15714,34 @@ function MemberForm({ memberId, onEditEnd }) {
15223
15714
  }
15224
15715
  setLoading(false);
15225
15716
  };
15717
+ const fetchSearchMembers = async () => {
15718
+ if (member && member.contentByLocale) {
15719
+ const localizedName = member.contentByLocale.find((cl) => cl.locale === selectedLocale);
15720
+ if (localizedName) {
15721
+ setLoadingSearch(true);
15722
+ const searchParams = parseSearchMemberParams({
15723
+ q: localizedName.name,
15724
+ limit: "10",
15725
+ locale: selectedLocale,
15726
+ visible: "true",
15727
+ includes: "true",
15728
+ noImage: "false",
15729
+ format: "plain",
15730
+ all: "true"
15731
+ });
15732
+ dispatch(actions_exports.searchMember(searchParams)).then((resp) => {
15733
+ if (resp && resp.results) {
15734
+ const members = resp.results.filter((r) => r.content_id !== memberId);
15735
+ setMembersSearch(members);
15736
+ }
15737
+ setLoadingSearch(false);
15738
+ }).catch((e) => {
15739
+ console.error(e);
15740
+ setLoadingSearch(false);
15741
+ });
15742
+ }
15743
+ }
15744
+ };
15226
15745
  useEffect(() => {
15227
15746
  if (memberId) {
15228
15747
  fetchMemberData();
@@ -15230,6 +15749,11 @@ function MemberForm({ memberId, onEditEnd }) {
15230
15749
  setMember(null);
15231
15750
  }
15232
15751
  }, [memberId]);
15752
+ useEffect(() => {
15753
+ if (member) {
15754
+ fetchSearchMembers();
15755
+ }
15756
+ }, [member, selectedLocale]);
15233
15757
  const onImageSelectorClose = async (edited) => {
15234
15758
  if (edited) {
15235
15759
  fetchMemberData();
@@ -15268,12 +15792,30 @@ function MemberForm({ memberId, onEditEnd }) {
15268
15792
  } : null,
15269
15793
  image_id: member.image_id
15270
15794
  };
15271
- await axios.post("/api/cms/update/member", payload).then((resp) => {
15795
+ const updateMembersPromises = [
15796
+ axios.post("/api/cms/update/member", payload)
15797
+ ];
15798
+ const selectedRecordKeys = Object.keys(selectedRecords);
15799
+ if (selectedRecordKeys.length > 0) {
15800
+ selectedRecordKeys.forEach((sr) => {
15801
+ updateMembersPromises.push(
15802
+ axios.post("/api/cms/update/member", { content_id: membersSearch[sr].content_id, image_id: member.image_id })
15803
+ );
15804
+ });
15805
+ }
15806
+ Promise.all(updateMembersPromises).then(() => {
15272
15807
  onEditEnd();
15273
- return resp.data.data;
15808
+ }).catch((e) => {
15809
+ console.error(e);
15810
+ setError(true);
15274
15811
  });
15275
15812
  };
15276
15813
  const isValidLocalizedForm = Object.keys(localizedForms[selectedLocale].values).length > 0;
15814
+ const membersTableProps = {
15815
+ state: { rowSelection: selectedRecords },
15816
+ onRowSelectionChange: setSelectedRecords,
15817
+ enableRowSelection: (row) => member.image_id && row.original.image_id !== member.image_id
15818
+ };
15277
15819
  return /* @__PURE__ */ jsxs(Fragment, { children: [
15278
15820
  /* @__PURE__ */ jsx(
15279
15821
  Drawer,
@@ -15292,169 +15834,218 @@ function MemberForm({ memberId, onEditEnd }) {
15292
15834
  DrawerContentWithScroll,
15293
15835
  {
15294
15836
  content: /* @__PURE__ */ jsxs(Fragment, { children: [
15295
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 50 }),
15837
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5 }),
15296
15838
  error && /* @__PURE__ */ jsx(Alert, { title: "Member Form", color: "red", children: "Error, please try again." }),
15297
- member && !error && /* @__PURE__ */ jsxs(Stack, { justify: "space-between", children: [
15298
- /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15299
- /* @__PURE__ */ jsxs(Stack, { children: [
15300
- /* @__PURE__ */ jsx(ImagePreview_default, { member, forceRefreshTimestamp: true }),
15301
- /* @__PURE__ */ jsx(
15302
- Button,
15303
- {
15304
- variant: "outline",
15305
- disabled: loading,
15306
- leftIcon: /* @__PURE__ */ jsx(IconPolaroid, {}),
15307
- onClick: () => setShowImageSelector(true),
15308
- children: "Change image"
15309
- }
15310
- ),
15311
- member && member.image && /* @__PURE__ */ jsx(
15312
- Button,
15313
- {
15314
- variant: "outline",
15315
- disabled: loading,
15316
- leftIcon: /* @__PURE__ */ jsx(IconCircleMinus, {}),
15317
- onClick: () => clearImage(),
15318
- children: "Remove image"
15319
- }
15320
- ),
15321
- /* @__PURE__ */ jsx(Space, { h: "md" })
15839
+ member && !error && /* @__PURE__ */ jsxs(Tabs, { defaultValue: "member", value: activeTab, onTabChange: setActiveTab, children: [
15840
+ /* @__PURE__ */ jsxs(Tabs.List, { grow: true, children: [
15841
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "member", icon: /* @__PURE__ */ jsx(IconListCheck, {}), children: "Member" }),
15842
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "image", icon: /* @__PURE__ */ jsx(IconPhoto, {}), children: "Image" })
15843
+ ] }),
15844
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "member", py: "md", children: /* @__PURE__ */ jsxs(Stack, { justify: "space-between", children: [
15845
+ /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15846
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Original ID", ...mainForm.getInputProps("id") }),
15847
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Content ID", ...mainForm.getInputProps("content_id") })
15322
15848
  ] }),
15323
- /* @__PURE__ */ jsxs(Stack, { justify: "flex-start", children: [
15849
+ /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15324
15850
  /* @__PURE__ */ jsx(
15325
15851
  TextInput,
15326
15852
  {
15327
- disabled: !member || !member.image,
15328
- label: "Source",
15329
- ...imageForm.getInputProps("url")
15330
- }
15331
- ),
15332
- /* @__PURE__ */ jsx(
15333
- TextInput,
15334
- {
15335
- disabled: !member || !member.image,
15336
- label: "Author",
15337
- ...imageForm.getInputProps("author")
15338
- }
15339
- ),
15340
- /* @__PURE__ */ jsx(
15341
- TextInput,
15342
- {
15343
- disabled: !member || !member.image,
15344
- label: "License",
15345
- ...imageForm.getInputProps("license")
15853
+ mt: "xs",
15854
+ icon: "/",
15855
+ disabled: true,
15856
+ label: "Variant Slug",
15857
+ ...mainForm.getInputProps("variant_slug")
15346
15858
  }
15347
15859
  ),
15860
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", icon: "/", disabled: true, label: "Member Slug", ...mainForm.getInputProps("slug") })
15861
+ ] }),
15862
+ /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15863
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Report", ...mainForm.getInputProps("report_name") }),
15864
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Dimension", ...mainForm.getInputProps("dimension_name") }),
15865
+ /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Variant", ...mainForm.getInputProps("variant_name") })
15866
+ ] }),
15867
+ /* @__PURE__ */ jsxs(Group, { grow: true, children: [
15868
+ /* @__PURE__ */ jsxs(Box, { onClick: () => setActiveTab("image"), style: { cursor: "pointer" }, pos: "relative", children: [
15869
+ /* @__PURE__ */ jsx(Overlay, { opacity: 0, center: true, sx: {
15870
+ backdropFilter: "none",
15871
+ "& button": {
15872
+ display: "none"
15873
+ },
15874
+ "&:hover": {
15875
+ backdropFilter: "blur(0.2375rem)",
15876
+ "button": {
15877
+ display: "flex"
15878
+ }
15879
+ }
15880
+ }, children: /* @__PURE__ */ jsx(Button, { size: "xs", radius: "sm", variant: "filled", leftIcon: /* @__PURE__ */ jsx(IconPhoto, { size: "0.9rem" }), children: "Edit" }) }),
15881
+ /* @__PURE__ */ jsx(ImagePreview_default, { member, forceRefreshTimestamp: true })
15882
+ ] }),
15348
15883
  /* @__PURE__ */ jsx(
15349
- SegmentedControl,
15884
+ Input.Wrapper,
15350
15885
  {
15351
- disabled: !member || !member.image,
15352
- value: selectedLocale,
15353
- onChange: setSelectedLocale,
15354
- data: localesItems
15886
+ label: "Search relevance",
15887
+ description: "\n Relevance index to be used with search. Values from 0 (less relevant) to 1 (more relevant)\n ",
15888
+ children: /* @__PURE__ */ jsx(
15889
+ NumberInput,
15890
+ {
15891
+ disabled: !mainForm.values.visible,
15892
+ type: "number",
15893
+ precision: 4,
15894
+ step: 1e-4,
15895
+ removeTrailingZeros: true,
15896
+ min: 0,
15897
+ max: 1,
15898
+ decimalSeparator: ".",
15899
+ ...mainForm.getInputProps("zvalue")
15900
+ }
15901
+ )
15355
15902
  }
15356
15903
  ),
15357
15904
  /* @__PURE__ */ jsx(
15358
- TextInput,
15905
+ Checkbox,
15359
15906
  {
15360
- disabled: !member || !member.image,
15361
- label: "Alternative image text",
15362
- ...localizedImageForms[selectedLocale].getInputProps("meta")
15907
+ mt: "2.3rem",
15908
+ label: "Visible in search",
15909
+ ...mainForm.getInputProps("visible", { type: "checkbox" })
15363
15910
  }
15364
15911
  )
15365
- ] })
15366
- ] }),
15367
- /* @__PURE__ */ jsxs(Code, { block: true, children: [
15368
- "TO-DO apply same image also to some of these members? List of checkboxes",
15369
- /* @__PURE__ */ jsx("br", {}),
15370
- "(x) another member, similar name",
15371
- /* @__PURE__ */ jsx("br", {}),
15372
- "(x) another member, similar name",
15373
- /* @__PURE__ */ jsx("br", {})
15374
- ] }),
15375
- /* @__PURE__ */ jsx(Divider, { my: "sm" }),
15376
- /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15377
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Original ID", ...mainForm.getInputProps("id") }),
15378
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Content ID", ...mainForm.getInputProps("content_id") })
15379
- ] }),
15380
- /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15381
- /* @__PURE__ */ jsx(
15382
- TextInput,
15912
+ ] }),
15913
+ /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", grow: true, children: /* @__PURE__ */ jsx(
15914
+ SegmentedControl,
15383
15915
  {
15384
- mt: "xs",
15385
- icon: "/",
15386
- disabled: true,
15387
- label: "Variant Slug",
15388
- ...mainForm.getInputProps("variant_slug")
15916
+ value: selectedLocale,
15917
+ onChange: setSelectedLocale,
15918
+ data: localesItems
15389
15919
  }
15390
- ),
15391
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", icon: "/", disabled: true, label: "Member Slug", ...mainForm.getInputProps("slug") })
15392
- ] }),
15393
- /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15394
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Report", ...mainForm.getInputProps("report_name") }),
15395
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Dimension", ...mainForm.getInputProps("dimension_name") }),
15396
- /* @__PURE__ */ jsx(TextInput, { mt: "xs", disabled: true, label: "Variant", ...mainForm.getInputProps("variant_name") })
15397
- ] }),
15398
- /* @__PURE__ */ jsx(Group, { position: "apart", grow: true, children: /* @__PURE__ */ jsx(
15399
- Checkbox,
15400
- {
15401
- mt: "xs",
15402
- label: "Visible",
15403
- ...mainForm.getInputProps("visible", { type: "checkbox" })
15404
- }
15405
- ) }),
15406
- /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", grow: true, children: /* @__PURE__ */ jsx(
15407
- SegmentedControl,
15408
- {
15409
- value: selectedLocale,
15410
- onChange: setSelectedLocale,
15411
- data: localesItems
15412
- }
15413
- ) }),
15414
- !isValidLocalizedForm && /* @__PURE__ */ jsx(Alert, { title: "Unavailable locale", color: "blue", children: "This language was not ingested for the current member. Go to variant editor and provide the members there." }),
15415
- isValidLocalizedForm && /* @__PURE__ */ jsxs(Fragment, { children: [
15416
- /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", grow: true, children: /* @__PURE__ */ jsx(TextInput, { label: "Name", ...localizedForms[selectedLocale].getInputProps("name") }) }),
15417
- /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", align: "top", grow: true, children: /* @__PURE__ */ jsx(
15418
- MultiSelect,
15419
- {
15420
- label: "Keywords",
15421
- data: localizedForms[selectedLocale].values.keywords,
15422
- placeholder: "Enter keywords",
15423
- searchable: true,
15424
- creatable: true,
15425
- valueComponent: ({
15426
- value,
15427
- label,
15428
- image,
15429
- name
15430
- }) => /* @__PURE__ */ jsxs(
15431
- Badge,
15920
+ ) }),
15921
+ !isValidLocalizedForm && /* @__PURE__ */ jsx(Alert, { title: "Unavailable locale", color: "blue", children: "This language was not ingested for the current member. Go to variant editor and provide the members there." }),
15922
+ isValidLocalizedForm && /* @__PURE__ */ jsxs(Fragment, { children: [
15923
+ /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", grow: true, children: /* @__PURE__ */ jsx(TextInput, { label: "Name", ...localizedForms[selectedLocale].getInputProps("name") }) }),
15924
+ /* @__PURE__ */ jsx(Group, { mt: "xs", position: "apart", align: "top", grow: true, children: /* @__PURE__ */ jsx(
15925
+ MultiSelect,
15926
+ {
15927
+ label: "Keywords",
15928
+ data: localizedForms[selectedLocale].values.keywords,
15929
+ placeholder: "Enter keywords",
15930
+ searchable: true,
15931
+ creatable: true,
15932
+ valueComponent: ({
15933
+ value,
15934
+ label,
15935
+ image,
15936
+ name
15937
+ }) => /* @__PURE__ */ jsxs(
15938
+ Badge,
15939
+ {
15940
+ onClick: () => {
15941
+ const current = localizedForms[selectedLocale].values.keywords;
15942
+ localizedForms[selectedLocale].setFieldValue(
15943
+ "keywords",
15944
+ current.filter((k) => k !== label)
15945
+ );
15946
+ },
15947
+ children: [
15948
+ label,
15949
+ " ",
15950
+ "x"
15951
+ ]
15952
+ }
15953
+ ),
15954
+ getCreateLabel: (query) => `+ Create ${query}`,
15955
+ value: localizedForms[selectedLocale].values.keywords,
15956
+ onCreate: (query) => {
15957
+ const current = localizedForms[selectedLocale].values.keywords;
15958
+ localizedForms[selectedLocale].setFieldValue("keywords", [...current, query]);
15959
+ return query;
15960
+ }
15961
+ }
15962
+ ) }),
15963
+ /* @__PURE__ */ jsx(Input.Wrapper, { label: "Attributes", children: /* @__PURE__ */ jsx(SortableTable, { data: localizedForms[selectedLocale].values.attributes }) })
15964
+ ] })
15965
+ ] }) }),
15966
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "image", py: "md", children: /* @__PURE__ */ jsxs(Stack, { justify: "space-between", children: [
15967
+ /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
15968
+ /* @__PURE__ */ jsxs(Stack, { children: [
15969
+ /* @__PURE__ */ jsx(ImagePreview_default, { member, forceRefreshTimestamp: true }),
15970
+ /* @__PURE__ */ jsx(
15971
+ Button,
15432
15972
  {
15433
- onClick: () => {
15434
- const current = localizedForms[selectedLocale].values.keywords;
15435
- localizedForms[selectedLocale].setFieldValue(
15436
- "keywords",
15437
- current.filter((k) => k !== label)
15438
- );
15439
- },
15440
- children: [
15441
- label,
15442
- " ",
15443
- "x"
15444
- ]
15973
+ variant: "outline",
15974
+ disabled: loading,
15975
+ leftIcon: /* @__PURE__ */ jsx(IconPolaroid, {}),
15976
+ onClick: () => setShowImageSelector(true),
15977
+ children: "Change image"
15978
+ }
15979
+ ),
15980
+ member && member.image && /* @__PURE__ */ jsx(
15981
+ Button,
15982
+ {
15983
+ variant: "outline",
15984
+ disabled: loading,
15985
+ leftIcon: /* @__PURE__ */ jsx(IconCircleMinus, {}),
15986
+ onClick: () => clearImage(),
15987
+ children: "Remove image"
15988
+ }
15989
+ ),
15990
+ /* @__PURE__ */ jsx(Space, { h: "md" })
15991
+ ] }),
15992
+ /* @__PURE__ */ jsxs(Stack, { justify: "flex-start", children: [
15993
+ /* @__PURE__ */ jsx(
15994
+ TextInput,
15995
+ {
15996
+ disabled: !member || !member.image,
15997
+ label: "Source",
15998
+ ...imageForm.getInputProps("url")
15999
+ }
16000
+ ),
16001
+ /* @__PURE__ */ jsx(
16002
+ TextInput,
16003
+ {
16004
+ disabled: !member || !member.image,
16005
+ label: "Author",
16006
+ ...imageForm.getInputProps("author")
16007
+ }
16008
+ ),
16009
+ /* @__PURE__ */ jsx(
16010
+ TextInput,
16011
+ {
16012
+ disabled: !member || !member.image,
16013
+ label: "License",
16014
+ ...imageForm.getInputProps("license")
16015
+ }
16016
+ ),
16017
+ /* @__PURE__ */ jsx(
16018
+ SegmentedControl,
16019
+ {
16020
+ disabled: !member || !member.image,
16021
+ value: selectedLocale,
16022
+ onChange: setSelectedLocale,
16023
+ data: localesItems
15445
16024
  }
15446
16025
  ),
15447
- getCreateLabel: (query) => `+ Create ${query}`,
15448
- value: localizedForms[selectedLocale].values.keywords,
15449
- onCreate: (query) => {
15450
- const current = localizedForms[selectedLocale].values.keywords;
15451
- localizedForms[selectedLocale].setFieldValue("keywords", [...current, query]);
15452
- return query;
16026
+ /* @__PURE__ */ jsx(
16027
+ TextInput,
16028
+ {
16029
+ disabled: !member || !member.image,
16030
+ label: "Alternative image text",
16031
+ ...localizedImageForms[selectedLocale].getInputProps("meta")
16032
+ }
16033
+ )
16034
+ ] })
16035
+ ] }),
16036
+ loadingSearch && /* @__PURE__ */ jsx(Loader, {}),
16037
+ !loadingSearch && membersSearch.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
16038
+ /* @__PURE__ */ jsx(Text, { children: "Select the members you want to update with the same image." }),
16039
+ /* @__PURE__ */ jsx(
16040
+ MembersTable,
16041
+ {
16042
+ members: membersSearch,
16043
+ colsToRender: ["id", "report", "name", "slug", "image"],
16044
+ dataTableProps: membersTableProps
15453
16045
  }
15454
- }
15455
- ) }),
15456
- /* @__PURE__ */ jsx(Input.Wrapper, { label: "Attributes", children: /* @__PURE__ */ jsx(SortableTable, { data: localizedForms[selectedLocale].values.attributes }) })
15457
- ] })
16046
+ )
16047
+ ] })
16048
+ ] }) })
15458
16049
  ] })
15459
16050
  ] }),
15460
16051
  buttons: /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -15485,133 +16076,6 @@ function MemberForm({ memberId, onEditEnd }) {
15485
16076
  showImageSelector && /* @__PURE__ */ jsx(ImageSelector_default, { member, onEditEnd: onImageSelectorClose })
15486
16077
  ] });
15487
16078
  }
15488
-
15489
- // components/metadata/MembersTable.tsx
15490
- init_esm_shims();
15491
- init_store2();
15492
- function MembersTable({ members, onClickEdit, onSort }) {
15493
- const [sortStatus, setSortStatus] = useState();
15494
- const [records, setRecords] = useState([]);
15495
- useEffect(() => {
15496
- if (sortStatus) {
15497
- onSort(sortStatus);
15498
- }
15499
- }, [sortStatus]);
15500
- useEffect(() => {
15501
- setRecords(members);
15502
- }, [members]);
15503
- useEffect(() => {
15504
- setRecords(members);
15505
- }, []);
15506
- const localeDefault10 = useAppSelector((state) => state.status.localeDefault);
15507
- const cols = [
15508
- {
15509
- title: "",
15510
- accessor: "visible",
15511
- width: "10px",
15512
- render: ({ visible }) => /* @__PURE__ */ jsx(Fragment, { children: !visible ? /* @__PURE__ */ jsx(Tooltip, { label: "Visible: false", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconEyeOff, { size: 20 }) }) }) : /* @__PURE__ */ jsx("span", {}) })
15513
- },
15514
- {
15515
- title: "ID",
15516
- accessor: "id",
15517
- sortable: true,
15518
- textAlignment: "right"
15519
- },
15520
- {
15521
- title: "Report",
15522
- accessor: "report.name"
15523
- },
15524
- {
15525
- title: "Dimension",
15526
- accessor: "dimension.name"
15527
- },
15528
- {
15529
- title: "Variant",
15530
- accessor: "variant.name"
15531
- },
15532
- {
15533
- title: "Relevance",
15534
- sortable: true,
15535
- accessor: "zvalue"
15536
- },
15537
- {
15538
- title: "Slug",
15539
- accessor: "slug",
15540
- render: ({ slug, variant }) => /* @__PURE__ */ jsxs("span", { children: [
15541
- "/",
15542
- variant.slug,
15543
- "/",
15544
- slug
15545
- ] })
15546
- },
15547
- {
15548
- title: `Name ${localeDefault10.toUpperCase()}`,
15549
- sortable: true,
15550
- accessor: "name",
15551
- render: ({ contentByLocale }) => {
15552
- const defaultLocalized = contentByLocale.find((item) => item.locale === localeDefault10);
15553
- const othersLocalized = contentByLocale.filter((item) => item.locale !== localeDefault10);
15554
- const nameTooltipContent = othersLocalized.reduce((acc, item) => {
15555
- const extraName = `${item.locale.toUpperCase()}: ${item.name}`;
15556
- const newLine2 = acc !== "" ? "\n" : "";
15557
- return `${acc}${newLine2}${extraName}`;
15558
- }, "");
15559
- return /* @__PURE__ */ jsxs(Group, { children: [
15560
- /* @__PURE__ */ jsx("span", { children: defaultLocalized.name }),
15561
- othersLocalized.length > 0 && /* @__PURE__ */ jsx(Tooltip, { label: nameTooltipContent, children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", color: "pink", radius: "xl", children: [
15562
- "+",
15563
- othersLocalized.length
15564
- ] }) })
15565
- ] });
15566
- }
15567
- },
15568
- {
15569
- title: `Keywords ${localeDefault10.toUpperCase()}`,
15570
- accessor: "keywords",
15571
- render: ({ contentByLocale }) => {
15572
- const defaultLocalized = contentByLocale.find((item) => item.locale === localeDefault10);
15573
- const othersLocalized = contentByLocale.filter((item) => item.locale !== localeDefault10);
15574
- const keywords = (defaultLocalized.keywords ? defaultLocalized.keywords : []).map((k) => /* @__PURE__ */ jsx(Badge, { children: k }, k));
15575
- const keywordsTooltipContent = othersLocalized.reduce((acc, item) => {
15576
- const otherKeywords = item.keywords || [];
15577
- const extraKeywords = `${item.locale.toUpperCase()}: ${otherKeywords.length > 0 ? otherKeywords.join(",") : "None"}`;
15578
- const newLine2 = acc !== "" ? "\n" : "";
15579
- return `${acc}${newLine2}${extraKeywords}`;
15580
- }, "");
15581
- return /* @__PURE__ */ jsxs(Group, { children: [
15582
- /* @__PURE__ */ jsx("span", { children: keywords.length > 0 ? keywords : /* @__PURE__ */ jsx(Badge, { color: "gray", children: "None" }) }),
15583
- othersLocalized.length > 0 && /* @__PURE__ */ jsx(Tooltip, { label: keywordsTooltipContent, children: /* @__PURE__ */ jsxs(Avatar, { size: "sm", color: "pink", radius: "xl", children: [
15584
- "+",
15585
- othersLocalized.length
15586
- ] }) })
15587
- ] });
15588
- }
15589
- },
15590
- {
15591
- title: "Image",
15592
- accessor: "image",
15593
- render: (member) => /* @__PURE__ */ jsx(ImagePreview_default, { member, height: "50px" })
15594
- },
15595
- {
15596
- title: "",
15597
- accessor: "actions",
15598
- render: (member) => /* @__PURE__ */ jsx(ActionIcon, { onClick: () => onClickEdit(member), children: /* @__PURE__ */ jsx(IconPencil, { size: 20 }) }, "edit")
15599
- }
15600
- ];
15601
- return /* @__PURE__ */ jsx(
15602
- DataTable,
15603
- {
15604
- striped: true,
15605
- minHeight: 150,
15606
- records,
15607
- columns: cols,
15608
- sortStatus,
15609
- onSortStatusChange: (s) => setSortStatus(s),
15610
- idAccessor: "content_id",
15611
- withBorder: true
15612
- }
15613
- );
15614
- }
15615
16079
  function MetadataEditor() {
15616
16080
  const [editingId, setEditingId] = useState(null);
15617
16081
  const [results, setResults] = useState([]);
@@ -15622,7 +16086,9 @@ function MetadataEditor() {
15622
16086
  setInternalFilters(filters);
15623
16087
  };
15624
16088
  const onChangeSort = (sort) => {
15625
- setInternalSort(sort);
16089
+ if (sort && sort.length) {
16090
+ setInternalSort(sort[0]);
16091
+ }
15626
16092
  };
15627
16093
  const setEditMember = (member) => {
15628
16094
  setEditingId(member.content_id);
@@ -15645,8 +16111,8 @@ function MetadataEditor() {
15645
16111
  ...getParams,
15646
16112
  locale: "all",
15647
16113
  includes: true,
15648
- sort: internalSort ? internalSort.columnAccessor : "zvalue",
15649
- direction: internalSort ? internalSort.direction : "desc"
16114
+ sort: internalSort ? internalSort.id : "zvalue",
16115
+ direction: internalSort ? internalSort.desc ? "desc" : "asc" : "desc"
15650
16116
  }
15651
16117
  }
15652
16118
  ).then((response) => response.data && response.data.data && response.data.data.results ? response.data.data.results : []);
@@ -15663,7 +16129,7 @@ function MetadataEditor() {
15663
16129
  /* @__PURE__ */ jsx(FilterSidebar2, { onChange: onChangeFilters, loading })
15664
16130
  ] }),
15665
16131
  /* @__PURE__ */ jsxs(Grid.Col, { span: 10, style: { height: "100vh", position: "relative" }, children: [
15666
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 50 }),
16132
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5 }),
15667
16133
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
15668
16134
  /* @__PURE__ */ jsx(MembersTable, { members: results, onClickEdit: setEditMember, onSort: onChangeSort })
15669
16135
  ] })
@@ -15784,7 +16250,7 @@ function ReportPicker() {
15784
16250
  }, [ref.data, ref.error, ref.status, reportAccess]);
15785
16251
  return /* @__PURE__ */ jsxs(Container, { size: "xl", children: [
15786
16252
  /* @__PURE__ */ jsx("h1", { children: "Reports" }),
15787
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: createLoading, overlayBlur: 2, overlayOpacity: 50 }),
16253
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: createLoading, overlayBlur: 2, overlayOpacity: 0.5 }),
15788
16254
  content,
15789
16255
  /* @__PURE__ */ jsx(Space, { h: "xl", w: "xl" }),
15790
16256
  /* @__PURE__ */ jsx(
@@ -16175,7 +16641,7 @@ function UserForm({ userId, onEditEnd, roles }) {
16175
16641
  DrawerContentWithScroll,
16176
16642
  {
16177
16643
  content: /* @__PURE__ */ jsxs(Fragment, { children: [
16178
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 50 }),
16644
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5 }),
16179
16645
  error && /* @__PURE__ */ jsx(Alert, { title: "Member Form", color: "red", children: "Error, please try again." }),
16180
16646
  user && !error && /* @__PURE__ */ jsxs(Stack, { justify: "space-between", children: [
16181
16647
  /* @__PURE__ */ jsxs(Group, { position: "apart", grow: true, children: [
@@ -16270,50 +16736,44 @@ function UserForm({ userId, onEditEnd, roles }) {
16270
16736
 
16271
16737
  // components/users/UsersTable.tsx
16272
16738
  init_esm_shims();
16273
- init_store2();
16274
- function UsersTable({ response, onClickEdit, onSort, onPageChange }) {
16275
- const [sortStatus, setSortStatus] = useState();
16739
+ function UsersTable({ response, onClickEdit, onPageChange }) {
16276
16740
  const [records, setRecords] = useState([]);
16277
16741
  const [paginationStatus, setPaginationStatus] = useState({
16278
- start: 0,
16279
- limit: 1,
16280
- total: 0,
16281
- page: 0
16742
+ pageIndex: 0,
16743
+ pageSize: 10
16282
16744
  });
16745
+ const [totalResults, setTotalResults] = useState(0);
16283
16746
  useEffect(() => {
16284
- if (sortStatus) {
16285
- onSort(sortStatus);
16286
- }
16287
- }, [sortStatus]);
16747
+ onPageChange(paginationStatus.pageIndex + 1);
16748
+ }, [paginationStatus.pageIndex]);
16288
16749
  useEffect(() => {
16289
16750
  if (response) {
16290
16751
  setRecords(response.users);
16291
- setPaginationStatus({
16292
- start: response.start,
16293
- limit: response.limit,
16294
- total: response.total,
16295
- page: response.start / response.limit + 1
16296
- });
16752
+ setTotalResults(response.total);
16297
16753
  }
16298
16754
  }, [response]);
16299
16755
  useEffect(() => {
16300
16756
  setRecords(response);
16301
16757
  }, []);
16302
- useAppSelector((state) => state.status.localeDefault);
16303
16758
  const cols = [
16304
16759
  {
16305
- title: "",
16306
- accessor: "image",
16307
- width: 50,
16308
- render: (member) => /* @__PURE__ */ jsx(Avatar, { src: member.picture, alt: "it's me", radius: 20 })
16760
+ header: "",
16761
+ accessorKey: "image",
16762
+ Cell: ({ row }) => {
16763
+ return /* @__PURE__ */ jsx(Avatar, { src: row.original.picture, alt: `${row.original.name}`, radius: 20 });
16764
+ },
16765
+ size: 50,
16766
+ mantineTableBodyCellProps: {
16767
+ align: "center"
16768
+ }
16309
16769
  },
16310
16770
  {
16311
- title: "Name",
16312
- accessor: "name"
16771
+ header: "Name",
16772
+ accessorKey: "name"
16313
16773
  },
16314
16774
  {
16315
- title: "Email",
16316
- accessor: "email"
16775
+ header: "Email",
16776
+ accessorKey: "email"
16317
16777
  },
16318
16778
  /*{
16319
16779
  title: `Keywords ${localeDefault.toUpperCase()}`,
@@ -16348,26 +16808,52 @@ function UsersTable({ response, onClickEdit, onSort, onPageChange }) {
16348
16808
  },
16349
16809
  },*/
16350
16810
  {
16351
- title: "",
16352
- accessor: "actions",
16353
- render: (member) => /* @__PURE__ */ jsx(ActionIcon, { onClick: () => onClickEdit(member), children: /* @__PURE__ */ jsx(IconPencil, { size: 20 }) }, "edit")
16811
+ header: "Actions",
16812
+ accessorKey: "actions",
16813
+ Cell: ({ row }) => /* @__PURE__ */ jsx(ActionIcon, { onClick: () => onClickEdit(row.original), children: /* @__PURE__ */ jsx(IconPencil, { size: 20 }) }, "edit"),
16814
+ size: 100,
16815
+ mantineTableHeadCellProps: {
16816
+ align: "center"
16817
+ },
16818
+ mantineTableBodyCellProps: {
16819
+ align: "center"
16820
+ }
16354
16821
  }
16355
16822
  ];
16356
16823
  return /* @__PURE__ */ jsx(
16357
- DataTable,
16824
+ MantineReactTable,
16358
16825
  {
16359
- striped: true,
16360
- minHeight: 150,
16361
- records,
16362
16826
  columns: cols,
16363
- sortStatus,
16364
- onSortStatusChange: (s) => setSortStatus(s),
16365
- idAccessor: "email",
16366
- withBorder: true,
16367
- totalRecords: paginationStatus.total,
16368
- recordsPerPage: paginationStatus.limit,
16369
- page: paginationStatus.page,
16370
- onPageChange
16827
+ data: records,
16828
+ enableColumnActions: false,
16829
+ enablePagination: true,
16830
+ enableSorting: false,
16831
+ enableTopToolbar: false,
16832
+ initialState: {
16833
+ density: "xs"
16834
+ },
16835
+ layoutMode: "grid",
16836
+ mantinePaginationProps: {
16837
+ showRowsPerPage: false
16838
+ },
16839
+ mantineTableContainerProps: {
16840
+ sx: {
16841
+ minHeight: 150
16842
+ }
16843
+ },
16844
+ mantineTableProps: {
16845
+ striped: true
16846
+ },
16847
+ manualPagination: true,
16848
+ onPaginationChange: setPaginationStatus,
16849
+ paginationDisplayMode: "pages",
16850
+ rowCount: totalResults,
16851
+ state: {
16852
+ pagination: {
16853
+ pageIndex: paginationStatus.pageIndex,
16854
+ pageSize: paginationStatus.pageSize
16855
+ }
16856
+ }
16371
16857
  }
16372
16858
  );
16373
16859
  }
@@ -16377,14 +16863,10 @@ function UsersEditor() {
16377
16863
  const [roles, setRoles] = useState([]);
16378
16864
  const [loading, setLoading] = useState(true);
16379
16865
  const [internalFilters, setInternalFilters] = useState({ query: "" });
16380
- const [internalSort, setInternalSort] = useState();
16381
16866
  const dispatch = useAppDispatch();
16382
16867
  const onChangeFilters = (filters) => {
16383
16868
  setInternalFilters(filters);
16384
16869
  };
16385
- const onChangeSort = (sort) => {
16386
- setInternalSort(sort);
16387
- };
16388
16870
  const onPageChange = (page) => {
16389
16871
  setInternalFilters({
16390
16872
  ...internalFilters,
@@ -16421,7 +16903,7 @@ function UsersEditor() {
16421
16903
  }, [dispatch]);
16422
16904
  useEffect(() => {
16423
16905
  doSearch();
16424
- }, [internalFilters, internalSort]);
16906
+ }, [internalFilters]);
16425
16907
  return /* @__PURE__ */ jsxs(Container, { fluid: true, children: [
16426
16908
  /* @__PURE__ */ jsxs(Grid, { children: [
16427
16909
  /* @__PURE__ */ jsxs(Grid.Col, { span: 2, children: [
@@ -16429,14 +16911,13 @@ function UsersEditor() {
16429
16911
  /* @__PURE__ */ jsx(FilterSidebar3, { onChange: onChangeFilters, loading, roles })
16430
16912
  ] }),
16431
16913
  /* @__PURE__ */ jsxs(Grid.Col, { span: 10, style: { height: "100vh", position: "relative" }, children: [
16432
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 50 }),
16914
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5 }),
16433
16915
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
16434
16916
  /* @__PURE__ */ jsx(
16435
16917
  UsersTable,
16436
16918
  {
16437
16919
  response: results,
16438
16920
  onClickEdit: setEditUser,
16439
- onSort: onChangeSort,
16440
16921
  onPageChange
16441
16922
  }
16442
16923
  )