97 Commits
Author SHA1 Message Date
aziis98 0c6f60e461 fix: wrong default 2025-08-27 15:04:57 +02:00
aziis98 e6c5db05a6 feat: first time button sends to all courses tab 2025-08-27 13:06:12 +02:00
BachoSeven d0c2f58094 chore: update calendar IDs for 1st semester 25/26 2025-08-15 20:33:12 +02:00
BachoSeven e9539b7f35 Fix lab1 split courses recognition, add snapping! 2025-02-14 16:39:35 +01:00
aziis98 4c98950822 chore: updated to new semester calendar ids 2025-02-04 10:57:14 +01:00
aziis98 d929aa6cfe chore: updated calendar ids to first semester of 2024/2025 2024-08-06 19:00:20 +02:00
aziis98 4d95a1a633 chore: empty commit to trigger deploy 2024-02-25 17:16:44 +01:00
aziis98 935309147c cmd: prettier -w src/ 2024-02-25 16:43:59 +01:00
aziis98 fb551fb719 fix: safari ios showPicker() bug 2024-02-25 16:42:10 +01:00
BachoSeven c731d9c8b9 Merge pull request 'chore: fix LIMCO courses' names' (#13) from dev into main
Reviewed-on: phc/orario#13
2024-02-04 15:35:53 +00:00
BachoSeven d9d2aaed11 chore: fix LIMCO courses' names 2024-02-04 16:35:20 +01:00
BachoSeven 7bbd9ba139 Merge pull request 'chore: update calendar IDs for the 2nd semester' (#12) from dev into main
Reviewed-on: phc/orario#12
2024-02-04 15:00:00 +00:00
BachoSeven 62a9b80b21 chore: update calendar IDs for the 2nd semester 2024-02-04 15:59:07 +01:00
Fran314 c43bdc60e7 Merge pull request 'dev' (#11) from dev into main
Reviewed-on: phc/orario#11
2023-10-09 13:30:58 +00:00
Fran314 c8172ad88a Added warning messages when date outside of lecture period 2023-10-09 15:29:51 +02:00
Fran314 c0b2894c22 Merge branch 'dev' of git.phc.dm.unipi.it:phc/orario into dev 2023-10-09 14:26:22 +02:00
Fran314 fd0440465c Added date picker and fixed menu rendering 2023-10-09 14:24:49 +02:00
aziis98 bdbf031bce Merge pull request 'fix: rimosso un console.log' (#8) from dev into main
Reviewed-on: phc/orario#8
2023-10-08 11:12:04 +00:00
aziis98 32dc9a6104 fix: rimosso un console.log 2023-10-08 13:09:57 +02:00
Fran314 2d4a3ce664 Merge pull request 'reintrodotta visualizzazione lista rimossa nel commit precedente' (#7) from dev into main
Reviewed-on: phc/orario#7
2023-10-07 21:05:33 +00:00
Fran314 af41177561 reintrodotta visualizzazione lista rimossa nel commit precedente 2023-10-07 22:49:03 +02:00
Fran314 22ce830c80 Merge pull request 'dev' (#6) from dev into main
Reviewed-on: phc/orario#6
2023-10-07 18:56:33 +00:00
Fran314 7efb311a61 Aggiunta trasposizione 2023-10-07 19:46:25 +02:00
Fran314 a34d36257b first brutal rework and first prototype 2023-08-19 03:57:46 +02:00
BachoSeven 04b6d5640d Merge pull request 'chore: update date ranges' (#5) from dev into main
Reviewed-on: phc/orario#5
2023-07-24 15:07:18 +00:00
BachoSeven 0caf967e14 chore: update date ranges 2023-07-24 17:04:40 +02:00
aziis98 291aa72fd0 Merge branch 'dev' 2023-03-05 23:17:28 +01:00
aziis98 17188b17ee fix: tolto definitivamente l'effetto hover da mobile 2023-03-05 23:17:07 +01:00
aziis98 e9d40598eb Merge pull request 'fix: aggiornato il range di date alla settimana del 2023-03-06' (#4) from dev into main
Reviewed-on: phc/orario#4
2023-03-05 22:07:33 +00:00
aziis98 9a8fa0c440 fix: aggiornato il range di date alla settimana del 2023-03-06 2023-03-05 23:05:23 +01:00
BachoSeven c831bb1715 WorkWeek: Add 18-20 slot, CSS seems to be fine. 2023-03-01 16:51:07 +01:00
aziis98 ce2f76da14 drone: now it actually works 2023-02-27 00:41:17 +01:00
aziis98 5ebc62b844 drone: testing per branch config 2023-02-27 00:40:22 +01:00
aziis98 d2f143133e fix: no hover on mobile 2023-02-27 00:29:23 +01:00
aziis98 82c21d2af9 fix: missing base url while building 2023-02-22 20:12:18 +01:00
aziis98 d4cd070cce fix: ora forse tutto funge 2023-02-22 20:05:01 +01:00
aziis98 bc1196f216 boh 2023-02-22 20:03:08 +01:00
aziis98 e77b4a19e3 boh 2023-02-22 20:02:40 +01:00
aziis98 4589cda93d fix: wrong dir again 2023-02-22 19:37:55 +01:00
aziis98 63b73ed0b3 fix: wrong folder 2023-02-22 18:55:36 +01:00
aziis98 1219eeb408 fix: testing drone 2023-02-22 18:24:10 +01:00
aziis98 15446e3cbc fix: missing command 2023-02-22 18:11:04 +01:00
aziis98 0af55b4755 fix: wrong image name 2023-02-22 18:10:14 +01:00
aziis98 4b01e91fa7 trying out drone deploy 2023-02-22 18:02:23 +01:00
aziis98 e7b145a02f fix: aggiunta un'altra patch per i nomi dei delle aule 2023-02-22 16:57:58 +01:00
aziis98 b6eb7a5ec1 fix: ehm avevo dimenticato una cosa 2023-02-03 22:28:22 +01:00
aziis98 03f9db6e76 fix: aggiornati gli id dei calendari 2023-02-03 22:18:36 +01:00
aziis98 e7f59c4693 fix: aggiunta finalmente un'icona 2023-01-24 17:27:03 +01:00
aziis98 f86edb9f6c fix: Beh che dire 2023-01-23 23:43:01 +01:00
aziis98 025a44472d fix: tutti gli orario ora sono nel range del secondo semestre 2023 2023-01-23 23:36:42 +01:00
aziis98 9f66f40984 fix: non so perché prima c'era 22 2023-01-23 23:32:18 +01:00
aziis98 9c12cbf759 chore: added new calendars 2023-01-23 23:28:59 +01:00
aziis98 4bf696ea75 feat: added analytics 2022-12-18 12:53:58 +01:00
aziis98 e432b60b54 Fixed half-hour lessons for work-week-v 2022-09-25 18:11:52 +02:00
aziis98 abb98dfbc3 Fixed grid lines again 2022-09-25 18:00:28 +02:00
aziis98 4af3529b6e Fixed grid lines offset 2022-09-25 17:54:56 +02:00
aziis98 8f9fbb2bc5 Changed dark theme colors a bit 2022-09-25 17:36:40 +02:00
BachoSeven e7f538c53c Update Help.jsx 2022-09-15 12:40:13 +02:00
BachoSeven 864a0d23da Revamp Help popup 2022-09-15 11:48:51 +02:00
aziis98 7cbbf243c4 Rimossa visualizzazione giornata dalla modalità desktop 2022-09-15 00:16:30 +02:00
aziis98 7d20ccab10 Fix: corsi con più aule, prof dei corsi, patch speciale per il lab di primo anno 2022-09-14 23:51:28 +02:00
aziis98 96ca0fef8f Added localstorage support 2022-09-14 14:55:42 +02:00
aziis98 d623df9158 Some fixes 2022-09-14 14:11:12 +02:00
aziis98 142c5e1b67 Finalizzazione nuovo layout da mobile 2022-09-14 14:00:17 +02:00
aziis98 5d8fbc9363 Missing conflicts 2022-09-14 13:31:17 +02:00
aziis98 0b1dbaebbd Merged conflicts 2022-09-14 13:30:23 +02:00
aziis98 22aa06ebf6 Some adjustments 2022-09-14 13:21:50 +02:00
aziis98 41195462f1 Merge pull request 'Added optionbar for mobile' (#2) from Fran314/orario:mobile-header into dev
Reviewed-on: phc/orario#2
2022-09-14 11:20:33 +00:00
Fran314 19389dbee2 Added optionbar for mobile 2022-09-13 15:40:52 +02:00
aziis98 4a5994210e Formatting 2022-09-13 14:42:59 +02:00
aziis98 16233adcf1 Formatting 2022-09-13 14:40:40 +02:00
aziis98 66b04ea7be Merge pull request 'Added compact grid view for the week' (#1) from Fran314/orario:compressed-week-view into dev
Reviewed-on: phc/orario#1
2022-09-13 12:37:24 +00:00
aziis98 7b1b9c2aed Merge branch 'dev' into compressed-week-view 2022-09-13 12:36:34 +00:00
Fran314 ebb78c4aff Added compact grid view for the week 2022-09-13 11:40:25 +02:00
BachoSeven 8e3d0b0155 Add hover to ScheduleView 2022-09-13 11:14:57 +02:00
BachoSeven 3b2fc34ef1 Add pointer cursor 2022-09-13 11:11:23 +02:00
aziis98 c0340c3407 Schedule view 2022-09-12 20:02:04 +02:00
aziis98 0f0bc1c52a Fiexed a bug 2022-09-12 12:03:56 +02:00
aziis98 01fa4b16e2 Refactor delle view-modes, readme and better dockerfile 2022-09-11 16:18:45 +02:00
aziis98 23c1510455 Slight adjustment to overlay buttons 2022-09-11 13:46:56 +02:00
aziis98 b76213e75d Merge branch 'main' of git.phc.dm.unipi.it:phc/orario 2022-09-11 13:37:46 +02:00
aziis98 fdeb17c90e Merged colors 2022-09-11 13:37:40 +02:00
BachoSeven d767615545 Formatting 2022-09-11 13:35:22 +02:00
aziis98 0a7331f63a Fixed a color 2022-09-11 13:34:46 +02:00
BachoSeven 85b24db785 Better selected-border colors for headerbar 2022-09-11 13:34:32 +02:00
aziis98 46d8b5b878 Updated some styles and colors 2022-09-11 13:28:27 +02:00
aziis98 c3810670b2 Some fixes 2022-09-11 13:13:59 +02:00
BachoSeven b593407915 Lighter borders for dark mode 2022-09-11 12:52:34 +02:00
BachoSeven d2526bcfa6 Slightly more readable dark mode text 2022-09-11 12:46:50 +02:00
aziis98 f90b60fbd9 Merged css and js 2022-09-10 19:49:25 +02:00
aziis98 c7c8ce9d48 Darkmode anche in mobile 2022-09-10 19:48:27 +02:00
BachoSeven 09ebad224b Add prefers-dark-theme 2022-09-10 19:42:49 +02:00
BachoSeven 0e81edfa3b Fix mobile css and links in help 2022-09-10 19:32:04 +02:00
BachoSeven 360fa42606 localstorage 2022-09-10 19:10:24 +02:00
BachoSeven 2dda03dd8a Minor fix 2022-09-10 19:06:31 +02:00
BachoSeven d5dd2a7824 Merge branch 'main' of git.phc.dm.unipi.it:phc/orario 2022-09-10 19:02:44 +02:00
BachoSeven 03ca03debc Add dark theme 2022-09-10 19:00:35 +02:00
30 changed files with 1738 additions and 63139 deletions
+46
View File
@@ -0,0 +1,46 @@
kind: pipeline
name: default
steps:
- name: deploy
image: node:latest
volumes:
- name: host-orario-dist
path: /drone/src/dist
environment:
BASE_URL:
from_secret: base_url
commands:
- pwd
- npm install
- npm run build
volumes:
- name: host-orario-dist
host:
path: /var/www/orario
trigger:
branch:
- main
event:
- push
---
kind: pipeline
type: exec
name: caddy-permissions
depends_on:
- default
steps:
- name: chown
commands:
- chown -R caddy:caddy /var/www/orario
trigger:
branch:
- main
event:
- push
+2
View File
@@ -6,3 +6,5 @@ node_modules/
.env .env
.env.production .env.production
.vscode/
+9
View File
@@ -0,0 +1,9 @@
{
"printWidth": 90,
"singleQuote": true,
"quoteProps": "consistent",
"tabWidth": 4,
"semi": false,
"arrowParens": "avoid",
"proseWrap": "always"
}
+2 -1
View File
@@ -2,7 +2,8 @@ FROM node:18
WORKDIR /app WORKDIR /app
COPY . ./ COPY package.json ./
RUN npm install RUN npm install
COPY . .
CMD ["npm", "run", "build"] CMD ["npm", "run", "build"]
+32
View File
@@ -0,0 +1,32 @@
# Orario
Sito per visualizzare l'orario delle lezioni per i vari anni di corso.
## Usage
You need to have installed `node` and `npm` (or `pnpm`). To setup the project just run `npm install`.
### Development
To start the development server run `npm run dev`.
### Editor
È meglio se prima di fare commit il codice sia formattato con Prettier, nel caso di VSCode c'è un'estensione omonima e le opzioni da aggiungere al proprio JSON di impostazioni sono
```json
...
"prettier.printWidth": 100,
"prettier.singleQuote": true,
"prettier.quoteProps": "consistent",
"prettier.tabWidth": 4,
"prettier.semi": false,
"prettier.arrowParens": "avoid",
"editor.formatOnSave": true,
...
```
### Production
To build the ViteJS project run `npm run build`, for deployment a `.env` files can be used to set the `BASE_URL` variable.
Executable
BIN
View File
Binary file not shown.
-81
View File
@@ -1,81 +0,0 @@
[
"ANALISI ARMONICA - ANALISI ARMONICA/a",
"ANALISI MATEMATICA 3",
"ASPETTI MATEMATICI NELLA COMPUTAZIONE QUANTISTICA",
"CALCOLO SCIENTIFICO",
"COMBINATORIA ALGEBRICA",
"DETERMINAZIONE ORBITALE",
"DINAMICA DEL SISTEMA SOLARE",
"DINAMICA DEL SISTEMA SOLARE",
"ELEMENTI DI GEOMETRIA ALGEBRICA",
"ELEMENTI DI GEOMETRIA ALGEBRICA",
"ELEMENTI DI GEOMETRIA ALGEBRICA",
"ELEMENTI DI GEOMETRIA ALGEBRICA",
"ELEMENTI DI TOPOLOGIA ALGEBRICA",
"ELEMENTI DI TOPOLOGIA ALGEBRICA",
"ELEMENTI DI TOPOLOGIA ALGEBRICA",
"ELEMENTI DI TOPOLOGIA ALGEBRICA",
"FISICA II",
"FISICA II",
"FISICA II",
"FISICA II",
"FISICA II",
"FISICA II",
"FISICA II",
"FISICA II",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"GEOMETRIA E TOPOLOGIA DIFFERENZIALE",
"ISTITUZIONI DI ALGEBRA",
"ISTITUZIONI DI ALGEBRA",
"ISTITUZIONI DI ANALISI MATEMATICA",
"ISTITUZIONI DI ANALISI MATEMATICA",
"ISTITUZIONI DI ANALISI MATEMATICA",
"ISTITUZIONI DI DIDATTICA DELLA MATEMATICA",
"ISTITUZIONI DI DIDATTICA DELLA MATEMATICA",
"ISTITUZIONI DI DIDATTICA DELLA MATEMATICA",
"ISTITUZIONI DI FISICA MATEMATICA",
"ISTITUZIONI DI FISICA MATEMATICA",
"LABORATORIO COMPUTAZIONALE",
"LOGICA MATEMATICA",
"LOGICA MATEMATICA",
"LOGICA MATEMATICA",
"LOGICA MATEMATICA",
"MECCANICA SUPERIORE - MECCANICA SUPERIORE/a",
"MECCANICA SUPERIORE - MECCANICA SUPERIORE/a",
"METODI NUMERICI PER CATENE DI MARKOV - METODI NUMERICI PER CATENE DI MARKOV/a",
"METODI NUMERICI PER CATENE DI MARKOV - METODI NUMERICI PER CATENE DI MARKOV/a",
"METODI NUMERICI PER LA GRAFICA - METODI NUMERICI PER LA GRAFICA/a",
"METODI NUMERICI PER LA GRAFICA - METODI NUMERICI PER LA GRAFICA/a",
"PROBABILITÀ",
"PROBABILITÀ",
"PROBABILITÀ",
"PROBABILITÀ",
"PROBABILITÀ",
"PROBABILITÀ",
"RICERCA OPERATIVA",
"RICERCA OPERATIVA",
"RICERCA OPERATIVA",
"RICERCA OPERATIVA",
"RICERCA OPERATIVA",
"RICERCA OPERATIVA",
"SISTEMI DINAMICI",
"SISTEMI DINAMICI",
"SISTEMI DINAMICI",
"SISTEMI DINAMICI",
"STORIA DELLA MATEMATICA",
"STORIA DELLA MATEMATICA",
"STORIA DELLA MATEMATICA",
"STORIA DELLA MATEMATICA",
"TECNOLOGIE PER LA DIDATTICA",
"TECNOLOGIE PER LA DIDATTICA",
"TEORIA ANALITICA DEI NUMERI A - TEORIA ANALITICA DEI NUMERI A/a",
"TEORIA ANALITICA DEI NUMERI A - TEORIA ANALITICA DEI NUMERI A/a",
"TEORIA E METODI DELL'OTTIMIZZAZIONE",
"TEORIA E METODI DELL'OTTIMIZZAZIONE",
"TOPOLOGIA DIFFERENZIALE - TOPOLOGIA DIFFERENZIALE/a",
"TOPOLOGIA DIFFERENZIALE - TOPOLOGIA DIFFERENZIALE/a"
]
-61819
View File
File diff suppressed because it is too large Load Diff
+22 -18
View File
@@ -1,24 +1,28 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Orario DM Unipi</title> <title>Orario DM Unipi</title>
<meta property="og:title" content="PHC - Orario" /> <meta property="og:title" content="PHC - Orario" />
<meta property="og:description" content="Sito per visualizzare l'orario delle lezioni per i vari anni di corso" /> <meta property="og:description" content="Sito per visualizzare l'orario delle lezioni per i vari anni di corso" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="https://lab.phc.dm.unipi.it/orario" /> <meta property="og:url" content="https://lab.phc.dm.unipi.it/orario" />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,1,0" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,1,0" />
<link rel="stylesheet" href="/src/styles/main.scss"> <link rel="icon" type="image/png" href="icon.png" />
</head>
<body> <link rel="stylesheet" href="/src/styles/main.scss" />
<script type="module" src="/src/main.jsx"></script>
</body> <script data-goatcounter="https://analytics.phc.dm.unipi.it/count" async src="//analytics.phc.dm.unipi.it/count.js"></script>
</head>
<body>
<script type="module" src="/src/main.jsx"></script>
</body>
</html> </html>
+167 -157
View File
@@ -1,30 +1,40 @@
lockfileVersion: 5.4 lockfileVersion: '6.0'
specifiers: settings:
'@babel/core': ^7.18.13 autoInstallPeers: true
'@preact/preset-vite': ^2.3.0 excludeLinksFromLockfile: false
date-fns: ^2.29.2
lodash: ^4.17.21
lodash-es: ^4.17.21
preact: ^10.10.6
sass: ^1.54.8
vite: ^3.0.9
dependencies: dependencies:
date-fns: 2.29.2 date-fns:
lodash: 4.17.21 specifier: ^2.29.2
lodash-es: 4.17.21 version: 2.29.2
preact: 10.10.6 lodash:
sass: 1.54.8 specifier: ^4.17.21
vite: 3.0.9_sass@1.54.8 version: 4.17.21
lodash-es:
specifier: ^4.17.21
version: 4.17.21
preact:
specifier: ^10.10.6
version: 10.10.6
sass:
specifier: ^1.54.8
version: 1.54.8
vite:
specifier: ^3.0.9
version: 3.0.9(sass@1.54.8)
devDependencies: devDependencies:
'@babel/core': 7.18.13 '@babel/core':
'@preact/preset-vite': 2.3.0_wibdudaz52xr4lhcmpvnys3x3u specifier: ^7.18.13
version: 7.18.13
'@preact/preset-vite':
specifier: ^2.3.0
version: 2.3.0(@babel/core@7.18.13)(preact@10.10.6)(vite@3.0.9)
packages: packages:
/@ampproject/remapping/2.2.0: /@ampproject/remapping@2.2.0:
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dependencies: dependencies:
@@ -32,26 +42,26 @@ packages:
'@jridgewell/trace-mapping': 0.3.15 '@jridgewell/trace-mapping': 0.3.15
dev: true dev: true
/@babel/code-frame/7.18.6: /@babel/code-frame@7.18.6:
resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/highlight': 7.18.6 '@babel/highlight': 7.18.6
dev: true dev: true
/@babel/compat-data/7.18.13: /@babel/compat-data@7.18.13:
resolution: {integrity: sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==} resolution: {integrity: sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/core/7.18.13: /@babel/core@7.18.13:
resolution: {integrity: sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==} resolution: {integrity: sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@ampproject/remapping': 2.2.0 '@ampproject/remapping': 2.2.0
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
'@babel/generator': 7.18.13 '@babel/generator': 7.18.13
'@babel/helper-compilation-targets': 7.18.9_@babel+core@7.18.13 '@babel/helper-compilation-targets': 7.18.9(@babel/core@7.18.13)
'@babel/helper-module-transforms': 7.18.9 '@babel/helper-module-transforms': 7.18.9
'@babel/helpers': 7.18.9 '@babel/helpers': 7.18.9
'@babel/parser': 7.18.13 '@babel/parser': 7.18.13
@@ -67,7 +77,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/generator/7.18.13: /@babel/generator@7.18.13:
resolution: {integrity: sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==} resolution: {integrity: sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -76,14 +86,14 @@ packages:
jsesc: 2.5.2 jsesc: 2.5.2
dev: true dev: true
/@babel/helper-annotate-as-pure/7.18.6: /@babel/helper-annotate-as-pure@7.18.6:
resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-compilation-targets/7.18.9_@babel+core@7.18.13: /@babel/helper-compilation-targets@7.18.9(@babel/core@7.18.13):
resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==} resolution: {integrity: sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
peerDependencies: peerDependencies:
@@ -96,12 +106,12 @@ packages:
semver: 6.3.0 semver: 6.3.0
dev: true dev: true
/@babel/helper-environment-visitor/7.18.9: /@babel/helper-environment-visitor@7.18.9:
resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/helper-function-name/7.18.9: /@babel/helper-function-name@7.18.9:
resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==} resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -109,21 +119,21 @@ packages:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-hoist-variables/7.18.6: /@babel/helper-hoist-variables@7.18.6:
resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-module-imports/7.18.6: /@babel/helper-module-imports@7.18.6:
resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-module-transforms/7.18.9: /@babel/helper-module-transforms@7.18.9:
resolution: {integrity: sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==} resolution: {integrity: sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -139,41 +149,41 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/helper-plugin-utils/7.18.9: /@babel/helper-plugin-utils@7.18.9:
resolution: {integrity: sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==} resolution: {integrity: sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/helper-simple-access/7.18.6: /@babel/helper-simple-access@7.18.6:
resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-split-export-declaration/7.18.6: /@babel/helper-split-export-declaration@7.18.6:
resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/helper-string-parser/7.18.10: /@babel/helper-string-parser@7.18.10:
resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/helper-validator-identifier/7.18.6: /@babel/helper-validator-identifier@7.18.6:
resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/helper-validator-option/7.18.6: /@babel/helper-validator-option@7.18.6:
resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/@babel/helpers/7.18.9: /@babel/helpers@7.18.9:
resolution: {integrity: sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==} resolution: {integrity: sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -184,7 +194,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/highlight/7.18.6: /@babel/highlight@7.18.6:
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -193,7 +203,7 @@ packages:
js-tokens: 4.0.0 js-tokens: 4.0.0
dev: true dev: true
/@babel/parser/7.18.13: /@babel/parser@7.18.13:
resolution: {integrity: sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==} resolution: {integrity: sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
@@ -201,7 +211,7 @@ packages:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.18.13: /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.18.13):
resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
peerDependencies: peerDependencies:
@@ -211,17 +221,17 @@ packages:
'@babel/helper-plugin-utils': 7.18.9 '@babel/helper-plugin-utils': 7.18.9
dev: true dev: true
/@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.18.13: /@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.18.13):
resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
dependencies: dependencies:
'@babel/core': 7.18.13 '@babel/core': 7.18.13
'@babel/plugin-transform-react-jsx': 7.18.10_@babel+core@7.18.13 '@babel/plugin-transform-react-jsx': 7.18.10(@babel/core@7.18.13)
dev: true dev: true
/@babel/plugin-transform-react-jsx/7.18.10_@babel+core@7.18.13: /@babel/plugin-transform-react-jsx@7.18.10(@babel/core@7.18.13):
resolution: {integrity: sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==} resolution: {integrity: sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
peerDependencies: peerDependencies:
@@ -231,11 +241,11 @@ packages:
'@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-annotate-as-pure': 7.18.6
'@babel/helper-module-imports': 7.18.6 '@babel/helper-module-imports': 7.18.6
'@babel/helper-plugin-utils': 7.18.9 '@babel/helper-plugin-utils': 7.18.9
'@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.18.13 '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.18.13)
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/template/7.18.10: /@babel/template@7.18.10:
resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -244,7 +254,7 @@ packages:
'@babel/types': 7.18.13 '@babel/types': 7.18.13
dev: true dev: true
/@babel/traverse/7.18.13: /@babel/traverse@7.18.13:
resolution: {integrity: sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==} resolution: {integrity: sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -262,7 +272,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/types/7.18.13: /@babel/types@7.18.13:
resolution: {integrity: sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==} resolution: {integrity: sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
@@ -271,7 +281,7 @@ packages:
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
dev: true dev: true
/@esbuild/linux-loong64/0.14.54: /@esbuild/linux-loong64@0.14.54:
resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [loong64] cpu: [loong64]
@@ -279,7 +289,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/@jridgewell/gen-mapping/0.1.1: /@jridgewell/gen-mapping@0.1.1:
resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dependencies: dependencies:
@@ -287,7 +297,7 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/sourcemap-codec': 1.4.14
dev: true dev: true
/@jridgewell/gen-mapping/0.3.2: /@jridgewell/gen-mapping@0.3.2:
resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dependencies: dependencies:
@@ -296,53 +306,53 @@ packages:
'@jridgewell/trace-mapping': 0.3.15 '@jridgewell/trace-mapping': 0.3.15
dev: true dev: true
/@jridgewell/resolve-uri/3.1.0: /@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dev: true dev: true
/@jridgewell/set-array/1.1.2: /@jridgewell/set-array@1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dev: true dev: true
/@jridgewell/sourcemap-codec/1.4.14: /@jridgewell/sourcemap-codec@1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
dev: true dev: true
/@jridgewell/trace-mapping/0.3.15: /@jridgewell/trace-mapping@0.3.15:
resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==}
dependencies: dependencies:
'@jridgewell/resolve-uri': 3.1.0 '@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/sourcemap-codec': 1.4.14
dev: true dev: true
/@preact/preset-vite/2.3.0_wibdudaz52xr4lhcmpvnys3x3u: /@preact/preset-vite@2.3.0(@babel/core@7.18.13)(preact@10.10.6)(vite@3.0.9):
resolution: {integrity: sha512-0kOuz7wdrQLqrPlyI/Ypw9IWDF2++GGcOHMRBYO5T2w2+dheelaBH+XrIN/okqdsGIflzFIFNyIGubo5BC8wbQ==} resolution: {integrity: sha512-0kOuz7wdrQLqrPlyI/Ypw9IWDF2++GGcOHMRBYO5T2w2+dheelaBH+XrIN/okqdsGIflzFIFNyIGubo5BC8wbQ==}
peerDependencies: peerDependencies:
'@babel/core': 7.x '@babel/core': 7.x
vite: 2.x || 3.x vite: 2.x || 3.x
dependencies: dependencies:
'@babel/core': 7.18.13 '@babel/core': 7.18.13
'@babel/plugin-transform-react-jsx': 7.18.10_@babel+core@7.18.13 '@babel/plugin-transform-react-jsx': 7.18.10(@babel/core@7.18.13)
'@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.18.13 '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.18.13)
'@prefresh/vite': 2.2.8_preact@10.10.6+vite@3.0.9 '@prefresh/vite': 2.2.8(preact@10.10.6)(vite@3.0.9)
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
babel-plugin-transform-hook-names: 1.0.2_@babel+core@7.18.13 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.18.13)
debug: 4.3.4 debug: 4.3.4
kolorist: 1.5.1 kolorist: 1.5.1
resolve: 1.22.1 resolve: 1.22.1
vite: 3.0.9_sass@1.54.8 vite: 3.0.9(sass@1.54.8)
transitivePeerDependencies: transitivePeerDependencies:
- preact - preact
- supports-color - supports-color
dev: true dev: true
/@prefresh/babel-plugin/0.4.3: /@prefresh/babel-plugin@0.4.3:
resolution: {integrity: sha512-fYAWbU1WDSLn108kKY4eDaaeUcnszFqXjgaGKYXNZ5NLulpRTpsrY+Sbfo9q8LDpWrBpqIgzjrwNnvglWI1xNQ==} resolution: {integrity: sha512-fYAWbU1WDSLn108kKY4eDaaeUcnszFqXjgaGKYXNZ5NLulpRTpsrY+Sbfo9q8LDpWrBpqIgzjrwNnvglWI1xNQ==}
dev: true dev: true
/@prefresh/core/1.3.4_preact@10.10.6: /@prefresh/core@1.3.4(preact@10.10.6):
resolution: {integrity: sha512-s7iNsnyJ3lZEUrYIgmVIB/hKtp4U6mdD91a31Zg7Q8M49O0x2KThrbrMQYraoDDrs4STdFB8Zv6bceUguOoX1A==} resolution: {integrity: sha512-s7iNsnyJ3lZEUrYIgmVIB/hKtp4U6mdD91a31Zg7Q8M49O0x2KThrbrMQYraoDDrs4STdFB8Zv6bceUguOoX1A==}
peerDependencies: peerDependencies:
preact: ^10.0.0 preact: ^10.0.0
@@ -350,11 +360,11 @@ packages:
preact: 10.10.6 preact: 10.10.6
dev: true dev: true
/@prefresh/utils/1.1.3: /@prefresh/utils@1.1.3:
resolution: {integrity: sha512-Mb9abhJTOV4yCfkXrMrcgFiFT7MfNOw8sDa+XyZBdq/Ai2p4Zyxqsb3EgHLOEdHpMj6J9aiZ54W8H6FTam1u+A==} resolution: {integrity: sha512-Mb9abhJTOV4yCfkXrMrcgFiFT7MfNOw8sDa+XyZBdq/Ai2p4Zyxqsb3EgHLOEdHpMj6J9aiZ54W8H6FTam1u+A==}
dev: true dev: true
/@prefresh/vite/2.2.8_preact@10.10.6+vite@3.0.9: /@prefresh/vite@2.2.8(preact@10.10.6)(vite@3.0.9):
resolution: {integrity: sha512-yGGa+PKPYPTzMlxgQ8aBgxw9K69I8X4iQ0E6KOcIvls96WKqKLLOYZW9SUgCve446jpUXvc9udviPBZjCeZIIQ==} resolution: {integrity: sha512-yGGa+PKPYPTzMlxgQ8aBgxw9K69I8X4iQ0E6KOcIvls96WKqKLLOYZW9SUgCve446jpUXvc9udviPBZjCeZIIQ==}
peerDependencies: peerDependencies:
preact: ^10.4.0 preact: ^10.4.0
@@ -362,16 +372,16 @@ packages:
dependencies: dependencies:
'@babel/core': 7.18.13 '@babel/core': 7.18.13
'@prefresh/babel-plugin': 0.4.3 '@prefresh/babel-plugin': 0.4.3
'@prefresh/core': 1.3.4_preact@10.10.6 '@prefresh/core': 1.3.4(preact@10.10.6)
'@prefresh/utils': 1.1.3 '@prefresh/utils': 1.1.3
'@rollup/pluginutils': 4.2.1 '@rollup/pluginutils': 4.2.1
preact: 10.10.6 preact: 10.10.6
vite: 3.0.9_sass@1.54.8 vite: 3.0.9(sass@1.54.8)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/@rollup/pluginutils/4.2.1: /@rollup/pluginutils@4.2.1:
resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
engines: {node: '>= 8.0.0'} engines: {node: '>= 8.0.0'}
dependencies: dependencies:
@@ -379,21 +389,21 @@ packages:
picomatch: 2.3.1 picomatch: 2.3.1
dev: true dev: true
/ansi-styles/3.2.1: /ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
color-convert: 1.9.3 color-convert: 1.9.3
dev: true dev: true
/anymatch/3.1.2: /anymatch@3.1.2:
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
dependencies: dependencies:
normalize-path: 3.0.0 normalize-path: 3.0.0
picomatch: 2.3.1 picomatch: 2.3.1
/babel-plugin-transform-hook-names/1.0.2_@babel+core@7.18.13: /babel-plugin-transform-hook-names@1.0.2(@babel/core@7.18.13):
resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==} resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==}
peerDependencies: peerDependencies:
'@babel/core': ^7.12.10 '@babel/core': ^7.12.10
@@ -401,17 +411,17 @@ packages:
'@babel/core': 7.18.13 '@babel/core': 7.18.13
dev: true dev: true
/binary-extensions/2.2.0: /binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
engines: {node: '>=8'} engines: {node: '>=8'}
/braces/3.0.2: /braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
fill-range: 7.0.1 fill-range: 7.0.1
/browserslist/4.21.3: /browserslist@4.21.3:
resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==} resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
@@ -419,14 +429,14 @@ packages:
caniuse-lite: 1.0.30001388 caniuse-lite: 1.0.30001388
electron-to-chromium: 1.4.241 electron-to-chromium: 1.4.241
node-releases: 2.0.6 node-releases: 2.0.6
update-browserslist-db: 1.0.7_browserslist@4.21.3 update-browserslist-db: 1.0.7(browserslist@4.21.3)
dev: true dev: true
/caniuse-lite/1.0.30001388: /caniuse-lite@1.0.30001388:
resolution: {integrity: sha512-znVbq4OUjqgLxMxoNX2ZeeLR0d7lcDiE5uJ4eUiWdml1J1EkxbnQq6opT9jb9SMfJxB0XA16/ziHwni4u1I3GQ==} resolution: {integrity: sha512-znVbq4OUjqgLxMxoNX2ZeeLR0d7lcDiE5uJ4eUiWdml1J1EkxbnQq6opT9jb9SMfJxB0XA16/ziHwni4u1I3GQ==}
dev: true dev: true
/chalk/2.4.2: /chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
@@ -435,7 +445,7 @@ packages:
supports-color: 5.5.0 supports-color: 5.5.0
dev: true dev: true
/chokidar/3.5.3: /chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'} engines: {node: '>= 8.10.0'}
dependencies: dependencies:
@@ -449,28 +459,28 @@ packages:
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
/color-convert/1.9.3: /color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies: dependencies:
color-name: 1.1.3 color-name: 1.1.3
dev: true dev: true
/color-name/1.1.3: /color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true dev: true
/convert-source-map/1.8.0: /convert-source-map@1.8.0:
resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==}
dependencies: dependencies:
safe-buffer: 5.1.2 safe-buffer: 5.1.2
dev: true dev: true
/date-fns/2.29.2: /date-fns@2.29.2:
resolution: {integrity: sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==} resolution: {integrity: sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==}
engines: {node: '>=0.11'} engines: {node: '>=0.11'}
dev: false dev: false
/debug/4.3.4: /debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'} engines: {node: '>=6.0'}
peerDependencies: peerDependencies:
@@ -482,11 +492,11 @@ packages:
ms: 2.1.2 ms: 2.1.2
dev: true dev: true
/electron-to-chromium/1.4.241: /electron-to-chromium@1.4.241:
resolution: {integrity: sha512-e7Wsh4ilaioBZ5bMm6+F4V5c11dh56/5Jwz7Hl5Tu1J7cnB+Pqx5qIF2iC7HPpfyQMqGSvvLP5bBAIDd2gAtGw==} resolution: {integrity: sha512-e7Wsh4ilaioBZ5bMm6+F4V5c11dh56/5Jwz7Hl5Tu1J7cnB+Pqx5qIF2iC7HPpfyQMqGSvvLP5bBAIDd2gAtGw==}
dev: true dev: true
/esbuild-android-64/0.14.54: /esbuild-android-64@0.14.54:
resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -494,7 +504,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-android-arm64/0.14.54: /esbuild-android-arm64@0.14.54:
resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
@@ -502,7 +512,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-darwin-64/0.14.54: /esbuild-darwin-64@0.14.54:
resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -510,7 +520,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-darwin-arm64/0.14.54: /esbuild-darwin-arm64@0.14.54:
resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
@@ -518,7 +528,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-freebsd-64/0.14.54: /esbuild-freebsd-64@0.14.54:
resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -526,7 +536,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-freebsd-arm64/0.14.54: /esbuild-freebsd-arm64@0.14.54:
resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
@@ -534,7 +544,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-32/0.14.54: /esbuild-linux-32@0.14.54:
resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ia32] cpu: [ia32]
@@ -542,7 +552,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-64/0.14.54: /esbuild-linux-64@0.14.54:
resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -550,15 +560,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-arm/0.14.54: /esbuild-linux-arm64@0.14.54:
resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
optional: true
/esbuild-linux-arm64/0.14.54:
resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
@@ -566,7 +568,15 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-mips64le/0.14.54: /esbuild-linux-arm@0.14.54:
resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
optional: true
/esbuild-linux-mips64le@0.14.54:
resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [mips64el] cpu: [mips64el]
@@ -574,7 +584,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-ppc64le/0.14.54: /esbuild-linux-ppc64le@0.14.54:
resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ppc64] cpu: [ppc64]
@@ -582,7 +592,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-riscv64/0.14.54: /esbuild-linux-riscv64@0.14.54:
resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [riscv64] cpu: [riscv64]
@@ -590,7 +600,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-linux-s390x/0.14.54: /esbuild-linux-s390x@0.14.54:
resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [s390x] cpu: [s390x]
@@ -598,7 +608,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-netbsd-64/0.14.54: /esbuild-netbsd-64@0.14.54:
resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -606,7 +616,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-openbsd-64/0.14.54: /esbuild-openbsd-64@0.14.54:
resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -614,7 +624,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-sunos-64/0.14.54: /esbuild-sunos-64@0.14.54:
resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -622,7 +632,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-windows-32/0.14.54: /esbuild-windows-32@0.14.54:
resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [ia32] cpu: [ia32]
@@ -630,7 +640,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-windows-64/0.14.54: /esbuild-windows-64@0.14.54:
resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [x64] cpu: [x64]
@@ -638,7 +648,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild-windows-arm64/0.14.54: /esbuild-windows-arm64@0.14.54:
resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
engines: {node: '>=12'} engines: {node: '>=12'}
cpu: [arm64] cpu: [arm64]
@@ -646,7 +656,7 @@ packages:
requiresBuild: true requiresBuild: true
optional: true optional: true
/esbuild/0.14.54: /esbuild@0.14.54:
resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==} resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
engines: {node: '>=12'} engines: {node: '>=12'}
hasBin: true hasBin: true
@@ -674,147 +684,147 @@ packages:
esbuild-windows-64: 0.14.54 esbuild-windows-64: 0.14.54
esbuild-windows-arm64: 0.14.54 esbuild-windows-arm64: 0.14.54
/escalade/3.1.1: /escalade@3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/escape-string-regexp/1.0.5: /escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}
dev: true dev: true
/estree-walker/2.0.2: /estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true dev: true
/fill-range/7.0.1: /fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
/fsevents/2.3.2: /fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
optional: true optional: true
/function-bind/1.1.1: /function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
/gensync/1.0.0-beta.2: /gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/glob-parent/5.1.2: /glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
dependencies: dependencies:
is-glob: 4.0.3 is-glob: 4.0.3
/globals/11.12.0: /globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/has-flag/3.0.0: /has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/has/1.0.3: /has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
dependencies: dependencies:
function-bind: 1.1.1 function-bind: 1.1.1
/immutable/4.1.0: /immutable@4.1.0:
resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==}
/is-binary-path/2.1.0: /is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
binary-extensions: 2.2.0 binary-extensions: 2.2.0
/is-core-module/2.10.0: /is-core-module@2.10.0:
resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
dependencies: dependencies:
has: 1.0.3 has: 1.0.3
/is-extglob/2.1.1: /is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
/is-glob/4.0.3: /is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dependencies: dependencies:
is-extglob: 2.1.1 is-extglob: 2.1.1
/is-number/7.0.0: /is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'} engines: {node: '>=0.12.0'}
/js-tokens/4.0.0: /js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true dev: true
/jsesc/2.5.2: /jsesc@2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
dev: true dev: true
/json5/2.2.1: /json5@2.2.1:
resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==}
engines: {node: '>=6'} engines: {node: '>=6'}
hasBin: true hasBin: true
dev: true dev: true
/kolorist/1.5.1: /kolorist@1.5.1:
resolution: {integrity: sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==} resolution: {integrity: sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==}
dev: true dev: true
/lodash-es/4.17.21: /lodash-es@4.17.21:
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
dev: false dev: false
/lodash/4.17.21: /lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: false dev: false
/ms/2.1.2: /ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true dev: true
/nanoid/3.3.4: /nanoid@3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true hasBin: true
/node-releases/2.0.6: /node-releases@2.0.6:
resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
dev: true dev: true
/normalize-path/3.0.0: /normalize-path@3.0.0:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
/path-parse/1.0.7: /path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
/picocolors/1.0.0: /picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
/picomatch/2.3.1: /picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
/postcss/8.4.16: /postcss@8.4.16:
resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==} resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
dependencies: dependencies:
@@ -822,16 +832,16 @@ packages:
picocolors: 1.0.0 picocolors: 1.0.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/preact/10.10.6: /preact@10.10.6:
resolution: {integrity: sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog==} resolution: {integrity: sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog==}
/readdirp/3.6.0: /readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'} engines: {node: '>=8.10.0'}
dependencies: dependencies:
picomatch: 2.3.1 picomatch: 2.3.1
/resolve/1.22.1: /resolve@1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true hasBin: true
dependencies: dependencies:
@@ -839,18 +849,18 @@ packages:
path-parse: 1.0.7 path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0 supports-preserve-symlinks-flag: 1.0.0
/rollup/2.77.3: /rollup@2.77.3:
resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==} resolution: {integrity: sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
hasBin: true hasBin: true
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
/safe-buffer/5.1.2: /safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
dev: true dev: true
/sass/1.54.8: /sass@1.54.8:
resolution: {integrity: sha512-ib4JhLRRgbg6QVy6bsv5uJxnJMTS2soVcCp9Y88Extyy13A8vV0G1fAwujOzmNkFQbR3LvedudAMbtuNRPbQww==} resolution: {integrity: sha512-ib4JhLRRgbg6QVy6bsv5uJxnJMTS2soVcCp9Y88Extyy13A8vV0G1fAwujOzmNkFQbR3LvedudAMbtuNRPbQww==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
hasBin: true hasBin: true
@@ -859,38 +869,38 @@ packages:
immutable: 4.1.0 immutable: 4.1.0
source-map-js: 1.0.2 source-map-js: 1.0.2
/semver/6.3.0: /semver@6.3.0:
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
hasBin: true hasBin: true
dev: true dev: true
/source-map-js/1.0.2: /source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
/supports-color/5.5.0: /supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
has-flag: 3.0.0 has-flag: 3.0.0
dev: true dev: true
/supports-preserve-symlinks-flag/1.0.0: /supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
/to-fast-properties/2.0.0: /to-fast-properties@2.0.0:
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/to-regex-range/5.0.1: /to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'} engines: {node: '>=8.0'}
dependencies: dependencies:
is-number: 7.0.0 is-number: 7.0.0
/update-browserslist-db/1.0.7_browserslist@4.21.3: /update-browserslist-db@1.0.7(browserslist@4.21.3):
resolution: {integrity: sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==} resolution: {integrity: sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@@ -901,7 +911,7 @@ packages:
picocolors: 1.0.0 picocolors: 1.0.0
dev: true dev: true
/vite/3.0.9_sass@1.54.8: /vite@3.0.9(sass@1.54.8):
resolution: {integrity: sha512-waYABTM+G6DBTCpYAxvevpG50UOlZuynR0ckTK5PawNVt7ebX6X7wNXHaGIO6wYYFXSM7/WcuFuO2QzhBB6aMw==} resolution: {integrity: sha512-waYABTM+G6DBTCpYAxvevpG50UOlZuynR0ckTK5PawNVt7ebX6X7wNXHaGIO6wYYFXSM7/WcuFuO2QzhBB6aMw==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true hasBin: true
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

-25
View File
@@ -1,25 +0,0 @@
// import { createContext } from 'preact'
// import { toChildArray } from 'preact'
// import { useContext, useState } from 'preact/hooks'
// const AnimationContext = createContext()
// export const useAnimation = animation => {
// const [styles, setStyles] = useState({})
// const start = () => {
// setStyles({ animation })
// }
// return [
// start,
// {
// styles,
// onAnimationEnd: e => {
// console.log('animation end')
// },
// },
// ]
// }
// export const Animation = ({ animation, children }) => {}
+3 -13
View File
@@ -1,28 +1,18 @@
import { useRef, useState } from 'preact/hooks'
import { Icon } from './Icon.jsx' import { Icon } from './Icon.jsx'
let ids = 0
function generateId() {
return 'combo-id-' + ids++
}
export const ComboBox = ({ options, value, setValue }) => { export const ComboBox = ({ options, value, setValue }) => {
const [uid] = useState(() => generateId())
const selectRef = useRef()
return ( return (
<div class="input-combo"> <div class="input-combo">
<select ref={selectRef} id={uid} onInput={e => setValue(e.target.value)}> <select onInput={e => setValue(e.target.value)}>
{options.map(option => ( {options.map(option => (
<option value={option.value} selected={option.value === value}> <option value={option.value} selected={option.value === value}>
{option.label} {option.label}
</option> </option>
))} ))}
</select> </select>
<label class="icon" for={uid}> <div class="icon">
<Icon name="expand_more" /> <Icon name="expand_more" />
</label> </div>
</div> </div>
) )
} }
+5 -1
View File
@@ -5,7 +5,11 @@ export const CompoundButton = ({ options, value, setValue }) => {
<div class="compound"> <div class="compound">
{options.map(option => ( {options.map(option => (
<button <button
class={withClasses(['radio', option.value === value && 'selected'])} class={withClasses([
'radio',
option.value === value && 'selected',
option.icon && 'icon',
])}
onClick={() => setValue(option.value)} onClick={() => setValue(option.value)}
> >
{option.label} {option.label}
-12
View File
@@ -1,12 +0,0 @@
import { Icon } from './Icon.jsx'
export const ToolOverlay = ({ visibility, toggleVisibility, onClose }) => (
<div class="overlay">
<button class="icon primary" onClick={toggleVisibility}>
<Icon name={visibility ? 'visibility_off' : 'visibility'} />
</button>
<button class="icon" onClick={onClose}>
<Icon name="close" />
</button>
</div>
)
+33
View File
@@ -0,0 +1,33 @@
import { useRef } from 'preact/hooks'
import { Icon } from './Icon.jsx'
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
export const DatePicker = ({ date, setDate }) => {
const input = useRef()
const [year, month, day] = date.split('T')[0].split('-')
return (
<div
class="date-picker"
onClick={() =>
isSafari ? input.current.focus() : input.current.showPicker()
}
>
<input
ref={input}
type="date"
value={`${year}-${month}-${day}`}
onChange={e => setDate(new Date(e.target.value).toISOString())}
/>
<div class="date-picker-render">
<div class="date">
{day}/{month}/{year}
</div>
<div class="calendar">
<Icon name="calendar_month" />
</div>
</div>
</div>
)
}
+34 -369
View File
@@ -1,376 +1,41 @@
// import { Courses } from './view/Courses.jsx'
// Modes import { Schedule } from './view/Schedule.jsx'
//
import { differenceInMinutes, format, startOfDay } from 'date-fns' export const MODE_COURSES = 'course'
export const MODE_WORKWEEK = 'work-week'
import _ from 'lodash' export const MODE_SCHEDULE = 'schedule'
import { useEffect, useRef, useState } from 'preact/hooks' export const MODE_WORKWEEK_GRID = 'work-week-grid'
import { layoutIntervals } from '../interval-layout.js' export const MODE_WORKWEEK_TRANSPOSE = 'work-week-transpose'
const WEEK_DAYS = ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato']
function hashString(str, seed = 0) {
let h1 = 0xdeadbeef ^ seed,
h2 = 0x41c6ce57 ^ seed
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i)
h1 = Math.imul(h1 ^ ch, 2654435761)
h2 = Math.imul(h2 ^ ch, 1597334677)
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
function normalizeCourseName(name) {
return name
.split(' ')
.map(word => word.toLowerCase())
.map(word => {
if (word.trim().length === 0) return word
return /(^del|^nel|^di$|^dei$|^con$|^alla$|^per$|^e$|^la$)/.test(word)
? word
: word[0].toUpperCase() + word.slice(1)
})
.join(' ')
.replaceAll('Ii', 'II')
.replaceAll('Iii', 'III')
.replaceAll(/'(.)/g, ({}, letter) => "'" + letter.toUpperCase())
}
const WorkWeekView = ({ events }) => {
const eventsByWeekday = _.groupBy(events, event => event.start.getDay())
// For each weekday compute the interval layout
const rowLayouts = _.mapValues(eventsByWeekday, events =>
layoutIntervals(
events.map(e => ({
start: differenceInMinutes(e.start, startOfDay(e.start)),
end: differenceInMinutes(e.end, startOfDay(e.start)),
data: e,
}))
)
)
return (
<div class="work-week-h-view">
<div class="week">
{WEEK_DAYS.slice(1, 6).map((label, index) => (
<div class="day" style={{ '--size': rowLayouts[index + 1]?.length ?? 0 }}>
{label}
</div>
))}
</div>
<div class="events">
<div class="header">
<div class="label" style={{ 'grid-column': '2 / span 2' }}>
9:00 &ndash; 11:00
</div>
<div class="label" style={{ 'grid-column': '4 / span 2' }}>
11:00 &ndash; 13:00
</div>
<div class="label" style={{ 'grid-column': '7 / span 2' }}>
14:00 &ndash; 16:00
</div>
<div class="label" style={{ 'grid-column': '9 / span 2' }}>
16:00 &ndash; 18:00
</div>
</div>
<div class="days">
{Object.values(rowLayouts).map(layout => (
<div class="day" style={{ '--size': layout.length }}>
{layout.map((events, rowIndex) =>
events.map(event => {
const Local = () => {
const eventRef = useRef()
const updateMinWidth = () => {
eventRef.current.style.minWidth =
eventRef.current.offsetWidth + 'px'
}
useEffect(() => {
if (eventRef.current) {
setTimeout(updateMinWidth, 100)
window.addEventListener('resize', updateMinWidth)
return () => {
window.removeEventListener(
'resize',
updateMinWidth
)
}
}
}, [eventRef.current])
return (
<div
class="event"
style={{
'--row': rowIndex + 1,
'--start': event.start / 60 - 7,
'--size': (event.end - event.start) / 60,
'--hue':
(Math.abs(
hashString('seed3' + event.data.name)
) %
360) +
'deg',
}}
ref={eventRef}
>
{normalizeCourseName(event.data.name)}
</div>
)
}
return <Local />
})
)}
</div>
))}
</div>
</div>
</div>
)
}
const WorkWeekVerticalView = ({ events, selection, setSelection, hideOtherCourses }) => {
const selectionSet = new Set(selection)
// const base = {
// 1: [],
// 2: [],
// 3: [],
// 4: [],
// 5: [],
// }
const eventsByWeekday = _.groupBy(
!hideOtherCourses ? events : events.filter(e => selectionSet.has(e.name)),
event => event.start.getDay()
)
// const dayIntervalLayout = _.mapValues(Object.assign(base, eventsByWeekday), events =>
const dayIntervalLayout = _.mapValues(eventsByWeekday, events =>
layoutIntervals(
events.map(e => ({
start: differenceInMinutes(e.start, startOfDay(e.start)),
end: differenceInMinutes(e.end, startOfDay(e.start)),
data: e,
}))
)
)
const [currentlyHovered, setCurrentlyHovered] = useState(null)
const element = useRef()
useEffect(() => {
if (element.current) {
const l = e => {
const $event = e.target.closest('.event')
if ($event) {
setCurrentlyHovered($event.dataset.eventId)
} else {
setCurrentlyHovered(null)
}
}
element.current.addEventListener('mousemove', l)
element.current.addEventListener('mouseleave', l)
return () => {
element.current.removeEventListener('mousemove', l)
element.current.removeEventListener('mouseleave', l)
}
}
}, [element.current])
return (
<div class="work-week-v-view" ref={element}>
<div class="pivot"></div>
<div class="left-header">
<div class="blocks">
<div
class="block skip-border"
style={{
'--start': 9 - 7,
'--size': 2,
}}
>
9:00 &ndash; 11:00
</div>
<div
class="block"
style={{
'--start': 11 - 7,
'--size': 2,
}}
>
11:00 &ndash; 13:00
</div>
<div
class="block skip-border"
style={{
'--start': 14 - 7,
'--size': 2,
}}
>
14:00 &ndash; 16:00
</div>
<div
class="block"
style={{
'--start': 16 - 7,
'--size': 2,
}}
>
16:00 &ndash; 18:00
</div>
</div>
</div>
{Object.entries(dayIntervalLayout).map(([index, layout]) => (
<div class="day" style={{ '--size': Math.max(1, layout.length) }}>
<div class="top-header">{WEEK_DAYS[parseInt(index)]}</div>
<div class="events">
{layout.map((events, stackIndex) => (
<>
{events.map(event => (
<div
class={
'event' +
(currentlyHovered === event.data.name
? ' highlight'
: '') +
(selectionSet.has(event.data.name) ? ' selected' : '')
}
data-event-id={event.data.name}
style={{
'--start': event.start / 60 - 7,
'--stack': stackIndex + 1,
'--size': (event.end - event.start) / 60,
'--hue':
(Math.abs(hashString('seed3' + event.data.name)) %
360) +
'deg',
}}
onClick={() => {
if (!selectionSet.has(event.data.name))
setSelection([...selection, event.data.name])
else
setSelection(
selection.filter(
name => event.data.name !== name
)
)
}}
>
<div class="title">
{normalizeCourseName(event.data.name)}
</div>
<div class="aula">{event.data.aula}</div>
</div>
))}
</>
))}
{/* Grid Tracks */}
{[1, 3, 5].map(i => (
<div class="grid-line-h" style={{ '--track': i }}></div>
))}
{[6, 8, 10].map(i => (
<div class="grid-line-h" style={{ '--track': i }}></div>
))}
</div>
</div>
))}
</div>
)
}
const CourseView = ({ events, selection, setSelection, hideOtherCourses }) => {
const selectionSet = new Set(selection)
const visibleEvents = !hideOtherCourses ? events : events.filter(e => selectionSet.has(e.name))
const eventsByCourse = _.groupBy(_.sortBy(visibleEvents, 'name'), 'name')
const [currentlyHovered, setCurrentlyHovered] = useState(null)
const element = useRef()
useEffect(() => {
if (element.current) {
const l = e => {
const $course = e.target.closest('.course')
if ($course) {
setCurrentlyHovered($course.dataset.courseId)
} else {
setCurrentlyHovered(null)
}
}
element.current.addEventListener('mousemove', l)
element.current.addEventListener('mouseleave', l)
return () => {
element.current.removeEventListener('mousemove', l)
element.current.removeEventListener('mouseleave', l)
}
}
}, [element.current])
return (
<div class="course-view" ref={element}>
<div class="wrap-container">
{Object.entries(eventsByCourse).map(([name, courseEvents]) => (
<div
class={
'course' +
(currentlyHovered === name ? ' highlight' : '') +
(selectionSet.has(name) ? ' selected' : '')
}
data-course-id={name}
onClick={() => {
if (!selectionSet.has(name)) setSelection([...selection, name])
else setSelection(selection.filter(n => n !== name))
}}
>
<div class="title">{normalizeCourseName(name)}</div>
<div class="docenti">{courseEvents[0].docenti.join(', ')}</div>
<div class="events">
{courseEvents.map(course => (
<div>
{WEEK_DAYS[course.start.getDay()]}{' '}
{format(course.start, 'H:mm')} &ndash;
{format(course.end, 'H:mm')} {course.aula}
</div>
))}
</div>
</div>
))}
</div>
</div>
)
}
//
// EventsView
//
const viewModeMap = { const viewModeMap = {
'work-week-h': WorkWeekView, [MODE_COURSES]: Courses,
'work-week-v': WorkWeekVerticalView, [MODE_SCHEDULE]: Schedule,
'course': CourseView,
} }
export const EventsView = ({ mode, ...viewProps }) => { // export const EventsView = ({ mode, ...viewProps }) => {
const Mode = viewModeMap[mode] // const Mode = viewModeMap[mode]
//
// return (
// <div class="events-view">
// <Mode {...viewProps} />
// </div>
// )
// }
return ( export const EventsView = ({ mode, source, ...viewProps }) => {
<div class="events-view"> // const Mode = viewModeMap[mode]
<Mode {...viewProps} />
</div> if (source === 'orario') {
) return (
<div class="events-view">
<Schedule source={source} {...viewProps} />
</div>
)
} else {
return (
<div class="events-view">
<Courses source={source} {...viewProps} />
</div>
)
}
} }
+8 -37
View File
@@ -1,46 +1,17 @@
import { ComboBox } from './ComboBox.jsx' import { ComboBox } from './ComboBox.jsx'
import {
MODE_COURSES,
MODE_SCHEDULE,
MODE_WORKWEEK,
MODE_WORKWEEK_GRID,
} from './EventsView.jsx'
import { DatePicker } from './DatePicker.jsx'
import { Help } from './Help.jsx' import { Help } from './Help.jsx'
import { Icon } from './Icon.jsx' import { Icon } from './Icon.jsx'
export const HamburgerMenu = ({ onClose, mode, setMode, source, setSource }) => { export const HamburgerMenu = ({ date, setDate, onClose, theme, setTheme }) => {
return ( return (
<div class="menu"> <div class="menu">
<div class="header">
<button class="flat icon" onClick={onClose}>
<Icon name="close" />
</button>
<div class="item logo">
<img src="logo-circuit-board.svg" alt="logo" /> / <span>Orario</span>
</div>
</div>
<div class="options">
<div class="label">Gruppo Corsi</div>
<ComboBox
value={source}
setValue={setSource}
options={[
{ value: 'anno-1', label: 'I' },
{ value: 'anno-2', label: 'II' },
{ value: 'anno-3', label: 'III' },
{ value: 'magistrale', label: 'Magistrale' },
{ value: 'tutti', label: 'Tutti' },
]}
/>
<div class="label">Visualizzazione</div>
<ComboBox
value={mode}
setValue={setMode}
options={[
{ value: 'course', label: 'Corsi' },
{ value: 'work-week-v', label: 'Settimana' },
// {
// value: 'work-week-h',
// label: 'Settimana (Trasposto)',
// },
]}
/>
</div>
<hr />
<div class="help"> <div class="help">
<h2> <h2>
<Icon name="info" /> <Icon name="info" />
+22 -15
View File
@@ -2,38 +2,45 @@ import { Icon } from './Icon.jsx'
export const Help = ({}) => ( export const Help = ({}) => (
<> <>
<h3>Selezione Corsi</h3> <h3>Visualizzazione Corsi</h3>
<p> <p>
Per visualizzare solo una selezione dei corsi disponibili, clicca su quelli che ti Per visualizzare i corsi che ti interessano nella tabella dell'orario, devi
interessano e poi nascondi gli altri con il tasto <Icon name="visibility" /> che prima selezionarli. Puoi selezionare dei corsi cliccandoli, cercandoli nelle
comparirà in basso a destra. sezioni Primo anno (<b>I</b>), Secondo anno (<b>II</b>), Terzo anno (
<b>III</b>), Magistrale (<b>M</b>), o Tutti.
</p> </p>
<p> <p>
Per vedere l'orario settimanale, clicca su <b>Settimana</b>, che mostrerà un calendario Una volta compiuta la selezione, è possibile vedere la tabella delle lezioni
con i corsi attualmente selezionati. andando nella visualizzazione Orario (
<Icon name="calendar_view_month" />)
</p> </p>
<p> <p>
La selezione effettuata verrà preservata dalla visualizzazione <b>Corsi</b> a quella Per via di eventuali preferenze personali, è possibile cambiare l'orientazione
Settimana, permettendo di individuare eventuali sovrapposizioni di orari. della tabella Orario trasponendola, utilizzando il pulsante Trasponi (
<Icon name="switch_left" style="transform: rotate(-45deg)" />)
</p> </p>
<p> <p>
I corsi sono raggruppati per: primo, secondo, terzo anno (<b>I</b>,<b>II</b>,<b>III</b>) È anche possibile visualizzare in uno specchietto riassuntivo soltanto i corsi
e magistrale. Alternativamente, puoi scegliere fra tutti i corsi disponibili cliccando selezionati, andando nella visualizzazione Lista (
su <b>Tutti</b>. <Icon name="list" />)
</p> </p>
<h3>Stampa</h3> <h3>Stampa</h3>
<p> <p>
Da desktop puoi stampare l'orario attualmente visibile con il bottone <Icon name="print" /> (è Da desktop puoi stampare l'orario attualmente visibile con il bottone{' '}
consigliato controllare le opzioni di stampa per un risultato soddisfacente). <Icon name="print" /> (è consigliato controllare le opzioni di stampa per
ottenere un risultato soddisfacente).
</p> </p>
<h3>Bug &amp; Contatti</h3> <h3>Bug &amp; Contatti</h3>
<p> <p>
In caso di bug puoi creare una issue sulla repo git del progetto{' '} In caso di bug puoi creare una issue sulla repo git del progetto{' '}
<a href="https://git.phc.dm.unipi.it/phc/orario"> <a href="https://git.phc.dm.unipi.it/phc/orario">
https://git.phc.dm.unipi.it/phc/orario https://git.phc.dm.unipi.it/phc/orario
</a>
, contattarci all'indirizzo{' '}
<a href="mailto:macchinisti@lists.dm.unipi.it">
macchinisti@lists.dm.unipi.it
</a>{' '} </a>{' '}
oppure puoi contattarci direttamente all'indirizzo{' '} oppure passare direttamente in PHC.
<a href="mailto:macchinisti@lists.dm.unipi.it">macchinisti@lists.dm.unipi.it</a>.
</p> </p>
</> </>
) )
+40
View File
@@ -0,0 +1,40 @@
import { CompoundButton } from './CompoundButton.jsx'
import { Icon } from './Icon.jsx'
export const OptionBar = ({ view, setView }) => {
return (
<div class="option-bar">
<div class="option-group">
<div class="item option">
<CompoundButton
options={[
{ value: 'anno-1', label: 'I' },
{ value: 'anno-2', label: 'II' },
{ value: 'anno-3', label: 'III' },
{ value: 'magistrale', label: 'M' },
{ value: 'tutti', label: 'Tutti' },
]}
value={view}
setValue={setView}
/>
</div>
<CompoundButton
options={[
{
value: 'orario',
label: <Icon name="calendar_view_month" />,
icon: true,
},
{
value: 'lista',
label: <Icon name="list" />,
icon: true,
},
]}
value={view}
setValue={setView}
/>
</div>
</div>
)
}
+12 -8
View File
@@ -9,17 +9,21 @@ export const Popup = ({ title, children, onClose }) => {
class="popup-container" class="popup-container"
ref={popupLeaveRegionRef} ref={popupLeaveRegionRef}
onClick={e => onClick={e =>
popupLeaveRegionRef.current && popupLeaveRegionRef.current === e.target && onClose() popupLeaveRegionRef.current &&
popupLeaveRegionRef.current === e.target &&
onClose()
} }
> >
<div class="popup"> <div class="popup-wrapper">
<div class="header"> <div class="popup">
<div class="title">{title}</div> <div class="header">
<button class="flat icon" onClick={onClose}> <div class="title">{title}</div>
<Icon name="close" /> <button class="flat icon" onClick={onClose}>
</button> <Icon name="close" />
</button>
</div>
<div class="content">{children}</div>
</div> </div>
<div class="content">{children}</div>
</div> </div>
</div> </div>
) )
+18
View File
@@ -0,0 +1,18 @@
import { DatePicker } from './DatePicker.jsx'
import { Icon } from './Icon.jsx'
export const SettingsBar = ({ theme, setTheme, date, setDate }) => {
return (
<div class="settings-bar">
<div class="settings-group">
<button
class="icon"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
</button>
<DatePicker date={date} setDate={setDate} />
</div>
</div>
)
}
+13
View File
@@ -0,0 +1,13 @@
import { Icon } from './Icon.jsx'
import { MODE_COURSES } from './EventsView.jsx'
export const ToolOverlay = ({ mode, toggleMode, onClose }) => (
<div class="overlay">
<button class="icon primary" onClick={toggleMode}>
<Icon name={mode === MODE_COURSES ? 'calendar_month' : 'view_list'} />
</button>
<button class="icon" onClick={onClose}>
<Icon name="close" />
</button>
</div>
)
+34 -18
View File
@@ -1,12 +1,26 @@
import { CompoundButton } from './CompoundButton.jsx' import { CompoundButton } from './CompoundButton.jsx'
import { DatePicker } from './DatePicker.jsx'
import { Icon } from './Icon.jsx' import { Icon } from './Icon.jsx'
export const Toolbar = ({ mode, setMode, source, setSource, onShowMenu, onHelp }) => { export const Toolbar = ({
source,
setSource,
date,
setDate,
showMobileMenu,
setShowMobileMenu,
onHelp,
theme,
setTheme,
}) => {
return ( return (
<div class="toolbar"> <div class="toolbar">
<div class="mobile"> <div class="mobile">
<button class="flat icon" onClick={onShowMenu}> <button
<Icon name="menu" /> class="flat icon"
onClick={() => setShowMobileMenu(!showMobileMenu)}
>
<Icon name={`${showMobileMenu ? 'close' : 'menu'}`} />
</button> </button>
</div> </div>
<div class="item logo"> <div class="item logo">
@@ -26,32 +40,34 @@ export const Toolbar = ({ mode, setMode, source, setSource, onShowMenu, onHelp }
setValue={setSource} setValue={setSource}
/> />
</div> </div>
</div>
<div class="option-group">
<div class="item option"> <div class="item option">
<CompoundButton <CompoundButton
options={[ options={[
{ value: 'course', label: 'Corsi' }, { value: 'orario', label: 'Orario' },
{ value: 'work-week-v', label: 'Settimana' }, { value: 'lista', label: 'Lista' },
// {
// value: 'work-week-h',
// label: (
// <>
// <Icon name="warning" />
// Settimana<sup>T</sup>
// </>
// ),
// },
]} ]}
value={mode} value={source}
setValue={setMode} setValue={setSource}
/> />
</div> </div>
</div>
<div class="option-group">
<DatePicker date={date} setDate={setDate} />
</div>
<div class="option-group">
<div class="item option"> <div class="item option">
<button class="icon" onClick={() => window.print()}> <button class="icon" onClick={() => window.print()}>
<Icon name="print" /> <Icon name="print" />
</button> </button>
</div> </div>
<div class="item option">
<button
class="icon"
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
>
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
</button>
</div>
<div class="item option"> <div class="item option">
<button class="icon" onClick={onHelp}> <button class="icon" onClick={onHelp}>
<Icon name="question_mark" /> <Icon name="question_mark" />
+95
View File
@@ -0,0 +1,95 @@
import { format } from 'date-fns'
import _ from 'lodash'
import { useEffect, useRef, useState } from 'preact/hooks'
import { prettyCourseName, WEEK_DAYS } from '../../utils.jsx'
import { Icon } from '../Icon.jsx'
export const Courses = ({
source,
timetables,
selection,
setSelection,
hideOtherCourses,
}) => {
const events = timetables[source]
const selectionSet = new Set(selection)
const visibleEvents = hideOtherCourses
? events.filter(e => selectionSet.has(e.id))
: events
const eventsByCourse = _.groupBy(_.sortBy(visibleEvents, 'id'), 'id')
const profsPerCourse = _.mapValues(eventsByCourse, events =>
_.uniq(events.flatMap(event => event.docenti))
)
const [currentlyHovered, setCurrentlyHovered] = useState(null)
const element = useRef()
useEffect(() => {
if (element.current) {
const l = e => {
const isMobile = window.matchMedia('(pointer: coarse)').matches
const $course = e.target.closest('.course')
if ($course && !isMobile) {
setCurrentlyHovered($course.dataset.courseId)
} else {
setCurrentlyHovered(null)
}
}
element.current.addEventListener('mousemove', l)
element.current.addEventListener('mouseleave', l)
return () => {
element.current.removeEventListener('mousemove', l)
element.current.removeEventListener('mouseleave', l)
}
}
}, [element.current])
return (
<div class="course-view" ref={element}>
{hideOtherCourses && selection.length === 0 && (
<div class="warning">
<p>Non hai ancora selezionato nessun corso.</p>
<p>
Clicca sui corsi nelle altre visuali per selezionarli e
visualizzarli nella lista
</p>
</div>
)}
<div class="wrap-container">
{Object.entries(eventsByCourse).map(([id, courseEvents]) => (
<div
class={
'course' +
(currentlyHovered === id ? ' highlight' : '') +
(selectionSet.has(id) ? ' selected' : '')
}
data-course-id={id}
onClick={() => {
if (!selectionSet.has(id)) setSelection([...selection, id])
else setSelection(selection.filter(selId => selId !== id))
}}
>
<div class="title">{prettyCourseName(courseEvents[0].name)}</div>
<div class="docenti">{profsPerCourse[id].join(', ')}</div>
<div class="events">
{courseEvents.map(course => (
<div>
{WEEK_DAYS[course.start.getDay()]}{' '}
{format(course.start, 'H:mm')}&ndash;
{format(course.end, 'H:mm')} {course.aule.join(', ')}
</div>
))}
</div>
</div>
))}
</div>
</div>
)
}
+266
View File
@@ -0,0 +1,266 @@
import { useEffect, useRef, useState } from 'preact/hooks'
import _ from 'lodash'
import { differenceInMinutes, startOfDay } from 'date-fns'
import { WEEK_DAYS_SHORT, prettyCourseName, usePersistentState } from '../../utils.jsx'
import { layoutEvents, layoutIntervals } from '../../interval-layout.js'
import { Popup } from '../Popup.jsx'
import { Icon } from '../Icon.jsx'
const TransposePopup = ({ onClose }) => {
return (
<Popup
title={
<>
<Icon name="info" /> Attenzione! La tabella è stata trasposta!
</>
}
onClose={onClose}
>
<p>A grande richiesta popolare abbiamo trasposto la tabella dell'orario!</p>
<p>
Assicurati quindi di leggerla correttamente (dall'alto verso il basso
invece che da sinistra verso destra).
</p>
<p>
Se preferisci utilizzare la versione vecchia, puoi utilizzare il pulsante
Trasponi <Icon name="switch_left" style="transform: rotate(-45deg)" />{' '}
nell'origine della tabella per trasporla. Questa scelta verrà salvata nei
cookie e verrà ricordata in futuro
</p>
</Popup>
)
}
const NoCourseWarning = () => {
return (
<div class="warning">
<p>Non hai ancora selezionato nessun corso.</p>
<p>
Clicca sui corsi nelle altre visuali per selezionarli e visualizzarli
nell'orario
</p>
</div>
)
}
const Layout = ({ layout, day, colors }) => {
return (
<>
{layout.map(block => (
<div
class="event-block-wrapper"
style={{
'--time-start': block.start,
'--time-end': block.end,
'--day-position': day,
}}
>
<div class="event-block">
{block.events.map((event, index) => (
<div
class="event-wrapper"
style={{
'--block-size': block.end - block.start,
'--size': event.end - event.start,
'--relative-start': event.start - block.start,
'--index': event.index,
'--of': block.layers,
'--color': `var(--event-${colors[event.id]})`,
}}
>
<div class="event">
{event.aule.map(aula => (
<div>{aula.replace(/^Fib /, '')}</div>
))}
</div>
</div>
))}
</div>
</div>
))}
</>
)
}
const ScheduleGrid = ({
orientation,
setOrientation,
weekStart,
weekEnd,
dayBlocksLayout,
colors,
}) => {
return (
<div
class={`grid ${orientation}`}
style={{
'--time-slots': weekEnd - weekStart,
}}
>
<div class="transpose-button">
<button
class="small"
onClick={() =>
setOrientation(
orientation === 'original' ? 'transposed' : 'original'
)
}
>
<Icon name="switch_left" style="transform: rotate(-45deg)" />
</button>
</div>
{[1, 2, 3, 4, 5].map(n => (
<>
<div class="day-label" style={`--position: ${n + 1}`}>
{WEEK_DAYS_SHORT[n]}
</div>
<div class="day-line" style={`--position: ${n + 1}`}></div>
</>
))}
{[9, 11, 14, 16].map(n => (
<div
class="time-label"
style={{
'--position': n * 2 - weekStart,
}}
>
{n}-{n + 2}
</div>
))}
<div class="time-line" style="--position: 0"></div>
{[9, 11, 13, 14, 16, 18].map(n => (
<>
{n * 2 > weekStart && n * 2 < weekEnd && (
<div
class="time-line"
style={{
'--position': n * 2 - weekStart,
}}
></div>
)}
</>
))}
{Object.entries(dayBlocksLayout).map(([day, layout]) => (
<Layout layout={layout} day={day} colors={colors} />
))}
</div>
)
}
const ScheduleLegend = ({ courses, colors }) => {
return (
<div class="legend">
{courses.map(course => (
<>
<div
class="color"
style={{
'--color': `var(--event-${colors[course.id]})`,
}}
></div>
<div class="name">{prettyCourseName(course.name)}</div>
</>
))}
</div>
)
}
const ScheduleCard = ({
orientation,
setOrientation,
weekStart,
weekEnd,
dayBlocksLayout,
courses,
colors,
}) => {
return (
<div class="schedule-card">
<ScheduleGrid
orientation={orientation}
setOrientation={setOrientation}
weekStart={weekStart}
weekEnd={weekEnd}
dayBlocksLayout={dayBlocksLayout}
colors={colors}
/>
<ScheduleLegend courses={courses} colors={colors} />
</div>
)
}
export const Schedule = ({ timetables, selection }) => {
const [hasSeenTranspose, setHasSeenTranspose] = usePersistentState(
'transpose_info',
'false'
)
const [orientation, setOrientation] = usePersistentState('orientation', 'original')
const colorList = ['red', 'purple', 'blue', 'yellow', 'green', 'orange', 'lightblue']
const allEvents = timetables['tutti']
const selectionSet = new Set(selection)
const events = allEvents
.filter(e => selectionSet.has(e.id))
.map(e => ({
...e,
day: e.start.getDay(),
start: differenceInMinutes(e.start, startOfDay(e.start)),
end: differenceInMinutes(e.end, startOfDay(e.start)),
}))
const weekStart = Math.min(...events.map(e => e.start), 9 * 60) / 30
const weekEnd = Math.max(...events.map(e => e.end), 18 * 60) / 30
const relativeEvents = events.map(e => ({
...e,
start: Math.round(e.start / 30 - weekStart),
end: Math.round(e.end / 30 - weekStart),
}))
const courses = _.uniqBy(events, event => event.id)
const colors = Object.fromEntries(
courses.map((course, index) => {
return [course.id, colorList[index % colorList.length]]
})
)
const base = {
1: [],
2: [],
3: [],
4: [],
5: [],
}
const eventsByWeekday = {
...base,
..._.groupBy(relativeEvents, event => event.day),
}
const dayBlocksLayout = _.mapValues(eventsByWeekday, dayEvents =>
layoutEvents(dayEvents)
)
return (
<>
{hasSeenTranspose === 'false' && (
<TransposePopup onClose={() => setHasSeenTranspose('true')} />
)}
<div class="schedule-view">
{selection.length === 0 && <NoCourseWarning />}
<ScheduleCard
orientation={orientation}
setOrientation={setOrientation}
weekStart={weekStart}
weekEnd={weekEnd}
dayBlocksLayout={dayBlocksLayout}
courses={courses}
colors={colors}
/>
</div>
</>
)
}
+49
View File
@@ -34,6 +34,55 @@ export function layoutIntervals(intervals, { tight } = {}) {
return stack.map(({ intervals }) => intervals) return stack.map(({ intervals }) => intervals)
} }
function layoutBlockEvents(events) {
events.sort((a, b) => a.start - b.start)
let result = []
for (const event of events) {
let viableIndex = 0
while (
result.filter(
e => e.index === viableIndex && e.start < event.end && event.start < e.end
).length !== 0
) {
viableIndex += 1
}
result.push({ ...event, index: viableIndex })
}
return result
}
export function layoutEvents(events) {
const overlap = (event, block) => event.start < block.end && block.start < event.end
events.sort((a, b) => a.start - b.start)
let layout = []
for (const event of events) {
const blocks = layout.filter(block => overlap(event, block))
if (blocks.length > 0) {
layout = layout.filter(block => !overlap(event, block))
layout.push({
start: Math.min(event.start, ...blocks.map(block => block.start)),
end: Math.max(event.end, ...blocks.map(block => block.end)),
events: blocks.flatMap(block => block.events).concat([event]),
})
} else {
layout.push({ start: event.start, end: event.end, events: [event] })
}
}
return layout.map(block => {
const events = layoutBlockEvents(block.events)
return {
...block,
layers: Math.max(...events.map(event => event.index)) + 1,
events: events,
}
})
}
// // // //
// // Testing... // // Testing...
// // // //
+266 -123
View File
@@ -1,156 +1,299 @@
import _ from 'lodash' import _ from 'lodash'
import { render } from 'preact' import { render } from 'preact'
import { useEffect, useState } from 'preact/hooks' import { useEffect, useState } from 'preact/hooks'
import { ToolOverlay } from './components/CourseVisibility.jsx'
import { EventsView } from './components/EventsView.jsx' // import { ToolOverlay } from './components/ToolOverlay.jsx'
//
// import {
// EventsView,
// MODE_COURSES,
// MODE_SCHEDULE,
// } from './components/EventsView.jsx'
import { Courses } from './components/view/Courses.jsx'
import { Schedule } from './components/view/Schedule.jsx'
import { HamburgerMenu } from './components/HamburgerMenu.jsx' import { HamburgerMenu } from './components/HamburgerMenu.jsx'
import { Help } from './components/Help.jsx' import { Help } from './components/Help.jsx'
import { Icon } from './components/Icon.jsx' import { Icon } from './components/Icon.jsx'
import { Popup } from './components/Popup.jsx' import { Popup } from './components/Popup.jsx'
import { Toolbar } from './components/Toolbar.jsx' import { Toolbar } from './components/Toolbar.jsx'
import { OptionBar } from './components/OptionBar.jsx'
import {
prettyAulaName,
prettyProfName,
clearOldPersistentStates,
usePersistentState,
} from './utils.jsx'
import { SettingsBar } from './components/SettingsBar.jsx'
// Che fanno queste due righe?
window._ = _ window._ = _
window.dataBuffer = {} window.dataBuffer = {}
const CALENDAR_IDS = { // NOTA: magistrale *non* è quello con i corsi a cavallo
'anno-1': ['6308cfcb1df5cb026699ce32'], const TIMETABLE_IDS = {
'anno-2': ['6308e2dc09352a0208fefdd9'], 'anno-1': '687e66d62d13e6001edd366d',
'anno-3': ['6308e42a1df5cb026699ced4'], 'anno-2': '687e681301ee9300198320e6',
'magistrale': ['6308e8ea0c34e703bb1f7e85'], 'anno-3': '687e68bb01ee9300198320eb',
'tutti': [ 'magistrale': '687e6a9f96ea080019d439d5',
'6308cfcb1df5cb026699ce32',
'6308e2dc09352a0208fefdd9',
'6308e42a1df5cb026699ced4',
'6308e8ea0c34e703bb1f7e85',
],
} }
async function loadEventi(ids) { // const DEFAULT_DATE_RANGE = {
const calendari = await Promise.all( // from: '2023-10-09T00:00:00.000Z',
ids.map(async id => { // to: '2023-10-14T00:00:00.000Z',
// Almost directly copy-pasted from Chrome Dev Tools // }
const req = await fetch(
'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
{
headers: {
'content-type': 'application/json;charset=UTF-8',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
},
body: JSON.stringify({
mostraImpegniAnnullati: true,
mostraIndisponibilitaTotali: false,
linkCalendarioId: id,
clienteId: '628de8b9b63679f193b87046',
pianificazioneTemplate: false,
dataInizio: '2022-10-02T22:00:00.000Z',
dataFine: '2022-10-07T22:00:00.000Z',
}),
method: 'POST',
mode: 'cors',
credentials: 'omit',
}
)
return await req.json() // const DATE_RANGES = {
}) // '64a7c1c651f079001d52e9c8': DEFAULT_DATE_RANGE,
// '6308e2dc09352a0208fefdd9': DEFAULT_DATE_RANGE,
// '6308e42a1df5cb026699ced4': DEFAULT_DATE_RANGE,
// '64a7c7091ab813002c5d9ede': DEFAULT_DATE_RANGE,
// }
function specialEventPatches(eventi) {
// Il laboratorio del primo anno in realtà è in due gruppi separati
eventi.forEach(evento => {
if (
evento.nome === 'LABORATORIO DI INTRODUZIONE ALLA MATEMATICA COMPUTAZIONALE'
) {
if (evento.evento.dettagliDidattici[0].partizione.descrizione === 'CORSO A') {
evento.nome += ' (A)'
}
if (evento.evento.dettagliDidattici[0].partizione.descrizione === 'CORSO B') {
evento.nome += ' (B)'
}
}
})
return eventi
}
function formatEvents(timetable) {
return timetable.map(({ nome, dataInizio, dataFine, docenti, aule }) => {
return {
id: nome,
name: _.split(nome, '-', 1)[0].trim(),
start: new Date(dataInizio),
end: new Date(dataFine),
docenti: docenti.map(({ nome, cognome }) => prettyProfName(nome, cognome)),
aule: aule.map(aula => prettyAulaName(aula.codice)),
}
})
}
async function loadCalendari(date) {
function getMonday(d) {
const day = d.getDay()
const diff = d.getDate() - day + (day === 0 ? -6 : 1)
const monday = new Date(d.setDate(diff))
monday.setUTCHours(0, 0, 0, 0)
return monday
}
const monday = getMonday(date)
const saturday = new Date(monday)
saturday.setDate(monday.getDate() + 5)
async function req(id) {
// Almost directly copy-pasted from Chrome Dev Tools
const req = await fetch(
'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
{
headers: {
'content-type': 'application/json;charset=UTF-8',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
},
body: JSON.stringify({
mostraImpegniAnnullati: true,
mostraIndisponibilitaTotali: false,
linkCalendarioId: id,
clienteId: '628de8b9b63679f193b87046',
pianificazioneTemplate: false,
dataInizio: monday.toISOString(),
dataFine: saturday.toISOString(),
}),
method: 'POST',
mode: 'cors',
credentials: 'omit',
}
)
return await req.json()
}
const requests = [
req(TIMETABLE_IDS['anno-1']),
req(TIMETABLE_IDS['anno-2']),
req(TIMETABLE_IDS['anno-3']),
req(TIMETABLE_IDS['magistrale']),
]
const results = await Promise.all(requests)
const timetablesRaw = results.map(timetable =>
specialEventPatches(_.uniqBy(timetable, 'id'))
)
const allRaw = specialEventPatches(_.concat(...results), 'id')
return {
'anno-1': formatEvents(timetablesRaw[0]),
'anno-2': formatEvents(timetablesRaw[1]),
'anno-3': formatEvents(timetablesRaw[2]),
'magistrale': formatEvents(timetablesRaw[3]),
'tutti': formatEvents(allRaw),
}
}
const View = ({ view, selection, setSelection, timetables }) => {
if (view === 'orario') {
return <Schedule selection={selection} timetables={timetables} />
} else if (view === 'lista') {
return (
<Courses
selection={selection}
setSelection={setSelection}
source={'tutti'}
timetables={timetables}
hideOtherCourses={true}
/>
)
} else {
return (
<Courses
selection={selection}
setSelection={setSelection}
source={view}
timetables={timetables}
hideOtherCourses={false}
/>
)
}
}
const App = ({}) => {
// Clear persistent states unless state_token corresponds to the one passed
// as the argument. Useful with breaking updates. Change this token if your
// (breaking) update needs a reset of persistent states to avoid crashes.
//
// Use any random string of your choice
// clearOldPersistentStates('e73cba02')
const [date, setDate] = useState(new Date().toISOString())
// Data Sources
const [view, setView] = usePersistentState('view', 'tutti')
const [timetables, setTimetables] = useState(null)
useEffect(async () => {
setTimetables(await loadCalendari(new Date(date)))
}, [date])
// View Modes
// const [mode, setMode] = usePersistentState('orario.mode', MODE_COURSES)
// Selection
const [selectedCourses, setSelectedCourses] = usePersistentState('selection', [])
// Menus
const [helpVisible, setHelpVisible] = useState(false)
const [showMobileMenu, setShowMobileMenu] = useState(false)
const [theme, setTheme] = usePersistentState(
'theme',
'light'
// window.matchMedia('(prefers-color-scheme: dark)').matches
// ? 'dark'
// : 'light'
) )
// console.log(calendari) document.body.classList.toggle('dark-mode', theme === 'dark')
if (ids.length === 1) {
return calendari[0]
}
return _.uniqBy(_.concat(...calendari), 'id')
}
const App = ({}) => {
const [source, setSource] = useState('magistrale')
const [eventi, setEventi] = useState([])
const [selectedCourses, setSelectedCourses] = useState([])
useEffect(() => {
setSelectedCourses([])
}, [source])
useEffect(async () => {
const eventi = await loadEventi(CALENDAR_IDS[source])
window.dataBuffer[source] = eventi
setEventi(eventi)
}, [source])
const [helpVisible, setHelpVisible] = useState(false)
const [mode, setMode] = useState('course')
const [hideOtherCourses, setHideOtherCourses] = useState(false)
// TODO: Should wrap in "useEffect"?
if (selectedCourses.length === 0) {
setHideOtherCourses(false)
}
const [showMobileMenu, setShowMobileMenu] = useState(false)
return ( return (
<> <>
<Toolbar <Toolbar
{...{ {...{
mode, source: view,
setMode, setSource: setView,
source, date: date,
setSource, setDate: setDate,
onShowMenu: () => setShowMobileMenu(true), showMobileMenu: showMobileMenu,
setShowMobileMenu: setShowMobileMenu,
onHelp: () => setHelpVisible(true), onHelp: () => setHelpVisible(true),
theme,
setTheme,
}} }}
/> />
<EventsView {showMobileMenu ? (
mode={mode} <SettingsBar
selection={selectedCourses}
setSelection={setSelectedCourses}
hideOtherCourses={hideOtherCourses}
start={new Date(2022, 10, 3)}
events={eventi.map(({ nome, dataInizio, dataFine, docenti, aule }) => ({
name: _.split(nome, '-', 1)[0].trim(),
start: new Date(dataInizio),
end: new Date(dataFine),
docenti: docenti.map(({ nome, cognome }) =>
_.startCase(_.lowerCase(nome) + ' ' + _.lowerCase(cognome))
),
aula: _.startCase(aule[0].codice.toLowerCase()).replace(
/([A-Z]) ([1-9])/,
'$1$2'
),
}))}
/>
{selectedCourses.length > 0 && (
<ToolOverlay
visibility={hideOtherCourses}
toggleVisibility={() => setHideOtherCourses(s => !s)}
onClose={() => {
setSelectedCourses([])
setHideOtherCourses(false)
}}
/>
)}
{showMobileMenu && (
<HamburgerMenu
{...{ {...{
mode, theme,
setMode, setTheme,
source, date,
setSource, setDate,
onClose: () => {
setShowMobileMenu(false)
},
}} }}
/> />
) : (
<OptionBar
{...{
view: view,
setView: setView,
onHelp: () => setHelpVisible(true),
}}
orizzontale
/>
)} )}
<div class="content">
{timetables &&
(showMobileMenu ? (
<HamburgerMenu
{...{
date,
setDate,
theme,
setTheme,
onClose: () => {
setShowMobileMenu(false)
},
}}
/>
) : timetables['tutti'].length === 0 ? (
<div class="warning">
<p>
Non esistono corsi per la settimana selezionata: buone
vacanze! 🎉
</p>
<p>
Clicca sul bottone qua sotto per vedere la prima settimana
completa di lezioni:
</p>
<button
onClick={() => {
setDate('2025-09-29T00:00:00.000Z')
}}
>
Vai al 29 settembre! 🚀
</button>
{/* <p>
Per cambiare settimana puoi usare il widget Calendario (
<Icon name="calendar_month" />) in alto a destra
<br />
In versione mobile, il widget Calendario è situato dentro
il Menu (
<Icon name="menu" />)
</p> */}
</div>
) : (
<View
selection={selectedCourses}
setSelection={setSelectedCourses}
view={view}
timetables={timetables}
/>
))}
</div>
{/* showMobileMenu && (
) */}
{helpVisible && ( {helpVisible && (
<Popup <Popup
title={ title={
+465 -442
View File
File diff suppressed because it is too large Load Diff
+95
View File
@@ -1,3 +1,71 @@
// Calendar
import { useEffect, useState } from 'preact/hooks'
export const WEEK_DAYS = [
'Domenica',
'Lunedì',
'Martedì',
'Mercoledì',
'Giovedì',
'Venerdì',
'Sabato',
]
export const WEEK_DAYS_SHORT = ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab']
// Hashing
export function hashString(str, seed = 0) {
let h1 = 0xdeadbeef ^ seed,
h2 = 0x41c6ce57 ^ seed
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i)
h1 = Math.imul(h1 ^ ch, 2654435761)
h2 = Math.imul(h2 ^ ch, 1597334677)
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)
return 4294967296 * (2097151 & h2) + (h1 >>> 0)
}
// Courses
export function prettyCourseName(name) {
return name
.split(' ')
.map(word => word.toLowerCase())
.map(word => {
if (word.trim().length === 0) return word
return /(^del|^nel|^di$|^dei$|^con$|^alla$|^per$|^e$|^la$)/.test(word)
? word
: word[0].toUpperCase() + word.slice(1)
})
.join(' ')
.replaceAll('Ii', 'II')
.replaceAll('IIi', 'III')
.replaceAll('Iii', 'III')
.replaceAll(/'(.)/g, ({}, letter) => "'" + letter.toUpperCase())
.replaceAll(/\((a|b)\)/g, ({}, letter) => '(' + letter.toUpperCase() + ')')
}
export function prettyAulaName(name) {
return name
.replace('FIB', 'Fib')
.replace('RIUNIONI', 'Riunioni')
.replace(/([A-Z0-9])\-LAB/, 'Lab $1')
}
export function prettyProfName(nome, cognome) {
return (nome + ' ' + cognome)
.split(/\b/)
.map(word => _.capitalize(word))
.join('')
}
// JSX
export const withClasses = classes => export const withClasses = classes =>
Array.isArray(classes) Array.isArray(classes)
? classes.filter(e => !!e).join(' ') ? classes.filter(e => !!e).join(' ')
@@ -5,3 +73,30 @@ export const withClasses = classes =>
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key) .map(([key]) => key)
.join(' ') .join(' ')
// LocalStorage stuff
export const clearOldPersistentStates = stateToken => {
const lastStateToken = localStorage.getItem('orario.state_token')
if (lastStateToken === null || lastStateToken !== stateToken) {
localStorage.clear()
localStorage.setItem('orario.state_token', stateToken)
}
}
// Hooks
export const usePersistentState = (key, initialValue) => {
const previousValue = localStorage.getItem(`orario.${key}`)
const [value, setValue] = useState(
previousValue !== null ? JSON.parse(previousValue) : initialValue
)
useEffect(() => {
localStorage.setItem(`orario.${key}`, JSON.stringify(value))
}, [value])
return [value, setValue]
}