mirror of
https://github.com/ae-utbm/sith.git
synced 2024-12-22 07:41:14 +00:00
Use typescript api for user pictures and allow imports across js files
* Add imports paths for js files in node * Add a ts version of fetchPaginated * Update documentation
This commit is contained in:
parent
9247696c1c
commit
9199f91151
@ -1,5 +1,7 @@
|
||||
import { paginated } from "#core:utils/api";
|
||||
import { HttpReader, ZipWriter } from "@zip.js/zip.js";
|
||||
import { showSaveFilePicker } from "native-file-system-adapter";
|
||||
import { picturesFetchPictures } from "#openapi";
|
||||
|
||||
/**
|
||||
* @typedef UserProfile
|
||||
@ -28,14 +30,14 @@ import { showSaveFilePicker } from "native-file-system-adapter";
|
||||
|
||||
/**
|
||||
* @typedef PicturePageConfig
|
||||
* @param {string} apiUrl Url of the api endpoint to fetch pictures from the user
|
||||
* @param {number} userId Id of the user to get the pictures from
|
||||
**/
|
||||
|
||||
/**
|
||||
* Load user picture page with a nice download bar
|
||||
* @param {PicturePageConfig} Configuration
|
||||
**/
|
||||
window.loadPicturePage = (config) => {
|
||||
window.window.loadPicturePage = (config) => {
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("user_pictures", () => ({
|
||||
isDownloading: false,
|
||||
@ -44,8 +46,10 @@ window.loadPicturePage = (config) => {
|
||||
albums: {},
|
||||
|
||||
async init() {
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: imported from script.json
|
||||
this.pictures = await fetchPaginated(config.apiUrl);
|
||||
this.pictures = await paginated(picturesFetchPictures, {
|
||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||
query: { users_identified: [config.userId] },
|
||||
});
|
||||
this.albums = this.pictures.reduce((acc, picture) => {
|
||||
if (!acc[picture.album]) {
|
||||
acc[picture.album] = [];
|
||||
|
46
core/static/webpack/utils/api.ts
Normal file
46
core/static/webpack/utils/api.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { Options, RequestResult } from "@hey-api/client-fetch";
|
||||
|
||||
interface PaginatedResponse<T> {
|
||||
count: number;
|
||||
next: string | null;
|
||||
previous: string | null;
|
||||
results: T[];
|
||||
}
|
||||
|
||||
interface PaginatedRequest {
|
||||
query?: {
|
||||
page?: number;
|
||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||
page_size?: number;
|
||||
};
|
||||
}
|
||||
|
||||
type PaginatedEndpoint<T> = <ThrowOnError extends boolean = false>(
|
||||
options?: Options<PaginatedRequest, ThrowOnError>,
|
||||
) => RequestResult<PaginatedResponse<T>, unknown, ThrowOnError>;
|
||||
|
||||
export const paginated = async <T>(
|
||||
endpoint: PaginatedEndpoint<T>,
|
||||
options?: PaginatedRequest,
|
||||
) => {
|
||||
const maxPerPage = 199;
|
||||
options.query.page_size = maxPerPage;
|
||||
options.query.page = 1;
|
||||
|
||||
const firstPage = (await endpoint(options)).data;
|
||||
const results = firstPage.results;
|
||||
|
||||
const nbElements = firstPage.count;
|
||||
const nbPages = Math.ceil(nbElements / maxPerPage);
|
||||
|
||||
if (nbPages > 1) {
|
||||
const promises: Promise<T[]>[] = [];
|
||||
for (let i = 2; i <= nbPages; i++) {
|
||||
const nextPage = structuredClone(options);
|
||||
nextPage.query.page = i;
|
||||
promises.push(endpoint(nextPage).then((res) => res.data.results));
|
||||
}
|
||||
results.push(...(await Promise.all(promises)).flat());
|
||||
}
|
||||
return results;
|
||||
};
|
@ -62,9 +62,7 @@
|
||||
{{ super() }}
|
||||
<script>
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
loadPicturePage({
|
||||
apiUrl: "{{ url("api:pictures") }}?users_identified={{ object.id }}"
|
||||
});
|
||||
loadPicturePage({ userId: {{ object.id }} });
|
||||
})
|
||||
</script>
|
||||
{% endblock script %}
|
||||
|
39
docs/howto/js-import-paths.md
Normal file
39
docs/howto/js-import-paths.md
Normal file
@ -0,0 +1,39 @@
|
||||
Vous avez ajouté une application et vous voulez y mettre du javascript ?
|
||||
|
||||
Vous voulez importer depuis cette nouvelle application dans votre script géré par webpack ?
|
||||
|
||||
Eh bien il faut manuellement enregistrer dans node où les trouver et c'est très simple.
|
||||
|
||||
D'abord, il faut ajouter dans node via `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
// ...
|
||||
"imports": {
|
||||
// ...
|
||||
"#mon_app:*": "./mon_app/static/webpack/*"
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Ensuite, pour faire fonctionne l'auto-complétion, il faut configurer `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"paths": {
|
||||
// ...
|
||||
"#mon_app:*": ["./mon_app/static/webpack/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Et c'est tout !
|
||||
|
||||
!!!note
|
||||
|
||||
Il se peut qu'il soit nécessaire de redémarrer `./manage.py runserver` pour
|
||||
que les changements prennent effet.
|
@ -35,8 +35,9 @@ les fichiers sont à mettre dans un dossier `static/webpack` de l'application à
|
||||
Pour accéder au fichier, il faut utiliser `static` comme pour le reste mais en ajouter `webpack/` comme prefix.
|
||||
|
||||
```jinja
|
||||
{# Exemple pour ajouter sith/core/webpack/alpine-index.js #}
|
||||
{# Example pour ajouter sith/core/webpack/alpine-index.js #}
|
||||
<script src="{{ static('webpack/alpine-index.js') }}" defer></script>
|
||||
<script src="{{ static('webpack/other-index.ts') }}" defer></script>
|
||||
```
|
||||
|
||||
!!!note
|
||||
@ -45,6 +46,16 @@ Pour accéder au fichier, il faut utiliser `static` comme pour le reste mais en
|
||||
Les autres fichiers sont disponibles à l'import dans le JavaScript comme
|
||||
si ils étaient tous au même niveau.
|
||||
|
||||
### Les imports au sein des fichiers de webpack
|
||||
|
||||
Pour importer au sein de webpack, faut préfixer ses imports de `#app:`.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
import { paginated } from "#core:utils/api";
|
||||
```
|
||||
|
||||
## Comment ça fonctionne le post processing ?
|
||||
|
||||
Le post processing est géré par le module `staticfiles`. Les fichiers sont
|
||||
|
@ -72,6 +72,7 @@ nav:
|
||||
- Gérer les migrations: howto/migrations.md
|
||||
- Gérer les traductions: howto/translation.md
|
||||
- Gérer les statics: howto/statics.md
|
||||
- Ajouter un chemin d'import javascript: howto/js-import-paths.md
|
||||
- Configurer pour la production: howto/prod.md
|
||||
- Ajouter un logo de promo: howto/logo.md
|
||||
- Ajouter une cotisation: howto/subscriptions.md
|
||||
|
@ -14,7 +14,8 @@
|
||||
"license": "GPL-3.0-only",
|
||||
"sideEffects": [".css"],
|
||||
"imports": {
|
||||
"#openapi": "./staticfiles/generated/openapi/index.ts"
|
||||
"#openapi": "./staticfiles/generated/openapi/index.ts",
|
||||
"#core:*": "./core/static/webpack/*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
@ -9,7 +9,8 @@
|
||||
"allowJs": true,
|
||||
"moduleResolution": "node",
|
||||
"paths": {
|
||||
"#openapi": ["./staticfiles/generated/openapi/index.ts"]
|
||||
"#openapi": ["./staticfiles/generated/openapi/index.ts"],
|
||||
"#core:*": ["./core/static/webpack/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user