@movalib/movalib-commons 1.59.38 → 1.59.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -26,6 +26,7 @@ export { default as ActivateAccount } from './src/components/singup/ActivateAcco
26
26
  export { QrCodePLVContainer } from './src/components/QrCodePLVContainer/QrCodePLVContainer';
27
27
  export { PLVComponent, PrintSize } from './src/components/QrCodePLVContainer/PLVComponent';
28
28
  export { LinkedDocumentDialog } from './src/components/LinkedDocumentDialog';
29
+ export { default as MovaTable } from './src/components/MovaTable/MovaTable';
29
30
  export { default as Subscription } from './src/models/Subscription';
30
31
  export { default as Absence } from './src/models/Absence';
31
32
  export { default as Employee } from './src/models/Employee';
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.VehicleTire = exports.Event = exports.Schedule = exports.VehicleGarage = exports.Garage = exports.Document = exports.Vehicle = exports.Address = exports.Role = exports.User = exports.Customer = exports.Logger = exports.Operation = exports.Prestation = exports.Product = exports.Supplier = exports.Employee = exports.Absence = exports.Subscription = exports.LinkedDocumentDialog = exports.PrintSize = exports.PLVComponent = exports.QrCodePLVContainer = exports.ActivateAccount = exports.GenderSelector = exports.ConfirmationDialog = exports.MovaVehicleTireField = exports.MovaCopyright = exports.MovaSignUp = exports.MovaLogin = exports.MovaSnackbar = exports.TestButton = exports.oldRegexPlate = exports.regexPlate = exports.VehiclePlateField = exports.QRCode = exports.MovaDialog = exports.Loader = exports.MovaDigitalPassport = exports.VehicleFullCard = exports.ScheduleFields = exports.AddressFields = exports.AccountValidation = exports.GaragePLV = exports.IbanInput = exports.DialogForgotPassword = exports.UserService = exports.GarageService = exports.AuthenticationService = exports.VehicleService = void 0;
8
- exports.openDialogPrint = exports.APIMethod = exports.SubscriptionType = exports.SubscriptionState = exports.CountryCode = exports.PrestationState = exports.PrestationType = exports.RegistrationState = exports.SubscriptionPaymentInterval = exports.VehiclePlateType = exports.SlotAlgorithm = exports.OrderState = exports.OrderPreference = exports.ProductType = exports.PartsApplicationType = exports.DateFormatTypes = exports.Gender = exports.DocumentState = exports.DigitalPassportIndex = exports.DocumentType = exports.EventType = exports.EventState = exports.DayOfWeek = exports.MovaAppType = exports.RoleType = exports.CustomerType = exports.API_BASE_URL = exports.request = exports.getLongFormattedDateTime = exports.formatDateByTimezone = exports.validateEmail = exports.validateText = exports.validatePhoneNumber = exports.getApplicationsShortLabels = exports.isSafariOniOS = exports.getDayOfWeekLabel = exports.findScheduleByDayOfWeek = exports.getFormattedIntervals = exports.getFormattedSchedule = exports.formatPhoneNumber = exports.flexLeftRow = exports.capitalizeFirstLetter = exports.getApplicationShortLabel = exports.isEmpty = exports.formatFrenchVehiclePlate = exports.formatVehicleTire = exports.validateField = exports.deleteCookie = exports.readCookie = exports.CategoryPrestation = void 0;
9
- exports.StyledToggleButtonGroup = exports.StyledToggleButton = void 0;
7
+ exports.Event = exports.Schedule = exports.VehicleGarage = exports.Garage = exports.Document = exports.Vehicle = exports.Address = exports.Role = exports.User = exports.Customer = exports.Logger = exports.Operation = exports.Prestation = exports.Product = exports.Supplier = exports.Employee = exports.Absence = exports.Subscription = exports.MovaTable = exports.LinkedDocumentDialog = exports.PrintSize = exports.PLVComponent = exports.QrCodePLVContainer = exports.ActivateAccount = exports.GenderSelector = exports.ConfirmationDialog = exports.MovaVehicleTireField = exports.MovaCopyright = exports.MovaSignUp = exports.MovaLogin = exports.MovaSnackbar = exports.TestButton = exports.oldRegexPlate = exports.regexPlate = exports.VehiclePlateField = exports.QRCode = exports.MovaDialog = exports.Loader = exports.MovaDigitalPassport = exports.VehicleFullCard = exports.ScheduleFields = exports.AddressFields = exports.AccountValidation = exports.GaragePLV = exports.IbanInput = exports.DialogForgotPassword = exports.UserService = exports.GarageService = exports.AuthenticationService = exports.VehicleService = void 0;
8
+ exports.APIMethod = exports.SubscriptionType = exports.SubscriptionState = exports.CountryCode = exports.PrestationState = exports.PrestationType = exports.RegistrationState = exports.SubscriptionPaymentInterval = exports.VehiclePlateType = exports.SlotAlgorithm = exports.OrderState = exports.OrderPreference = exports.ProductType = exports.PartsApplicationType = exports.DateFormatTypes = exports.Gender = exports.DocumentState = exports.DigitalPassportIndex = exports.DocumentType = exports.EventType = exports.EventState = exports.DayOfWeek = exports.MovaAppType = exports.RoleType = exports.CustomerType = exports.API_BASE_URL = exports.request = exports.getLongFormattedDateTime = exports.formatDateByTimezone = exports.validateEmail = exports.validateText = exports.validatePhoneNumber = exports.getApplicationsShortLabels = exports.isSafariOniOS = exports.getDayOfWeekLabel = exports.findScheduleByDayOfWeek = exports.getFormattedIntervals = exports.getFormattedSchedule = exports.formatPhoneNumber = exports.flexLeftRow = exports.capitalizeFirstLetter = exports.getApplicationShortLabel = exports.isEmpty = exports.formatFrenchVehiclePlate = exports.formatVehicleTire = exports.validateField = exports.deleteCookie = exports.readCookie = exports.CategoryPrestation = exports.VehicleTire = void 0;
9
+ exports.StyledToggleButtonGroup = exports.StyledToggleButton = exports.openDialogPrint = void 0;
10
10
  // Export des services
11
11
  var VehicleService_1 = require("./src/services/VehicleService");
12
12
  Object.defineProperty(exports, "VehicleService", { enumerable: true, get: function () { return __importDefault(VehicleService_1).default; } });
@@ -68,6 +68,8 @@ Object.defineProperty(exports, "PLVComponent", { enumerable: true, get: function
68
68
  Object.defineProperty(exports, "PrintSize", { enumerable: true, get: function () { return PLVComponent_1.PrintSize; } });
69
69
  var LinkedDocumentDialog_1 = require("./src/components/LinkedDocumentDialog");
70
70
  Object.defineProperty(exports, "LinkedDocumentDialog", { enumerable: true, get: function () { return LinkedDocumentDialog_1.LinkedDocumentDialog; } });
71
+ var MovaTable_1 = require("./src/components/MovaTable/MovaTable");
72
+ Object.defineProperty(exports, "MovaTable", { enumerable: true, get: function () { return __importDefault(MovaTable_1).default; } });
71
73
  // Export des classes
72
74
  var Subscription_1 = require("./src/models/Subscription");
73
75
  Object.defineProperty(exports, "Subscription", { enumerable: true, get: function () { return __importDefault(Subscription_1).default; } });
@@ -0,0 +1,22 @@
1
+ import { MouseEvent, CSSProperties, ComponentType } from "react";
2
+ type TMovaTable<T> = {
3
+ data: T[];
4
+ displayedColumns: {
5
+ propName: keyof T & string;
6
+ displayName: string;
7
+ component?: ComponentType<{
8
+ element: T;
9
+ }>;
10
+ }[];
11
+ search?: string;
12
+ propSearch?: (keyof T)[];
13
+ isLoading?: boolean;
14
+ pagination?: boolean;
15
+ sx?: CSSProperties;
16
+ compact?: boolean;
17
+ onRowClick?: (data: T) => void;
18
+ onRowRightClick?: (data: T, event: MouseEvent<HTMLTableRowElement>) => void;
19
+ isClickable?: (data: T) => boolean;
20
+ };
21
+ export default function MovaTable<T>({ data, search, propSearch, isLoading, displayedColumns, pagination, onRowClick, onRowRightClick, sx, compact, isClickable }: TMovaTable<T>): import("react/jsx-runtime").JSX.Element;
22
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ var jsx_runtime_1 = require("react/jsx-runtime");
15
+ var react_1 = require("react");
16
+ var material_1 = require("@mui/material");
17
+ var lodash_1 = require("lodash");
18
+ function MovaTable(_a) {
19
+ var data = _a.data, search = _a.search, propSearch = _a.propSearch, isLoading = _a.isLoading, displayedColumns = _a.displayedColumns, pagination = _a.pagination, onRowClick = _a.onRowClick, onRowRightClick = _a.onRowRightClick, sx = _a.sx, compact = _a.compact, isClickable = _a.isClickable;
20
+ var _b = (0, react_1.useState)({ column: displayedColumns[0].propName, order: "asc" }), selectedSorting = _b[0], setSelectedSorting = _b[1];
21
+ var _c = (0, react_1.useState)(0), currentPageIndex = _c[0], setCurrentPageIndex = _c[1];
22
+ var _d = (0, react_1.useState)(25), rowsPerPage = _d[0], setRowsPerPage = _d[1];
23
+ var handleSorting = function (name) {
24
+ setSelectedSorting(function (prev) {
25
+ if (prev.column === name) {
26
+ var newOrder = prev.order === "asc" ? "desc" : "asc";
27
+ return { column: name, order: newOrder };
28
+ }
29
+ else {
30
+ return { column: name, order: "asc" };
31
+ }
32
+ });
33
+ };
34
+ var handleRowClick = (0, react_1.useCallback)(function (element) {
35
+ if (!onRowClick)
36
+ return;
37
+ onRowClick(element);
38
+ }, [onRowClick]);
39
+ var handlePageChange = function (event, page) {
40
+ setCurrentPageIndex(page);
41
+ };
42
+ var handleRowsPerPageChange = function (event) {
43
+ setCurrentPageIndex(0);
44
+ setRowsPerPage(Number(event.target.value));
45
+ };
46
+ var filteredGarages = (0, react_1.useMemo)(function () {
47
+ var filteredData = data;
48
+ // changement d'ordre de la colonne
49
+ filteredData = selectedSorting.order === "asc" ? (0, lodash_1.sortBy)(filteredData, [selectedSorting.column]) : (0, lodash_1.sortBy)(filteredData, [selectedSorting.column]).reverse();
50
+ if (search) {
51
+ var searchableFields_1 = propSearch || ['name']; // default to searching in 'name' field if propSearch is not provided
52
+ filteredData = filteredData.filter(function (element) {
53
+ return searchableFields_1.some(function (field) {
54
+ var elementField = element[field];
55
+ return elementField.toLowerCase().includes(search.toLowerCase());
56
+ });
57
+ });
58
+ }
59
+ return filteredData;
60
+ }, [search, data, selectedSorting, propSearch]);
61
+ var paginatedElements = (0, react_1.useMemo)(function () {
62
+ if (pagination) {
63
+ return filteredGarages.slice(currentPageIndex * rowsPerPage, (currentPageIndex + 1) * rowsPerPage);
64
+ }
65
+ else {
66
+ return filteredGarages;
67
+ }
68
+ }, [filteredGarages, currentPageIndex, rowsPerPage, pagination]);
69
+ var rowCount = (0, react_1.useMemo)(function () {
70
+ return filteredGarages.length;
71
+ }, [filteredGarages]);
72
+ // reset la page lors d'une recherche recherche
73
+ (0, react_1.useEffect)(function () {
74
+ setCurrentPageIndex(0);
75
+ }, [search]);
76
+ return ((0, jsx_runtime_1.jsx)(material_1.TableContainer, __assign({ sx: __assign({ height: '100%' }, sx), component: material_1.Paper }, { children: (0, jsx_runtime_1.jsxs)(material_1.Table, __assign({ size: compact ? "small" : "medium", sx: { height: '100%' }, stickyHeader: true }, { children: [(0, jsx_runtime_1.jsx)(material_1.TableHead, { children: (0, jsx_runtime_1.jsx)(material_1.TableRow, { children: displayedColumns.map(function (column, index) { return ((0, jsx_runtime_1.jsxs)(material_1.TableCell, { children: [column.displayName, (0, jsx_runtime_1.jsx)(material_1.TableSortLabel, { active: selectedSorting.column === column.propName, direction: selectedSorting.order, onClick: function () { handleSorting(column.propName); } })] }, index)); }) }) }), (0, jsx_runtime_1.jsxs)(material_1.TableBody, __assign({ sx: { overflowY: 'auto' } }, { children: [isLoading && ((0, jsx_runtime_1.jsx)(material_1.TableRow, { children: (0, jsx_runtime_1.jsx)(material_1.TableCell, __assign({ colSpan: 5, sx: { padding: 0 } }, { children: (0, jsx_runtime_1.jsx)(material_1.LinearProgress, {}) })) })), data.length !== 0 && paginatedElements.map(function (element, index) { return ((0, jsx_runtime_1.jsx)(material_1.TableRow, __assign({ onClick: function () { return handleRowClick(element); }, onContextMenu: function (event) { return onRowRightClick && onRowRightClick(element, event); }, sx: { cursor: isClickable ? (isClickable(element) ? 'pointer' : 'default') : 'pointer', height: 'auto' }, hover: true }, { children: displayedColumns.map(function (column, index) { return ((0, jsx_runtime_1.jsxs)(material_1.TableCell, { children: [column.component && (0, jsx_runtime_1.jsx)(column.component, { element: element }), !column.component && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: element[column.propName] })] }, index)); }) }), index)); }), (0, jsx_runtime_1.jsx)(material_1.TableRow, { sx: { height: '100%' } })] })), pagination !== undefined && ((0, jsx_runtime_1.jsx)(material_1.TableFooter, __assign({ sx: { position: 'sticky', bottom: 0, backgroundColor: 'white' } }, { children: (0, jsx_runtime_1.jsx)(material_1.TableRow, { children: (0, jsx_runtime_1.jsx)(material_1.TablePagination, { count: rowCount, onPageChange: handlePageChange, page: currentPageIndex, rowsPerPage: rowsPerPage, labelRowsPerPage: "Lignes par page :", onRowsPerPageChange: handleRowsPerPageChange, rowsPerPageOptions: [25, 50, 100] }) }) })))] })) })));
77
+ }
78
+ exports.default = MovaTable;
package/index.ts CHANGED
@@ -31,6 +31,8 @@ export { default as ActivateAccount } from './src/components/singup/ActivateAcco
31
31
  export { QrCodePLVContainer } from './src/components/QrCodePLVContainer/QrCodePLVContainer';
32
32
  export { PLVComponent, PrintSize } from './src/components/QrCodePLVContainer/PLVComponent';
33
33
  export {LinkedDocumentDialog} from './src/components/LinkedDocumentDialog';
34
+ export { default as MovaTable } from './src/components/MovaTable/MovaTable'
35
+
34
36
  // Export des classes
35
37
  export { default as Subscription } from './src/models/Subscription';
36
38
  export { default as Absence } from './src/models/Absence';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@movalib/movalib-commons",
3
- "version": "1.59.38",
3
+ "version": "1.59.39",
4
4
  "description": "Bibliothèque d'objets communs à l'ensemble des projets React de Movalib",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "scripts": {
9
9
  "start": "webpack-dev-server --entry ./devIndex.tsx --open --https",
10
10
  "build": "rm -rf dist && tsc && npm run copy-assets",
11
- "copy-assets": "cp -r src/assets/ dist/src/assets/ && cp -r src/style/ dist/src/style/",
11
+ "copy-assets": "cp -r src/assets/ dist/src/assets/ && cp -r src/style/. dist/src/style/",
12
12
  "test": "echo \"Error: no test specified\" && exit 1",
13
13
  "clean": "rm -rf dist node_modules package-lock.json",
14
14
  "build:dev": "rm -rf dist && tsc && npm run copy-assets && npm pack"
@@ -31,6 +31,7 @@
31
31
  "file-loader": "^6.2.0",
32
32
  "html2canvas": "^1.4.1",
33
33
  "js-cookie": "^3.0.5",
34
+ "lodash": "^4.17.21",
34
35
  "moment": "^2.30.1",
35
36
  "moment-timezone": "^0.5.48",
36
37
  "pdf-lib": "^1.17.1",
@@ -51,10 +52,11 @@
51
52
  },
52
53
  "devDependencies": {
53
54
  "@types/js-cookie": "^3.0.4",
55
+ "@types/lodash": "^4.17.17",
54
56
  "@types/pdfjs-dist": "^2.10.377",
55
57
  "@types/react-input-mask": "^3.0.5",
56
58
  "html-webpack-plugin": "^5.5.3",
57
59
  "ts-loader": "^9.4.4",
58
60
  "webpack-cli": "^5.1.4"
59
61
  }
60
- }
62
+ }
@@ -0,0 +1,150 @@
1
+ import { useEffect, useState, MouseEvent, ChangeEvent, CSSProperties, useMemo, ComponentType, useCallback } from "react";
2
+ import { Table, TableContainer, TableHead, TableCell, TableRow, TableBody, Paper, LinearProgress, TableSortLabel, TablePagination, TableFooter } from "@mui/material";
3
+ import { sortBy } from 'lodash';
4
+
5
+ type TMovaTable<T> = {
6
+ data: T[],
7
+ displayedColumns: {propName: keyof T & string, displayName: string, component?: ComponentType<{element: T}>}[],
8
+ search?: string,
9
+ propSearch?: (keyof T)[]
10
+ isLoading?: boolean,
11
+ pagination?: boolean,
12
+ sx?: CSSProperties,
13
+ compact?: boolean
14
+ onRowClick?: (data: T) => void,
15
+ onRowRightClick?: (data: T, event: MouseEvent<HTMLTableRowElement>) => void
16
+ isClickable?: (data: T) => boolean
17
+ }
18
+
19
+ type TSelectedSorting = {
20
+ column: string,
21
+ order: "asc" | "desc"
22
+ }
23
+
24
+ export default function MovaTable<T>({data, search, propSearch, isLoading, displayedColumns, pagination, onRowClick, onRowRightClick, sx, compact, isClickable}: TMovaTable<T>) {
25
+
26
+ const [selectedSorting, setSelectedSorting] = useState<TSelectedSorting>({column: displayedColumns[0].propName, order: "asc"});
27
+ const [currentPageIndex, setCurrentPageIndex] = useState<number>(0);
28
+ const [rowsPerPage, setRowsPerPage] = useState<number>(25);
29
+
30
+ const handleSorting = (name: string) => {
31
+ setSelectedSorting(prev => {
32
+ if (prev.column === name) {
33
+ const newOrder = prev.order === "asc" ? "desc" : "asc";
34
+ return { column: name, order: newOrder };
35
+ } else {
36
+ return { column: name, order: "asc" };
37
+ }
38
+ });
39
+ };
40
+
41
+ const handleRowClick = useCallback((element: T) => {
42
+ if(!onRowClick) return;
43
+ onRowClick(element);
44
+ }, [onRowClick])
45
+
46
+
47
+ const handlePageChange = (event: MouseEvent<HTMLButtonElement> | null, page: number) => {
48
+ setCurrentPageIndex(page);
49
+ }
50
+
51
+ const handleRowsPerPageChange = (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
52
+ setCurrentPageIndex(0);
53
+ setRowsPerPage(Number(event.target.value));
54
+ }
55
+
56
+ const filteredGarages = useMemo(() => {
57
+ let filteredData = data;
58
+
59
+ // changement d'ordre de la colonne
60
+ filteredData = selectedSorting.order === "asc" ? sortBy(filteredData, [selectedSorting.column]) : sortBy( filteredData, [selectedSorting.column]).reverse()
61
+
62
+ if(search){
63
+ const searchableFields = propSearch || ['name' as keyof T]; // default to searching in 'name' field if propSearch is not provided
64
+ filteredData = filteredData.filter((element: T) =>
65
+ searchableFields.some((field) =>{
66
+ const elementField = element[field] as keyof T & string;
67
+ return elementField.toLowerCase().includes(search.toLowerCase())
68
+ })
69
+ );
70
+ }
71
+ return filteredData;
72
+ }, [search, data, selectedSorting, propSearch])
73
+
74
+
75
+ const paginatedElements = useMemo(() => {
76
+ if(pagination){
77
+ return filteredGarages.slice(currentPageIndex * rowsPerPage, (currentPageIndex + 1) * rowsPerPage);
78
+ }else{
79
+ return filteredGarages;
80
+ }
81
+
82
+ }, [filteredGarages, currentPageIndex, rowsPerPage, pagination])
83
+
84
+ const rowCount = useMemo(() => {
85
+ return filteredGarages.length;
86
+ }, [filteredGarages])
87
+
88
+ // reset la page lors d'une recherche recherche
89
+ useEffect(() => {
90
+ setCurrentPageIndex(0);
91
+ }, [search])
92
+
93
+ return(
94
+ <TableContainer sx={{height: '100%', ...sx}} component={Paper}>
95
+ <Table size={compact ? "small" : "medium"} sx={{height: '100%'}} stickyHeader>
96
+ <TableHead>
97
+ <TableRow>
98
+ {displayedColumns.map((column, index) => (
99
+ <TableCell key={index}>
100
+ {column.displayName}
101
+ <TableSortLabel
102
+ active={selectedSorting.column === column.propName}
103
+ direction={selectedSorting.order}
104
+ onClick={() => {handleSorting(column.propName)}}
105
+ />
106
+ </TableCell>
107
+ ))}
108
+ </TableRow>
109
+ </TableHead>
110
+ <TableBody sx={{overflowY: 'auto'}}>
111
+ {isLoading && (
112
+ <TableRow>
113
+ <TableCell colSpan={5} sx={{padding: 0}}>
114
+ <LinearProgress />
115
+ </TableCell>
116
+ </TableRow>
117
+ )}
118
+
119
+ {data.length !== 0 && paginatedElements.map((element, index) => (
120
+ <TableRow onClick={() => handleRowClick(element)} onContextMenu={(event) => onRowRightClick && onRowRightClick(element, event)} sx={{ cursor: isClickable ? (isClickable(element) ? 'pointer' : 'default') : 'pointer', height: 'auto' }} hover key={index}>
121
+ {displayedColumns.map((column, index) => (
122
+ <TableCell key={index}>
123
+ {column.component && <column.component element={element} />}
124
+ {!column.component && <>{element[column.propName]}</>}
125
+ </TableCell>
126
+ ))}
127
+ </TableRow>
128
+ ))}
129
+ <TableRow sx={{height: '100%'}} />
130
+ </TableBody>
131
+
132
+ {pagination !== undefined && (
133
+ <TableFooter sx={{position: 'sticky', bottom: 0, backgroundColor: 'white'}}>
134
+ <TableRow>
135
+ <TablePagination
136
+ count={rowCount}
137
+ onPageChange={handlePageChange}
138
+ page={currentPageIndex}
139
+ rowsPerPage={rowsPerPage}
140
+ labelRowsPerPage="Lignes par page :"
141
+ onRowsPerPageChange={handleRowsPerPageChange}
142
+ rowsPerPageOptions={[25, 50, 100]}
143
+ />
144
+ </TableRow>
145
+ </TableFooter>
146
+ )}
147
+ </Table>
148
+ </TableContainer>
149
+ );
150
+ }