Files
klz-cables.com/.pnpm-store/v10/files/b7/bb75523aaac976991684c6ca833f4d7499ecb1136c52e27b5672e715638e5bd3b700dfb06774417fa748ecb2dbd49018d4945ce59b50ca6596d16a518b5d8c
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

350 lines
12 KiB
Plaintext

/* eslint-disable no-console */'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { TZDateMini as TZDate } from '@date-fns/tz/date/mini';
import { useModal } from '@faceless-ui/modal';
import { getTranslation } from '@payloadcms/translations';
import { endOfToday, isToday, startOfDay } from 'date-fns';
import { transpose } from 'date-fns/transpose';
import { formatAdminURL } from 'payload/shared';
import * as qs from 'qs-esm';
import React, { useCallback, useMemo } from 'react';
import { toast } from 'sonner';
import { FieldLabel } from '../../../fields/FieldLabel/index.js';
import { Radio } from '../../../fields/RadioGroup/Radio/index.js';
import { useConfig } from '../../../providers/Config/index.js';
import { useDocumentInfo } from '../../../providers/DocumentInfo/index.js';
import { useDocumentTitle } from '../../../providers/DocumentTitle/index.js';
import { useServerFunctions } from '../../../providers/ServerFunctions/index.js';
import { useTranslation } from '../../../providers/Translation/index.js';
import { requests } from '../../../utilities/api.js';
import { Banner } from '../../Banner/index.js';
import { DrawerCloseButton } from '../../BulkUpload/DrawerCloseButton/index.js';
import { Button } from '../../Button/index.js';
import { DatePickerField } from '../../DatePicker/index.js';
import { Drawer } from '../../Drawer/index.js';
import { Gutter } from '../../Gutter/index.js';
import './index.scss';
import { ReactSelect } from '../../ReactSelect/index.js';
import { ShimmerEffect } from '../../ShimmerEffect/index.js';
import { Table } from '../../Table/index.js';
import { TimezonePicker } from '../../TimezonePicker/index.js';
import { buildUpcomingColumns } from './buildUpcomingColumns.js';
const baseClass = 'schedule-publish';
const defaultLocaleOption = {
label: 'All',
value: 'all'
};
export const ScheduleDrawer = ({
slug,
defaultType,
schedulePublishConfig
}) => {
const {
toggleModal
} = useModal();
const {
config: {
admin: {
dateFormat,
timezones: {
defaultTimezone,
supportedTimezones
}
},
localization,
routes: {
api
}
}
} = useConfig();
const {
id,
collectionSlug,
globalSlug
} = useDocumentInfo();
const {
title
} = useDocumentTitle();
const {
i18n,
t
} = useTranslation();
const {
schedulePublish
} = useServerFunctions();
const [type, setType] = React.useState(defaultType || 'publish');
const [date, setDate] = React.useState();
const [timezone, setTimezone] = React.useState(defaultTimezone);
const [locale, setLocale] = React.useState(defaultLocaleOption);
const [processing, setProcessing] = React.useState(false);
const modalTitle = t('general:schedulePublishFor', {
title
});
const [upcoming, setUpcoming] = React.useState();
const [upcomingColumns, setUpcomingColumns] = React.useState();
const deleteHandlerRef = React.useRef(() => null);
// Get the user timezone so we can adjust the displayed value against it
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const localeOptions = React.useMemo(() => {
if (localization) {
const options = localization.locales.map(({
code,
label
}) => ({
label: getTranslation(label, i18n),
value: code
}));
options.unshift(defaultLocaleOption);
return options;
}
return [];
}, [localization, i18n]);
const fetchUpcoming = React.useCallback(async () => {
const query = {
sort: 'waitUntil',
where: {
and: [{
taskSlug: {
equals: 'schedulePublish'
}
}, {
waitUntil: {
greater_than: new Date()
}
}]
}
};
if (collectionSlug) {
query.where.and.push({
'input.doc.value': {
equals: String(id)
}
});
query.where.and.push({
'input.doc.relationTo': {
equals: collectionSlug
}
});
}
if (globalSlug) {
query.where.and.push({
'input.global': {
equals: globalSlug
}
});
}
const {
docs
} = await requests.post(formatAdminURL({
apiRoute: api,
path: `/payload-jobs`
}), {
body: qs.stringify(query),
headers: {
'Accept-Language': i18n.language,
'Content-Type': 'application/x-www-form-urlencoded',
'X-Payload-HTTP-Method-Override': 'GET'
}
}).then(res => res.json());
setUpcomingColumns(buildUpcomingColumns({
dateFormat,
// eslint-disable-next-line @typescript-eslint/no-misused-promises
deleteHandler: deleteHandlerRef.current,
docs,
i18n,
localization,
supportedTimezones,
t
}));
setUpcoming(docs);
}, [collectionSlug, globalSlug, api, i18n, dateFormat, localization, supportedTimezones, t, id]);
const deleteHandler = React.useCallback(async id_0 => {
try {
await schedulePublish({
deleteID: id_0
});
await fetchUpcoming();
toast.success(t('general:deletedSuccessfully'));
} catch (err) {
console.error(err);
toast.error(err.message);
}
}, [fetchUpcoming, schedulePublish, t]);
React.useEffect(() => {
deleteHandlerRef.current = deleteHandler;
}, [deleteHandler]);
const handleSave = React.useCallback(async () => {
if (!date) {
return toast.error(t('general:noDateSelected'));
}
setProcessing(true);
let localeToPublish;
if (typeof locale === 'object' && locale.value !== 'all' && type === 'publish') {
localeToPublish = locale.value;
}
try {
await schedulePublish({
type,
date,
doc: collectionSlug ? {
relationTo: collectionSlug,
value: String(id)
} : undefined,
global: globalSlug || undefined,
localeToPublish,
timezone
});
setDate(undefined);
toast.success(t('version:scheduledSuccessfully'));
void fetchUpcoming();
} catch (err_0) {
console.error(err_0);
toast.error(err_0.message);
}
setProcessing(false);
}, [date, locale, type, t, schedulePublish, collectionSlug, id, globalSlug, timezone, fetchUpcoming]);
const displayedValue = useMemo(() => {
if (timezone && userTimezone && date) {
// Create TZDate instances for the selected timezone and the user's timezone
// These instances allow us to transpose the date between timezones while keeping the same time value
const DateWithOriginalTz = TZDate.tz(timezone);
const DateWithUserTz = TZDate.tz(userTimezone);
const modifiedDate = new TZDate(date).withTimeZone(timezone);
// Transpose the date to the selected timezone
const dateWithTimezone = transpose(modifiedDate, DateWithOriginalTz);
// Transpose the date to the user's timezone - this is necessary because the react-datepicker component insists on displaying the date in the user's timezone
const dateWithUserTimezone = transpose(dateWithTimezone, DateWithUserTz);
return dateWithUserTimezone.toISOString();
}
return date;
}, [timezone, date, userTimezone]);
const onChangeDate = useCallback(incomingDate => {
if (timezone && incomingDate) {
// Create TZDate instances for the selected timezone
const tzDateWithUTC = TZDate.tz(timezone);
// Creates a TZDate instance for the user's timezone — this is default behaviour of TZDate as it wraps the Date constructor
const dateToUserTz = new TZDate(incomingDate);
// Transpose the date to the selected timezone
const dateWithTimezone_0 = transpose(dateToUserTz, tzDateWithUTC);
setDate(dateWithTimezone_0 || null);
} else {
setDate(incomingDate || null);
}
}, [setDate, timezone]);
React.useEffect(() => {
if (!upcoming) {
const fetchInitialUpcoming = async () => {
await fetchUpcoming();
};
void fetchInitialUpcoming();
}
}, [upcoming, fetchUpcoming]);
const minTime = useMemo(() => {
if (date && isToday(date)) {
return new Date();
}
return startOfDay(new Date());
}, [date]);
return /*#__PURE__*/_jsxs(Drawer, {
className: baseClass,
gutter: false,
Header: /*#__PURE__*/_jsxs("div", {
className: `${baseClass}__drawer-header`,
children: [/*#__PURE__*/_jsx("h2", {
title: modalTitle,
children: modalTitle
}), /*#__PURE__*/_jsx(DrawerCloseButton, {
onClick: () => toggleModal(slug)
})]
}),
slug: slug,
children: [/*#__PURE__*/_jsxs(Gutter, {
className: `${baseClass}__scheduler`,
children: [/*#__PURE__*/_jsx(FieldLabel, {
label: t('version:type'),
required: true
}), /*#__PURE__*/_jsxs("ul", {
className: `${baseClass}__type`,
children: [/*#__PURE__*/_jsx("li", {
children: /*#__PURE__*/_jsx(Radio, {
id: `${slug}-type`,
isSelected: type === 'publish',
onChange: () => setType('publish'),
option: {
label: t('version:publish'),
value: 'publish'
},
path: `${slug}-type`,
readOnly: processing
})
}), /*#__PURE__*/_jsx("li", {
children: /*#__PURE__*/_jsx(Radio, {
id: `${slug}-type`,
isSelected: type === 'unpublish',
onChange: () => setType('unpublish'),
option: {
label: t('version:unpublish'),
value: 'unpublish'
},
path: `${slug}-type`,
readOnly: processing
})
})]
}), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx(FieldLabel, {
label: t('general:time'),
path: 'time',
required: true
}), /*#__PURE__*/_jsx(DatePickerField, {
id: "time",
maxTime: endOfToday(),
minDate: new Date(),
minTime: minTime,
onChange: e => onChangeDate(e),
pickerAppearance: "dayAndTime",
readOnly: processing,
timeFormat: schedulePublishConfig?.timeFormat,
timeIntervals: schedulePublishConfig?.timeIntervals ?? 5,
value: displayedValue
}), supportedTimezones.length > 0 && /*#__PURE__*/_jsx(TimezonePicker, {
id: `timezone-picker`,
onChange: setTimezone,
options: supportedTimezones,
selectedTimezone: timezone
}), /*#__PURE__*/_jsx("br", {}), localeOptions.length > 0 && type === 'publish' && /*#__PURE__*/_jsxs(React.Fragment, {
children: [/*#__PURE__*/_jsx(FieldLabel, {
label: t('localization:localeToPublish')
}), /*#__PURE__*/_jsx(ReactSelect, {
onChange: e_0 => setLocale(e_0),
options: localeOptions,
value: locale
}), /*#__PURE__*/_jsx("br", {})]
}), /*#__PURE__*/_jsxs("div", {
className: `${baseClass}__actions`,
children: [/*#__PURE__*/_jsx(Button, {
buttonStyle: "primary",
disabled: processing,
id: "scheduled-publish-save",
onClick: handleSave,
type: "button",
children: t('general:save')
}), processing ? /*#__PURE__*/_jsx("span", {
children: t('general:saving')
}) : null]
})]
}), /*#__PURE__*/_jsxs(Gutter, {
className: `${baseClass}__upcoming`,
children: [/*#__PURE__*/_jsx("h4", {
children: t('general:upcomingEvents')
}), !upcoming && /*#__PURE__*/_jsx(ShimmerEffect, {}), upcoming?.length === 0 && /*#__PURE__*/_jsx(Banner, {
type: "info",
children: t('general:noUpcomingEventsScheduled')
}), upcoming?.length > 0 && /*#__PURE__*/_jsx(Table, {
appearance: "condensed",
columns: upcomingColumns,
data: upcoming
})]
})]
});
};
//# sourceMappingURL=index.js.map