Preserve meeting metadata when duplicating and fix switch alignment in RTL
Update executive meeting duplication to maintain `isExternal` and `rowColor` properties, and adjust switch component's RTL translation for correct alignment.
This commit is contained in:
@@ -2210,6 +2210,18 @@ router.post(
|
|||||||
isHighlighted: 0,
|
isHighlighted: 0,
|
||||||
notes: stripTagsToPlainTextOrNull(source.notes),
|
notes: stripTagsToPlainTextOrNull(source.notes),
|
||||||
attachments: source.attachments,
|
attachments: source.attachments,
|
||||||
|
// #678: Carry the external-meeting flag onto the copy. Omitting it
|
||||||
|
// silently reset duplicates/repeats to "internal" (default false),
|
||||||
|
// losing the red tint + no-auto-postpone behavior of the source.
|
||||||
|
isExternal: source.isExternal,
|
||||||
|
// Same class of bug: rowColor is a shared editorial signal about
|
||||||
|
// the meeting (urgent / VIP), and the merge overlay is user
|
||||||
|
// content — both should survive a duplicate. mergeText is
|
||||||
|
// re-sanitized like the other rich-text fields above.
|
||||||
|
rowColor: source.rowColor,
|
||||||
|
mergeStartColumn: source.mergeStartColumn,
|
||||||
|
mergeEndColumn: source.mergeEndColumn,
|
||||||
|
mergeText: source.mergeText ? sanitizeRichText(source.mergeText) : source.mergeText,
|
||||||
createdBy: userId,
|
createdBy: userId,
|
||||||
updatedBy: userId,
|
updatedBy: userId,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -409,6 +409,36 @@ test("Meetings: POST /duplicate clones a meeting onto another date", async () =>
|
|||||||
assert.ok(dayBody.meetings.some((m) => m.id === newRow.id));
|
assert.ok(dayBody.meetings.some((m) => m.id === newRow.id));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// #678: duplicating/repeating must preserve the external-meeting flag
|
||||||
|
// (and the shared row colour) instead of silently resetting the copy
|
||||||
|
// to a normal internal meeting.
|
||||||
|
test("Meetings: POST /duplicate preserves isExternal and rowColor on the copy", async () => {
|
||||||
|
const create = await api(adminCookie, "POST", "/api/executive-meetings", {
|
||||||
|
titleAr: "خارجي",
|
||||||
|
titleEn: "External",
|
||||||
|
meetingDate: today,
|
||||||
|
isExternal: true,
|
||||||
|
attendees: [],
|
||||||
|
});
|
||||||
|
assert.equal(create.status, 201);
|
||||||
|
const original = await create.json();
|
||||||
|
created.meetingIds.push(original.id);
|
||||||
|
assert.equal(original.isExternal, true, "source must be external");
|
||||||
|
assert.equal(original.rowColor, "red", "external source is force-tinted red");
|
||||||
|
|
||||||
|
const dup = await api(
|
||||||
|
adminCookie,
|
||||||
|
"POST",
|
||||||
|
`/api/executive-meetings/${original.id}/duplicate`,
|
||||||
|
{ targetDate: tomorrow },
|
||||||
|
);
|
||||||
|
assert.equal(dup.status, 201);
|
||||||
|
const copy = await dup.json();
|
||||||
|
created.meetingIds.push(copy.id);
|
||||||
|
assert.equal(copy.isExternal, true, "duplicate must stay external (#678)");
|
||||||
|
assert.equal(copy.rowColor, "red", "duplicate keeps the red row colour");
|
||||||
|
});
|
||||||
|
|
||||||
// #189: plain-text sanitization for location / meetingUrl / notes.
|
// #189: plain-text sanitization for location / meetingUrl / notes.
|
||||||
test("Sanitization: POST strips HTML from location, meetingUrl, and notes", async () => {
|
test("Sanitization: POST strips HTML from location, meetingUrl, and notes", async () => {
|
||||||
const create = await api(adminCookie, "POST", "/api/executive-meetings", {
|
const create = await api(adminCookie, "POST", "/api/executive-meetings", {
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ const Switch = React.forwardRef<
|
|||||||
>
|
>
|
||||||
<SwitchPrimitives.Thumb
|
<SwitchPrimitives.Thumb
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:ltr:translate-x-4 data-[state=checked]:rtl:-translate-x-4 data-[state=unchecked]:ltr:translate-x-0 data-[state=unchecked]:rtl:translate-x-4"
|
// #682: in RTL the flex container already places the resting
|
||||||
|
// (unchecked) thumb at the track's start edge, so unchecked must
|
||||||
|
// be translate-x-0 in BOTH directions. The old rtl:translate-x-4
|
||||||
|
// pushed the resting thumb sideways, making OFF look like ON in
|
||||||
|
// Arabic. Checked travel: +x in LTR, -x in RTL.
|
||||||
|
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0 data-[state=checked]:ltr:translate-x-4 data-[state=checked]:rtl:-translate-x-4"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SwitchPrimitives.Root>
|
</SwitchPrimitives.Root>
|
||||||
|
|||||||
Reference in New Issue
Block a user