Bump local twake-mui lockfile to 1.1.8.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Generated
+2490
-65
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ A highly reusable dialog component that supports both normal and expanded (fulls
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- ✅ **Two Modes**: Normal popup (570px) and expanded fullscreen mode
|
- ✅ **Two Modes**: Normal popup (570px) and expanded fullscreen mode
|
||||||
- ✅ **Preserves Header**: Expanded mode doesn't cover app header (90px default)
|
- ✅ **Preserves Header**: Expanded mode doesn't cover app header (70px default)
|
||||||
- ✅ **Clean Expanded View**: No backdrop/shadow in expanded mode for seamless integration
|
- ✅ **Clean Expanded View**: No backdrop/shadow in expanded mode for seamless integration
|
||||||
- ✅ **Instant Transition**: No animation when expanding for immediate feedback
|
- ✅ **Instant Transition**: No animation when expanding for immediate feedback
|
||||||
- ✅ **Back Navigation**: Expanded mode shows back arrow icon in header for easy collapse
|
- ✅ **Back Navigation**: Expanded mode shows back arrow icon in header for easy collapse
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import iconCamera from "@/static/images/icon-camera.svg";
|
|||||||
import {
|
import {
|
||||||
addVideoConferenceToDescription,
|
addVideoConferenceToDescription,
|
||||||
generateMeetingLink,
|
generateMeetingLink,
|
||||||
|
removeVideoConferenceFromDescription,
|
||||||
} from "@/utils/videoConferenceUtils";
|
} from "@/utils/videoConferenceUtils";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
@@ -186,10 +187,6 @@ export default function EventFormFields({
|
|||||||
const [hasClickedCalendarSection, setHasClickedCalendarSection] =
|
const [hasClickedCalendarSection, setHasClickedCalendarSection] =
|
||||||
React.useState(false);
|
React.useState(false);
|
||||||
|
|
||||||
// Track if user has clicked on video meeting section in normal mode
|
|
||||||
const [hasClickedVideoMeetingSection, setHasClickedVideoMeetingSection] =
|
|
||||||
React.useState(false);
|
|
||||||
|
|
||||||
// Reset hasEndDateChanged and hasClickedDateTimeSection when modal closes
|
// Reset hasEndDateChanged and hasClickedDateTimeSection when modal closes
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
@@ -197,7 +194,6 @@ export default function EventFormFields({
|
|||||||
setHasClickedDateTimeSection(false);
|
setHasClickedDateTimeSection(false);
|
||||||
setHasClickedLocationSection(false);
|
setHasClickedLocationSection(false);
|
||||||
setHasClickedCalendarSection(false);
|
setHasClickedCalendarSection(false);
|
||||||
setHasClickedVideoMeetingSection(false);
|
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
@@ -428,9 +424,6 @@ export default function EventFormFields({
|
|||||||
if (showMore) {
|
if (showMore) {
|
||||||
setShowDescription(true);
|
setShowDescription(true);
|
||||||
}
|
}
|
||||||
if (!showMore) {
|
|
||||||
setHasClickedVideoMeetingSection(true);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const [openToast, setOpenToast] = React.useState(false);
|
const [openToast, setOpenToast] = React.useState(false);
|
||||||
@@ -447,11 +440,7 @@ export default function EventFormFields({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteVideoConference = () => {
|
const handleDeleteVideoConference = () => {
|
||||||
const updatedDescription = description.replace(
|
setDescription(removeVideoConferenceFromDescription(description));
|
||||||
/\nVisio: https?:\/\/[^\s]+/,
|
|
||||||
""
|
|
||||||
);
|
|
||||||
setDescription(updatedDescription);
|
|
||||||
setHasVideoConference(false);
|
setHasVideoConference(false);
|
||||||
setMeetingLink(null);
|
setMeetingLink(null);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ interface ClickableFieldProps {
|
|||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
iconColor?: string;
|
iconColor?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ClickableField: React.FC<ClickableFieldProps> = ({
|
export const ClickableField: React.FC<ClickableFieldProps> = ({
|
||||||
@@ -16,12 +17,22 @@ export const ClickableField: React.FC<ClickableFieldProps> = ({
|
|||||||
onClick,
|
onClick,
|
||||||
iconColor,
|
iconColor,
|
||||||
children,
|
children,
|
||||||
|
ariaLabel,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label={ariaLabel ?? text}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
e.preventDefault();
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: children ? "flex-start" : "center",
|
alignItems: children ? "flex-start" : "center",
|
||||||
@@ -31,6 +42,10 @@ export const ClickableField: React.FC<ClickableFieldProps> = ({
|
|||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "action.hover",
|
backgroundColor: "action.hover",
|
||||||
},
|
},
|
||||||
|
"&:focus-visible": {
|
||||||
|
outline: `2px solid ${theme.palette.primary.main}`,
|
||||||
|
outlineOffset: "2px",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -65,9 +65,7 @@ export function renderAttendeeBadge(
|
|||||||
<Avatar {...stringAvatar(a.cn || a.cal_address)} />
|
<Avatar {...stringAvatar(a.cn || a.cal_address)} />
|
||||||
</Badge>
|
</Badge>
|
||||||
<Box style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
|
<Box style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
|
||||||
<Typography noWrap>
|
<Typography noWrap>{a.cn || a.cal_address}</Typography>
|
||||||
{a.cn || a.cal_address}
|
|
||||||
</Typography>
|
|
||||||
{isOrganizer && (
|
{isOrganizer && (
|
||||||
<Typography variant="caption" color="text.secondary">
|
<Typography variant="caption" color="text.secondary">
|
||||||
{t("event.organizer")}
|
{t("event.organizer")}
|
||||||
|
|||||||
@@ -197,9 +197,7 @@ export function Menubar({
|
|||||||
</div>
|
</div>
|
||||||
<div className="menu-items">
|
<div className="menu-items">
|
||||||
<div className="current-date-time">
|
<div className="current-date-time">
|
||||||
<p>
|
<p>{dateLabel}</p>
|
||||||
{dateLabel}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -232,7 +230,7 @@ export function Menubar({
|
|||||||
sx={{
|
sx={{
|
||||||
borderRadius: "12px",
|
borderRadius: "12px",
|
||||||
marginLeft: 1,
|
marginLeft: 1,
|
||||||
"& fieldset": { borderRadius: "12px" }
|
"& fieldset": { borderRadius: "12px" },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value="dayGridMonth">
|
<MenuItem value="dayGridMonth">
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
extractVideoConferenceFromDescription,
|
extractVideoConferenceFromDescription,
|
||||||
generateMeetingId,
|
generateMeetingId,
|
||||||
generateMeetingLink,
|
generateMeetingLink,
|
||||||
|
removeVideoConferenceFromDescription,
|
||||||
} from "../videoConferenceUtils";
|
} from "../videoConferenceUtils";
|
||||||
|
|
||||||
// Mock window object for Node.js environment
|
// Mock window object for Node.js environment
|
||||||
@@ -82,4 +83,39 @@ describe("videoConferenceUtils", () => {
|
|||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("removeVideoConferenceFromDescription", () => {
|
||||||
|
it("should return empty string when description is only the Visio line", () => {
|
||||||
|
const description = "Visio: https://meet.linagora.com/abc-defg-hij";
|
||||||
|
const result = removeVideoConferenceFromDescription(description);
|
||||||
|
expect(result).toBe("");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove Visio line when at end of description", () => {
|
||||||
|
const description =
|
||||||
|
"This is a meeting description.\nVisio: https://meet.linagora.com/abc-defg-hij";
|
||||||
|
const result = removeVideoConferenceFromDescription(description);
|
||||||
|
expect(result).toBe("This is a meeting description.");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove Visio line when in middle of description", () => {
|
||||||
|
const description =
|
||||||
|
"Line one\nVisio: https://meet.linagora.com/abc-defg-hij\nLine two";
|
||||||
|
const result = removeVideoConferenceFromDescription(description);
|
||||||
|
expect(result).toBe("Line one\nLine two");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should leave description unchanged when no Visio line present", () => {
|
||||||
|
const description = "Just a regular meeting description.";
|
||||||
|
const result = removeVideoConferenceFromDescription(description);
|
||||||
|
expect(result).toBe(description);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should remove Visio line when at start of description", () => {
|
||||||
|
const description =
|
||||||
|
"Visio: https://meet.linagora.com/abc-defg-hij\nRest of the text";
|
||||||
|
const result = removeVideoConferenceFromDescription(description);
|
||||||
|
expect(result).toBe("Rest of the text");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -59,3 +59,19 @@ export function extractVideoConferenceFromDescription(
|
|||||||
const match = description.match(/Visio:\s*(https?:\/\/[^\s]+)/);
|
const match = description.match(/Visio:\s*(https?:\/\/[^\s]+)/);
|
||||||
return match ? match[1] : null;
|
return match ? match[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VISIO_LINE_REGEX = /^Visio:\s*https?:\/\/\S+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the Visio video conference line from description.
|
||||||
|
* Finds and removes the line matching "Visio: <url>" regardless of position (start, middle, end).
|
||||||
|
* @param {string} description - Event description
|
||||||
|
* @returns {string} Description with the Visio line removed
|
||||||
|
*/
|
||||||
|
export function removeVideoConferenceFromDescription(
|
||||||
|
description: string
|
||||||
|
): string {
|
||||||
|
const lines = description.split("\n");
|
||||||
|
const filtered = lines.filter((line) => !VISIO_LINE_REGEX.test(line.trim()));
|
||||||
|
return filtered.join("\n").trimEnd();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user