mirror of
https://github.com/ae-utbm/sith.git
synced 2025-01-03 13:41:15 +00:00
add a button to download products as csv
This commit is contained in:
parent
39b36aa509
commit
1a9556f811
@ -1,8 +1,12 @@
|
||||
import { paginated } from "#core:utils/api";
|
||||
import { csv } from "#core:utils/csv";
|
||||
import { History, getCurrentUrlParams, updateQueryString } from "#core:utils/history";
|
||||
import type { NestedKeyOf } from "#core:utils/types";
|
||||
import { showSaveFilePicker } from "native-file-system-adapter";
|
||||
import {
|
||||
type ProductSchema,
|
||||
productSearchProductsDetailed,
|
||||
type ProductSearchProductsDetailedData,
|
||||
productSearchProductsDetailed,
|
||||
} from "#openapi";
|
||||
|
||||
type ProductType = string;
|
||||
@ -11,6 +15,38 @@ type GroupedProducts = Record<ProductType, ProductSchema[]>;
|
||||
const defaultPageSize = 100;
|
||||
const defaultPage = 1;
|
||||
|
||||
/**
|
||||
* Keys of the properties to include in the CSV.
|
||||
*/
|
||||
const csvColumns = [
|
||||
"id",
|
||||
"name",
|
||||
"code",
|
||||
"description",
|
||||
"product_type.name",
|
||||
"club.name",
|
||||
"limit_age",
|
||||
"purchase_price",
|
||||
"selling_price",
|
||||
"archived",
|
||||
] as NestedKeyOf<ProductSchema>[];
|
||||
|
||||
/**
|
||||
* Title of the csv columns.
|
||||
*/
|
||||
const csvColumnTitles = [
|
||||
"id",
|
||||
gettext("name"),
|
||||
"code",
|
||||
"description",
|
||||
gettext("product type"),
|
||||
"club",
|
||||
gettext("limit age"),
|
||||
gettext("purchase price"),
|
||||
gettext("selling price"),
|
||||
gettext("archived"),
|
||||
];
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("productList", () => ({
|
||||
loading: false,
|
||||
@ -84,5 +120,33 @@ document.addEventListener("alpine:init", () => {
|
||||
}, {});
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Download products corresponding to the current filters as a CSV file.
|
||||
* If the pagination has multiple pages, all pages are downloaded.
|
||||
*/
|
||||
async downloadCsv() {
|
||||
this.csvLoading = true;
|
||||
const fileHandle = await showSaveFilePicker({
|
||||
_preferPolyfill: false,
|
||||
suggestedName: gettext("products.csv"),
|
||||
types: [],
|
||||
excludeAcceptAllOption: false,
|
||||
});
|
||||
// if products to download are already in-memory, directly take them.
|
||||
// If not, fetch them.
|
||||
const products =
|
||||
this.nbPages > 1
|
||||
? await paginated(productSearchProductsDetailed, this.getQueryParams())
|
||||
: Object.values<ProductSchema[]>(this.products).flat();
|
||||
const content = csv.stringify(products, {
|
||||
columns: csvColumns,
|
||||
titleRow: csvColumnTitles,
|
||||
});
|
||||
const file = await fileHandle.createWritable();
|
||||
await file.write(content);
|
||||
await file.close();
|
||||
this.csvLoading = false;
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
@ -39,9 +39,19 @@
|
||||
</form>
|
||||
<h3 @click="console.log(totalCount, nbPages())">{% trans %}Product list{% endtrans %}</h3>
|
||||
|
||||
<a href="{{ url('counter:new_product') }}" class="btn btn-blue">
|
||||
{% trans %}New product{% endtrans %} <i class="fa fa-plus"></i>
|
||||
</a>
|
||||
<div class="row">
|
||||
<a href="{{ url('counter:new_product') }}" class="btn btn-blue">
|
||||
{% trans %}New product{% endtrans %} <i class="fa fa-plus"></i>
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-blue"
|
||||
@click="downloadCsv()"
|
||||
:disabled="csvLoading"
|
||||
:aria-busy="csvLoading"
|
||||
>
|
||||
{% trans %}Download as cvs{% endtrans %} <i class="fa fa-file-arrow-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<template x-if="loading">
|
||||
<section :aria-busy="loading"></section>
|
||||
</template>
|
||||
|
Loading…
Reference in New Issue
Block a user