Skip to content

Commit

Permalink
Add faircalendar list view, calendar view becomes lazy, reduce CLS an…
Browse files Browse the repository at this point in the history
…d FLOUC
  • Loading branch information
florimondmanca committed Dec 29, 2023
1 parent be1657c commit 3db62b7
Show file tree
Hide file tree
Showing 39 changed files with 380 additions and 193 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"_esbuild": "esbuild src/assets/main.js src/assets/faircalendar.js --bundle --splitting --outdir=dist/public --format=esm",
"_esbuild": "esbuild src/assets/main.js --bundle --splitting --outdir=dist/public --format=esm",
"assets:build": "npm run _esbuild -- --minify",
"assets:watch": "npm run _esbuild -- --watch",
"format": "prettier --write \"src/**/*.ts\" \"src/assets/**/*\" \"e2e/**/*.js\"",
Expand Down
1 change: 1 addition & 0 deletions src/Application/IDateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { MonthDate } from './Common/MonthDate';
export interface IDateUtils {
format(date: Date, format: string): string;
getDaysInMonth(date: Date): number;
getWeekDaysOfMonth(date: Date): Date[];
isWeekend(date: Date): boolean;
getCurrentDate(): Date;
getCurrentDateToISOString(): string;
Expand Down
14 changes: 13 additions & 1 deletion src/Infrastructure/Adapter/DateUtilsAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
isWeekend as fnsIsWeekend,
getDaysInMonth as fnsGetDaysInMonth,
eachDayOfInterval,
addDays
addDays,
isWeekend
} from 'date-fns';
import { MonthDate } from 'src/Application/Common/MonthDate';
import { IDateUtils } from 'src/Application/IDateUtils';
Expand Down Expand Up @@ -55,6 +56,17 @@ export class DateUtilsAdapter implements IDateUtils {
return fnsGetDaysInMonth(date);
}

public getWeekDaysOfMonth(date: Date): Date[] {
return eachDayOfInterval({
start: new Date(date.getFullYear(), date.getUTCMonth(), 1),
end: new Date(
date.getFullYear(),
date.getUTCMonth(),
this.getDaysInMonth(date)
)
}).filter(day => !isWeekend(day));
}

public isWeekend(date: Date): boolean {
return fnsIsWeekend(date);
}
Expand Down
11 changes: 11 additions & 0 deletions src/Infrastructure/Common/Utils/ArrayUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ export class ArrayUtils {
public static zip<T, U>(left: T[], right: U[]): [T, U][] {
return left.map((value, idx) => [value, right[idx]]);
}

public static groupBy<T>(
xs: Array<T>,
key: (x: T) => string
): { [key: string]: T } {
// Credit: https://stackoverflow.com/a/34890276
return xs.reduce(function(rv, x) {
(rv[key(x)] = rv[key(x)] || []).push(x);
return rv;
}, {});
}
}
8 changes: 8 additions & 0 deletions src/Infrastructure/Common/Utils/dateUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { format, parseISO } from 'date-fns';
import { fr } from 'date-fns/locale';

export const minutesToHours = (value: number): string => {
const hours = Math.floor(value / 60);
Expand Down Expand Up @@ -29,3 +30,10 @@ export const formatHtmlDate = (value: Date): string => {
export const formatHtmlYearMonth = (value: Date): string => {
return format(value, 'yyyy-MM');
};

export const formatEventDate = (value: Date | string): string => {
if (typeof value === 'string') {
value = parseISO(value);
}
return format(value, 'eee dd', { locale: fr });
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { GetTasksQuery } from 'src/Application/Task/Query/GetTasksQuery';
import { GetProjectsQuery } from 'src/Application/Project/Query/GetProjectsQuery';
import { GetCooperativeQuery } from 'src/Application/Settings/Query/GetCooperativeQuery';
import { ArrayUtils } from 'src/Infrastructure/Common/Utils/ArrayUtils';
import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver';

@Controller('app/faircalendar/events/add')
@UseGuards(IsAuthenticatedGuard)
Expand All @@ -32,7 +33,8 @@ export class AddEventController {
@Inject('ICommandBus')
private readonly commandBus: ICommandBus,
@Inject('IQueryBus')
private readonly queryBus: IQueryBus
private readonly queryBus: IQueryBus,
private readonly resolver: RouteNameResolver
) {}

@Get(':startDate--:endDate')
Expand Down Expand Up @@ -97,7 +99,7 @@ export class AddEventController {
)
);

res.redirect(303, '/app/faircalendar');
res.redirect(303, this.resolver.resolve('faircalendar_index'));
} catch (e) {
throw new BadRequestException(e.message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import { User } from 'src/Domain/HumanResource/User/User.entity';
import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO';
import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName';
import { DeleteEventCommand } from 'src/Application/FairCalendar/Command/DeleteEventCommand';
import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver';

@Controller('app/faircalendar/events/delete')
@UseGuards(IsAuthenticatedGuard)
export class DeleteEventController {
constructor(
@Inject('ICommandBus')
private readonly commandBus: ICommandBus
private readonly commandBus: ICommandBus,
private readonly resolver: RouteNameResolver
) {}

@Post(':id')
Expand All @@ -33,7 +35,7 @@ export class DeleteEventController {
) {
try {
await this.commandBus.execute(new DeleteEventCommand(dto.id, user));
res.redirect(303, '/app/faircalendar');
res.redirect(303, this.resolver.resolve('faircalendar_index'));
} catch (e) {
throw new BadRequestException(e.message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
import { ICommandBus } from 'src/Application/ICommandBus';
import { IsAuthenticatedGuard } from 'src/Infrastructure/HumanResource/User/Security/IsAuthenticatedGuard';
import { WithName } from 'src/Infrastructure/Common/ExtendedRouting/WithName';
import { AddEventControllerDTO } from '../DTO/AddEventControllerDTO';
import { LoggedUser } from 'src/Infrastructure/HumanResource/User/Decorator/LoggedUser';
import { User } from 'src/Domain/HumanResource/User/User.entity';
import { IQueryBus } from 'src/Application/IQueryBus';
Expand All @@ -30,6 +29,7 @@ import { IdDTO } from 'src/Infrastructure/Common/DTO/IdDTO';
import { EditEventDTO } from '../DTO/EditEventDTO';
import { UpdateEventCommand } from 'src/Application/FairCalendar/Command/UpdateEventCommand';
import { GetEventByIdQuery } from 'src/Application/FairCalendar/Query/GetEventByIdQuery';
import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver';

@Controller('app/faircalendar/events/edit')
@UseGuards(IsAuthenticatedGuard)
Expand All @@ -38,7 +38,8 @@ export class EditEventController {
@Inject('ICommandBus')
private readonly commandBus: ICommandBus,
@Inject('IQueryBus')
private readonly queryBus: IQueryBus
private readonly queryBus: IQueryBus,
private readonly resolver: RouteNameResolver
) {}

@Get(':id')
Expand Down Expand Up @@ -99,7 +100,7 @@ export class EditEventController {
)
);

res.redirect(303, '/app/faircalendar');
res.redirect(303, this.resolver.resolve('faircalendar_index'));
} catch (e) {
throw new BadRequestException(e.message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import {
Inject,
Query,
Render,
Req,
UseGuards
} from '@nestjs/common';
import { Request } from 'express';
import { User } from 'src/Domain/HumanResource/User/User.entity';
import { GetMonthlyFairCalendarQuery } from 'src/Application/FairCalendar/Query/GetMonthlyFairCalendarQuery';
import { IQueryBus } from 'src/Application/IQueryBus';
Expand All @@ -20,6 +22,9 @@ import { GetUsersQuery } from 'src/Application/HumanResource/User/Query/GetUsers
import { FairCalendarView } from 'src/Application/FairCalendar/View/FairCalendarView';
import { FairCalendarOverviewFactory } from 'src/Domain/FairCalendar/FairCalendarOverviewFactory';
import { FairCalendarOverviewTableFactory } from '../Table/FairCalendarOverviewTableFactory';
import { IDateUtils } from 'src/Application/IDateUtils';
import { ArrayUtils } from 'src/Infrastructure/Common/Utils/ArrayUtils';
import { RouteNameResolver } from 'src/Infrastructure/Common/ExtendedRouting/RouteNameResolver';

@Controller('app/faircalendar')
@UseGuards(IsAuthenticatedGuard)
Expand All @@ -29,16 +34,20 @@ export class FairCalendarController {
private readonly queryBus: IQueryBus,
@Inject('ITranslator')
private readonly translator: ITranslator,
@Inject('IDateUtils')
private readonly dateUtils: IDateUtils,
private overviewFactory: FairCalendarOverviewFactory,
private overviewTableFactory: FairCalendarOverviewTableFactory
private overviewTableFactory: FairCalendarOverviewTableFactory,
private readonly resolver: RouteNameResolver
) {}

@Get()
@WithName('faircalendar_index')
@Render('pages/faircalendar/index.njk')
public async get(
@Query() dto: FairCalendarControllerDTO,
@LoggedUser() user: User
@LoggedUser() user: User,
@Req() req: Request
) {
let date = new Date();

Expand Down Expand Up @@ -87,7 +96,9 @@ export class FairCalendarController {
...(event.id
? {
extendedProps: {
url: `/app/faircalendar/events/edit/${event.id}`
url: this.resolver.resolve('faircalendar_events_edit', {
id: event.id
})
}
}
: {}),
Expand All @@ -97,14 +108,28 @@ export class FairCalendarController {
};
});

const eventsByStartDate = ArrayUtils.groupBy(
fullCalendarEvents,
event => event.start
);

const listViewDays = this.dateUtils.getWeekDaysOfMonth(date).map(day => {
return [
day,
eventsByStartDate[this.dateUtils.format(day, 'yyyy-MM-dd')] || []
];
});

return {
users,
overviewTable,
fullCalendarEvents,
date,
currentMonth: date.getMonth() + 1,
currentYear: date.getFullYear(),
userId
userId,
viewName: req.cookies.faircalendar_view,
listViewDays
};
}
}
4 changes: 3 additions & 1 deletion src/Infrastructure/FairCalendar/faircalendar.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ import { FairCalendarOverviewFactory } from 'src/Domain/FairCalendar/FairCalenda
import { FairCalendarOverviewTableFactory } from './Table/FairCalendarOverviewTableFactory';
import { TranslationsModule } from '../Translations/translations.module';
import { TablesModule } from '../Tables/tables.module';
import { ExtendedRoutingModule } from '../Common/ExtendedRouting/extendedRouting.module';

@Module({
imports: [
BusModule,
ConfigModule,
TypeOrmModule.forFeature([Project, Event, Task, Leave, Cooperative]),
TranslationsModule,
TablesModule
TablesModule,
ExtendedRoutingModule
],
controllers: [
FairCalendarController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ITranslator } from 'src/Infrastructure/Translations/ITranslator';
import { formatFullName } from '../../Common/Utils/formatUtils';
import {
formatDate,
formatEventDate,
formatHtmlDate,
formatHtmlYearMonth,
minutesToHours
Expand Down Expand Up @@ -44,6 +45,7 @@ export class NunjucksTemplates implements ITemplates {
env.addFilter('date', value =>
value === 'now' ? new Date() : formatDate(value)
);
env.addFilter('eventDate', value => formatEventDate(value));
env.addFilter('htmlDate', value => formatHtmlDate(value));
env.addFilter('htmlYearMonth', value => formatHtmlYearMonth(value));
env.addFilter('longMonth', (month: number) =>
Expand Down
7 changes: 1 addition & 6 deletions src/assets/customElements/autoForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,13 @@ export default class extends HTMLElement {
onParsed(() => {
// Progressive enhancement:
// If this custom element activates, submit the form whenever
// a form control changes value, and remove any manual submit button.
// a form control changes value.

const form = /** @type {HTMLFormElement} */ (this.querySelector('form'));
const submitBtn = this.querySelector('button[type="submit"]');

for (const formControl of form.elements) {
formControl.addEventListener('change', () => form.requestSubmit());
}

if (submitBtn) {
submitBtn.remove();
}
});
}
}
5 changes: 0 additions & 5 deletions src/assets/customElements/clipboardButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ export default class extends HTMLElement {
throw new Error(`input at '${selector}' was not found`);
}

const template = /** @type {HTMLTemplateElement} */ (this.querySelector(
'template'
));
this.appendChild(document.importNode(template.content, true));

const btn = /** @type {HTMLButtonElement} */ (this.querySelector('button'));

btn.addEventListener('click', () => {
Expand Down
Loading

0 comments on commit 3db62b7

Please sign in to comment.