Color picker rework (#232)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2025-10-24 01:20:56 +02:00
committed by GitHub
parent 8681e88390
commit 34363562cc
23 changed files with 504 additions and 183 deletions
+8 -5
View File
@@ -34,7 +34,7 @@ export async function getCalendar(
export async function postCalendar(
userId: string,
calId: string,
color: string,
color: Record<string, string>,
name: string,
desc: string
) {
@@ -67,7 +67,10 @@ export async function addSharedCalendar(
"calendarserver:source": {
acl: cal.cal.acl,
calendarHomeId: cal.cal.id,
color: cal.cal["apple:color"],
color: {
light: cal.cal["apple:color"],
dark: cal.cal["X-TWAKE-Dark-theme-color"],
},
description: cal.cal["caldav:description"],
href: cal.cal._links.self.href,
id: cal.cal.id,
@@ -81,7 +84,7 @@ export async function addSharedCalendar(
export async function proppatchCalendar(
calLink: string,
patch: { name: string; desc: string; color: string }
patch: { name: string; desc: string; color: Record<string, string> }
) {
const body: Record<string, string> = {};
if (patch.name) {
@@ -90,8 +93,8 @@ export async function proppatchCalendar(
if (patch.desc) {
body["caldav:description"] = patch.desc;
}
if (patch.color) {
body["apple:color"] = patch.color;
if (patch.color.light) {
body["apple:color"] = patch.color.light;
}
const response = await api(`dav${calLink}`, {
method: "PROPPATCH",
+42 -14
View File
@@ -53,7 +53,10 @@ export const getCalendarsListAsync = createAsyncThunk<
const id = source.replace("/calendars/", "").replace(".json", "");
const visibility = getCalendarVisibility(cal["acl"]);
const ownerData: any = await getUserDetails(id.split("/")[0]);
const color = cal["apple:color"];
const color = {
light: cal["apple:color"] ?? "#006BD8",
dark: cal["X-TWAKE-Dark-theme-color"] ?? "#FFF",
};
importedCalendars[id] = {
id,
name,
@@ -106,7 +109,10 @@ export const getTempCalendarsListAsync = createAsyncThunk<
ownerEmails: ownerData.emails,
description,
delegated,
color: tempUser.color ?? "#a8a8a8ff",
color: {
light: tempUser.color?.light ?? "#a8a8a8ff",
dark: tempUser.color?.dark ?? "#a8a8a8ff",
},
visibility,
events: {},
};
@@ -157,7 +163,7 @@ export const putEventAsync = createAsyncThunk<
return vevents.map((vevent: any[]) => {
return parseCalendarEvent(
vevent[1],
cal.color ?? "",
cal.color ?? {},
cal.id,
eventURL,
valarm
@@ -187,12 +193,12 @@ export const patchCalendarAsync = createAsyncThunk<
{
calId: string;
calLink: string;
patch: { name: string; desc: string; color: string };
patch: { name: string; desc: string; color: Record<string, string> };
}, // Return type
{
calId: string;
calLink: string;
patch: { name: string; desc: string; color: string };
patch: { name: string; desc: string; color: Record<string, string> };
} // Arg type
>("calendars/patchCalendar", async ({ calId, calLink, patch }) => {
await proppatchCalendar(calLink, patch);
@@ -238,7 +244,7 @@ export const moveEventAsync = createAsyncThunk<
const vevents = eventdata.data[2] as any[][];
const eventURL = eventdata._links.self.href;
return vevents.map((vevent: any[]) => {
return parseCalendarEvent(vevent[1], cal.color ?? "", cal.id, eventURL);
return parseCalendarEvent(vevent[1], cal.color ?? {}, cal.id, eventURL);
});
}
);
@@ -304,13 +310,19 @@ export const createCalendarAsync = createAsyncThunk<
{
userId: string;
calId: string;
color: string;
color: Record<string, string>;
name: string;
desc: string;
owner: string;
ownerEmails: string[];
}, // Return type
{ userId: string; calId: string; color: string; name: string; desc: string } // Arg type
{
userId: string;
calId: string;
color: Record<string, string>;
name: string;
desc: string;
} // Arg type
>("calendars/createCalendar", async ({ userId, calId, color, name, desc }) => {
await postCalendar(userId, calId, color, name, desc);
const ownerData: any = await getUserDetails(userId.split("/")[0]);
@@ -331,7 +343,7 @@ export const createCalendarAsync = createAsyncThunk<
export const addSharedCalendarAsync = createAsyncThunk<
{
calId: string;
color: string;
color: Record<string, string>;
link: string;
name: string;
desc: string;
@@ -352,7 +364,10 @@ export const addSharedCalendarAsync = createAsyncThunk<
calId: cal.cal._links.self.href
.replace("/calendars/", "")
.replace(".json", ""),
color: cal.cal["apple:color"],
color: {
light: cal.cal["apple:color"],
dark: "#000",
},
link: `/calendars/${userId}/${calId}.json`,
desc: cal.cal["caldav:description"],
name: cal.cal["dav:name"],
@@ -388,12 +403,15 @@ const CalendarSlice = createSlice({
timeZone: string;
},
reducers: {
createCalendar: (state, action: PayloadAction<Record<string, string>>) => {
createCalendar: (
state,
action: PayloadAction<Record<string, string | Record<string, string>>>
) => {
const id = Date.now().toString(36);
state.list[id] = {} as Calendars;
state.list[id].name = action.payload.name;
state.list[id].color = action.payload.color;
state.list[id].description = action.payload.description;
state.list[id].name = action.payload.name as string;
state.list[id].color = action.payload.color as Record<string, string>;
state.list[id].description = action.payload.description as string;
state.list[id].events = {};
},
addEvent: (
@@ -450,6 +468,15 @@ const CalendarSlice = createSlice({
if (!state.list[action.payload]) return;
state.list[action.payload].lastCacheCleared = Date.now();
},
updateCalColor: (
state,
action: PayloadAction<{
id: string;
color: { light: string; dark: string };
}>
) => {
state.list[action.payload.id].color = action.payload.color;
},
},
extraReducers: (builder) => {
builder
@@ -719,5 +746,6 @@ export const {
emptyEventsCal,
setTimeZone,
clearFetchCache,
updateCalColor,
} = CalendarSlice.actions;
export default CalendarSlice.reducer;
+1 -1
View File
@@ -6,7 +6,7 @@ export interface Calendars {
name: string;
delegated?: boolean;
prodid?: string;
color?: string;
color?: Record<string, string>;
ownerEmails?: string[];
owner: string;
description?: string;
+1 -1
View File
@@ -36,7 +36,7 @@ export async function getEvent(event: CalendarEvent, isMaster?: boolean) {
const eventjson = parseCalendarEvent(
targetVevent[1],
event.color ?? "",
event.color ?? {},
event.calId,
event.URL
);
+4 -2
View File
@@ -48,6 +48,7 @@ import { userAttendee } from "../User/userDataTypes";
import { getEvent } from "./EventApi";
import { formatLocalDateTime } from "../../components/Event/EventFormFields";
import { CalendarEvent, RepetitionObject } from "./EventsTypes";
import { light } from "@mui/material/styles/createPalette";
export default function EventDisplayModal({
eventId,
@@ -224,7 +225,8 @@ export default function EventDisplayModal({
<Typography variant="body2">
<CircleIcon
style={{
color: userPersonnalCalendars[index].color ?? "#3788D8",
color:
userPersonnalCalendars[index].color?.light ?? "#3788D8",
width: 12,
height: 12,
}}
@@ -238,7 +240,7 @@ export default function EventDisplayModal({
<Typography variant="body2">
<CircleIcon
style={{
color: calendars[index].color ?? "#3788D8",
color: calendars[index].color?.light ?? "#3788D8",
width: 12,
height: 12,
}}
+1 -1
View File
@@ -577,7 +577,7 @@ export default function EventPreviewModal({
<CalendarTodayIcon style={{ fontSize: 16 }} />
<CircleIcon
style={{
color: calendar.color ?? "#3788D8",
color: calendar.color?.light ?? "#3788D8",
width: 12,
height: 12,
}}
+1 -1
View File
@@ -17,7 +17,7 @@ export interface CalendarEvent {
attendee: userAttendee[];
stamp?: string;
sequence?: Number;
color?: string;
color?: Record<string, string>;
allday?: boolean;
error?: string;
status?: string;
+2 -2
View File
@@ -1,5 +1,5 @@
import { userAttendee } from "../User/userDataTypes";
import { AlarmObject, CalendarEvent } from "./EventsTypes";
import { AlarmObject, CalendarEvent, RepetitionObject } from "./EventsTypes";
import ICAL from "ical.js";
import { TIMEZONES } from "../../utils/timezone-data";
import moment from "moment";
@@ -7,7 +7,7 @@ type RawEntry = [string, Record<string, string>, string, any];
export function parseCalendarEvent(
data: RawEntry[],
color: string,
color: Record<string, string>,
calendarid: string,
eventURL: string,
valarm?: RawEntry[]