[#106] added prettier check to jenkins and prettified files (#109)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2025-09-12 11:05:52 +02:00
committed by GitHub
parent 3b87965bed
commit d76775c7d2
16 changed files with 108 additions and 84 deletions
Vendored
+5
View File
@@ -26,6 +26,11 @@ pipeline {
sh 'npm run test'
}
}
stage('Check Formatting') {
steps {
sh 'npx prettier --check .'
}
}
stage('Deploy docker images') {
when {
anyOf {
+17 -4
View File
@@ -8,11 +8,20 @@ This project aims at service a Single Page Application allowing a user to intera
This frontend-only application will interact with:
- [esn-sabre](https://github.com/linagora/esn-sabre/) CalDAV + CardDAV server, tailor made for LINAGORA needs.
- [Twake Calendar side service](https://github.com/linagora/twake-calendar-side-service) that delivers additional backend features for Sabre.
- [esn-sabre](https://github.com/linagora/esn-sabre/) CalDAV + CardDAV server, tailor made for LINAGORA needs.
- [Twake Calendar side service](https://github.com/linagora/twake-calendar-side-service) that delivers additional backend features for Sabre.
It is meant as a drop in replacement of [esn-frontend-calendar](https://github.com/linagora/esn-frontend-calendar).
## Contributing
### Formating
We use [Prettier](https://prettier.io/) to keep code style consistent.
A `.prettierrc` file is already included in the repo, so formatting rules are predefined.
Before committing, make sure you format your files either using your IDE Prettier extension or Prettier CLI.
## Running it
Requirement: node 24+
@@ -77,7 +86,7 @@ And then visit [https://localhost:5000](https://localhost:5000).
### App grid
An applist is configurable in the public folder to setup the grid of app accessible within Twake Calendar.
An applist is configurable in the public folder to setup the grid of app accessible within Twake Calendar.
Each app has three fields:
@@ -89,7 +98,11 @@ Example:
```js
var appList = [
{ name: "My App", icon: "https://myapp.com/myapp.png", link: "https://myapp.com" },
{
name: "My App",
icon: "https://myapp.com/myapp.png",
link: "https://myapp.com",
},
];
```
@@ -111,7 +111,7 @@ describe("CalendarApp integration", () => {
openpaasId: "667037022b752d0026472254",
},
tokens: {
accessToken: "token"
accessToken: "token",
},
},
calendars: {
@@ -133,14 +133,16 @@ describe("CalendarApp integration", () => {
cn: "Alice",
cal_address: "alice@example.com",
},
attendee: [{
cn: "Alice",
partstat: "ACCEPTED",
rsvp: "TRUE",
role: "REQ-PARTICIPANT",
cutype: "INDIVIDUAL",
cal_address: "alice@example.com",
}, ],
attendee: [
{
cn: "Alice",
partstat: "ACCEPTED",
rsvp: "TRUE",
role: "REQ-PARTICIPANT",
cutype: "INDIVIDUAL",
cal_address: "alice@example.com",
},
],
...eventProps,
},
},
+21 -20
View File
@@ -57,33 +57,34 @@ describe("MiniCalendar", () => {
});
it.each([
{ today: new Date(2025, 8, 1), label: "Monday 1 Sept 2025" },
{ today: new Date(2025, 8, 3), label: "Wednesday 3 Sept 2025" },
{ today: new Date(2025, 8, 7), label: "Sunday 7 Sept 2025" },
{ today: new Date(2025, 8, 1), label: "Monday 1 Sept 2025" },
{ today: new Date(2025, 8, 3), label: "Wednesday 3 Sept 2025" },
{ today: new Date(2025, 8, 7), label: "Sunday 7 Sept 2025" },
])(
"renders mini calendar with the week in gray (except for today) when today is $label",
({ today }) => {
jest.useFakeTimers();
jest.setSystemTime(today);
"renders mini calendar with the week in gray (except for today) when today is $label",
({ today }) => {
jest.useFakeTimers();
jest.setSystemTime(today);
renderCalendar();
renderCalendar();
const monday = new Date(2025, 8, 1); // Monday Sept 1
const monday = new Date(2025, 8, 1); // Monday Sept 1
for (let i = 0; i < 7; i++) {
const date = new Date(monday);
date.setDate(monday.getDate() + i);
const dateTestId = `date-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
const tile = screen.getByTestId(dateTestId);
for (let i = 0; i < 7; i++) {
const date = new Date(monday);
date.setDate(monday.getDate() + i);
const dateTestId = `date-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
if (date.getTime() !== today.setHours(0, 0, 0, 0)) {
expect(tile?.parentElement).toHaveClass("selectedWeek");
const tile = screen.getByTestId(dateTestId);
if (date.getTime() !== today.setHours(0, 0, 0, 0)) {
expect(tile?.parentElement).toHaveClass("selectedWeek");
}
}
}
jest.useRealTimers();
});
jest.useRealTimers();
}
);
it("renders mini calendar with the day in gray (except for today) when full calendar in day view", async () => {
renderCalendar();
@@ -95,15 +95,13 @@ describe("Event Preview Display", () => {
};
it("renders correctly event data", () => {
jest
.spyOn(Date.prototype, "toLocaleString")
.mockImplementation(function (
this: Date,
locales?: Intl.LocalesArgument,
options?: Intl.DateTimeFormatOptions | undefined
): string {
return RealDateToLocaleString.call(this, "en-UK", options);
});
jest.spyOn(Date.prototype, "toLocaleString").mockImplementation(function (
this: Date,
locales?: Intl.LocalesArgument,
options?: Intl.DateTimeFormatOptions | undefined
): string {
return RealDateToLocaleString.call(this, "en-UK", options);
});
renderWithProviders(
<EventPreviewModal
anchorPosition={{ top: 0, left: 0 }}
+3 -3
View File
@@ -1,6 +1,6 @@
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
['@babel/preset-react', { runtime: 'automatic', importSource: 'preact' }],
["@babel/preset-env", { targets: { node: "current" } }],
["@babel/preset-react", { runtime: "automatic", importSource: "preact" }],
],
};
};
+1 -1
View File
@@ -6,4 +6,4 @@ var SSO_RESPONSE_TYPE = "code";
var SSO_CODE_CHALLENGE_METHOD = "S256";
var SSO_POST_LOGOUT_REDIRECT = "http://example.com?logout=1";
var CALENDAR_BASE_URL = "https://calendar.example.com";
var MAIL_SPA_URL = "https://mail.example.com"
var MAIL_SPA_URL = "https://mail.example.com";
+1 -1
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
+8 -2
View File
@@ -1,5 +1,11 @@
declare namespace Intl {
type Key = 'calendar' | 'collation' | 'currency' | 'numberingSystem' | 'timeZone' | 'unit';
type Key =
| "calendar"
| "collation"
| "currency"
| "numberingSystem"
| "timeZone"
| "unit";
function supportedValuesOf(input: Key): string[];
}
}
+4 -4
View File
@@ -1,5 +1,5 @@
import { useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
import { useDispatch, useSelector } from "react-redux";
import type { RootState, AppDispatch } from "./store";
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppDispatch = useDispatch.withTypes<AppDispatch>();
export const useAppSelector = useSelector.withTypes<RootState>();
+3 -1
View File
@@ -133,7 +133,9 @@ main {
/* selected day hover */
.react-calendar__tile {
transition: background-color 0.3s ease, color 0.3s ease;
transition:
background-color 0.3s ease,
color 0.3s ease;
border: none;
background-color: white;
width: 12px;
+16 -7
View File
@@ -31,13 +31,13 @@ import { createSelector } from "@reduxjs/toolkit";
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
import ClearIcon from "@mui/icons-material/Clear";
import AccessTimeIcon from "@mui/icons-material/AccessTime";
import LockIcon from '@mui/icons-material/Lock';
import LockIcon from "@mui/icons-material/Lock";
import { userAttendee } from "../../features/User/userDataTypes";
const computeStartOfTheWeek = (date: Date): Date => {
const startOfWeek = new Date(date);
startOfWeek.setDate(date.getDate() - ((date.getDay() + 6) % 7)); // Monday
startOfWeek.setHours(0, 0, 0, 0);
startOfWeek.setHours(0, 0, 0, 0);
return startOfWeek;
};
@@ -204,7 +204,6 @@ export default function CalendarApp() {
calendarRef.current?.view.type === "timeGridWeek" ||
calendarRef.current?.view.type === undefined
) {
const startOfWeek = computeStartOfTheWeek(selected);
const endOfWeek = new Date(startOfWeek);
@@ -430,7 +429,9 @@ export default function CalendarApp() {
if (!calendars[arg.event._def.extendedProps.calId]) return;
const attendees = event._def.extendedProps.attendee || [];
const isPrivate = event._def.extendedProps.class === "PRIVATE" || event._def.extendedProps.class === "CONFIDENTIAL";
const isPrivate =
event._def.extendedProps.class === "PRIVATE" ||
event._def.extendedProps.class === "CONFIDENTIAL";
let Icon = null;
let titleStyle: React.CSSProperties = {};
const ownerEmails = new Set(
@@ -461,9 +462,17 @@ export default function CalendarApp() {
}
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
{isPrivate && <LockIcon data-testid="lock-icon" fontSize="small" style={{ marginRight: '4px' }} />}
{Icon && <Icon fontSize="small" style={{ marginRight: '4px' }}/>}
<div style={{ display: "flex", alignItems: "center" }}>
{isPrivate && (
<LockIcon
data-testid="lock-icon"
fontSize="small"
style={{ marginRight: "4px" }}
/>
)}
{Icon && (
<Icon fontSize="small" style={{ marginRight: "4px" }} />
)}
<span style={titleStyle}>{event.title}</span>
</div>
);
+5 -2
View File
@@ -28,7 +28,6 @@ function CalendarPopover({
const [timeZone, setTimeZone] = useState("");
const timezones = Intl.supportedValuesOf?.("timeZone") ?? [];
const handleSave = () => {
dispatch(createCalendar({ name, description, color }));
onClose({}, "backdropClick");
@@ -64,7 +63,11 @@ function CalendarPopover({
}}
>
<Box p={2}>
<Typography variant="h6" gutterBottom style={{backgroundColor:color}}>
<Typography
variant="h6"
gutterBottom
style={{ backgroundColor: color }}
>
Create a Calendar
</Typography>
<TextField
+1 -1
View File
@@ -58,7 +58,7 @@ export function parseCalendarEvent(
case "organizer":
event.organizer = {
cn: params?.cn ?? "",
cal_address: value.replace(/^mailto:/, ""),
cal_address: value?.replace(/^mailto:/, ""),
};
break;
case "attendee":
+5 -5
View File
@@ -1,13 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
"Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
font-family:
source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
}
-15
View File
@@ -1,15 +0,0 @@
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;