Skip to content

Commit

Permalink
Feat/add new data structure component (#19)
Browse files Browse the repository at this point in the history
* feat: ✨ add new data structure component

* feat: ✨ add explore button

Co-authored-by: maudetes <[email protected]>
  • Loading branch information
nicolaskempf57 and maudetes authored Feb 28, 2023
1 parent b35cfed commit 0fdb324
Show file tree
Hide file tree
Showing 13 changed files with 363 additions and 122 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Add sort to exploration preview component [#20](https://github.com/opendatateam/udata-tabular-preview/pull/20)
- Fix setuptools version used in CI [#23](https://github.com/opendatateam/udata-tabular-preview/pull/23)
- Add pagination to exploration preview component [#21](https://github.com/opendatateam/udata-tabular-preview/pull/21)
- Add data structure component and explore button for hook `dataset.display.explore-button` [#19](https://github.com/opendatateam/udata-tabular-preview/pull/19)

## 3.0.0 (2023-01-18)

Expand Down
42 changes: 42 additions & 0 deletions udata-tabular-preview/csvapi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { apify, configure, getData } from "@etalab/explore.data.gouv.fr/lib/csvapi";

/**
* @typedef {object} CsvapiResponseWithEndpoint
* @property {string} endpoint - the endpoint for further requests
* @property {Promise<import("@etalab/explore.data.gouv.fr/lib/csvapi").CsvapiResponse>} data - data from the first call
*/

/**
* @type {Map<string, Promise<CsvapiResponseWithEndpoint>>}
*/
const csvapiRequests = new Map();

/**
* Call Csvapi functions apify and getData with provided configuration.
* Configuration is called twice : one time before each call to Csvapi.
*
* @param {string} url - a url to a resource hosted on udata
* @param {import("@etalab/explore.data.gouv.fr/lib/csvapi").CsvapiRequestConfiguration} config - Csvapi configuration
* @returns {Promise<CsvapiResponseWithEndpoint>}
*/
export default function requestCsvapi(url, config) {
let existingRequest;
if(existingRequest = csvapiRequests.get(url)) {
return existingRequest;
}
configure(config);
const request = apify(url).then(res => {
if (res.ok) {
config.dataEndpoint = res.endpoint;
configure(config);
return {
endpoint: res.endpoint,
data: getData("apify"),
};
} else {
throw new Error("Got 200 but result isn't ok");
}
});
csvapiRequests.set(url, request);
return request;
}
71 changes: 71 additions & 0 deletions udata-tabular-preview/data-structure.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<div class="bg-alt-green-tilleul-verveine fr-p-3v fr-mb-2w" v-if="hasError">
<p class="fr-grid-row fr-m-0">
<span class="fr-icon-warning-line" aria-hidden="true"></span>
{{ $t("The data structure of this file failed to load.") }}
</p>
</div>
<Loader v-if="loading" />
<div v-if="!hasError && !loading" class="fr-grid-row fr-grid-row--gutters">
<div class="bg-alt-green-tilleul-verveine fr-p-3v fr-mb-2w" v-if="isExcel">
<p class="fr-grid-row fr-m-0">
<span class="fr-icon-warning-line" aria-hidden="true"></span>
{{ $t("This is an Excel file, analysis on this type of files are limited.") }}
</p>
</div>
<div class="bg-alt-green-tilleul-verveine fr-p-3v fr-mb-2w" v-else-if="!hasColumnInfos">
<p class="fr-grid-row fr-m-0">
<span class="fr-icon-warning-line" aria-hidden="true"></span>
{{ $t("No data structure found for this file.") }}
</p>
</div>
<div v-if="hasColumnInfos" class="fr-col-12 fr-col-sm-6 fr-col-md-4 fr-col-lg-3" v-for="column in columns">
<h5 class="fr-text--sm fr-text--bold fr-mt-0 fr-mb-1v">{{column}}</h5>
<code class="code">
{{ columnsInfos[column].format }}
</code>
</div>
</div>
</template>

<script>
import { computed, defineComponent } from 'vue';
import Loader from "./loader.vue";
import useCsvapi from './useCsvapi';
export default defineComponent({
components: {Loader},
props: {
resource: {
/** @type {import("vue").PropType<import("./index").Resource>} */
type: Object,
required: true
}
},
setup(props) {
const {
apifyAndGetData,
columns,
columnsInfos,
generalInfos,
hasError,
isExcel,
loading,
} = useCsvapi(props.resource);
const hasColumnInfos = computed(() => Object.keys(columnsInfos.value).length > 0);
apifyAndGetData();
return {
columns,
columnsInfos,
generalInfos,
hasColumnInfos,
hasError,
isExcel,
loading,
};
}
});
</script>
140 changes: 27 additions & 113 deletions udata-tabular-preview/explore.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="bg-alt-green-tilleul-verveine fr-p-3v fr-my-2w" v-if="hasError">
<div class="bg-alt-green-tilleul-verveine fr-p-3v fr-mt-4w fr-mx-4w fr-mb-3v" v-if="hasError">
<p class="fr-grid-row fr-m-0">
<span class="fr-icon-warning-line" aria-hidden="true"></span>
{{ $t("The preview of this file failed to load.") }}
Expand Down Expand Up @@ -44,7 +44,7 @@
:page="currentPage"
:pageSize="pageSize"
:totalResults="rowCount"
:changePage="changeExplorePage"
:changePage="changePage"
/>
<div class="fr-grid-row fr-grid-row--gutters fr-grid-row--middle fr-px-5v">
<div class="fr-col">{{ $t('{count} columns', columnCount) }} — {{ $t('{count} rows', rowCount) }}</div>
Expand All @@ -58,138 +58,52 @@
</template>

<script>
import { apify, changePage, configure, getData, sort } from "@etalab/explore.data.gouv.fr/lib/csvapi";
import { Pagination } from "@etalab/udata-front-plugins-helper";
import { computed, defineComponent, ref } from 'vue';
import { tabular_csvapi_url, tabular_page_size } from "./config";
import { defineComponent } from 'vue';
import Loader from "./loader.vue";
import useCsvapi from "./useCsvapi";
export default defineComponent({
components: {Loader, Pagination},
props: {
resource: {
/** @type {import("vue").PropType<import("./index").Resource>} */
type: Object,
required: true
}
},
setup(props) {
/** @type {import("vue").Ref<Array>} */
const columns = ref([]);
/** @type {import("vue").Ref<Array>} */
const rows = ref([]);
const rowCount = ref(0);
/** @type {import("vue").Ref<number | null>} */
const columnCount = ref(null);
const loading = ref(true);
const hasError = ref(false);
const currentPage = ref(1);
/** @type {import("vue").Ref<string | null>} */
const dataEndpoint = ref(null);
const pageSize = Number.parseInt(tabular_page_size ?? "10");
/** @type {import("vue").Ref<string | null>} */
const sortBy = ref(null);
const sortDesc = ref(false);
/** @type {import("vue").ComputedRef<import("@etalab/explore.data.gouv.fr/lib/csvapi").CsvapiRequestConfiguration>} */
const config = computed(() => {
return {
csvapiUrl: tabular_csvapi_url,
dataEndpoint: dataEndpoint.value,
filters: [],
page: currentPage.value,
pageSize: pageSize,
sortBy: sortBy.value,
sortDesc: sortDesc.value,
totalRows: rowCount.value,
};
});
/**
*
* @param {import("@etalab/explore.data.gouv.fr/lib/csvapi").CsvapiResponse} res
*/
const update = (res) => {
if (res.ok) {
rows.value = res.rows;
columns.value = res.columns;
rowCount.value = res.total;
columnCount.value = res.columns.length;
} else {
hasError.value = true;
}
}
const changeExplorePage = (page) => {
configure(config.value);
const res = changePage(page);
if(res) {
res.then(update)
.catch(() => hasError.value = true)
.finally(() => loading.value = false);
}
currentPage.value = page;
}
/**
*
* @param {string} col
*/
const sortbyfield = (col) => {
if(sortBy.value == col) {
sortDesc.value = !sortDesc.value
} else {
sortDesc.value = false
}
sortBy.value = col;
configure(config.value);
return sort(sortBy.value, sortDesc.value).then(res => {
update(res);
currentPage.value = 1;
}).catch(() => hasError.value = true)
.finally(() => loading.value = false);
};
const requestData = () => {
loading.value = true;
configure(config.value);
return getData("apify").then(res => {
update(res);
}).catch(() => hasError.value = true)
.finally(() => loading.value = false);
}
const requestApify = () => {
configure(config.value);
return apify(props.resource.url).then(res => {
if (res.ok) {
dataEndpoint.value = res.endpoint;
return requestData();
} else {
hasError.value = true;
loading.value = false;
}
}).catch(() => {
hasError.value = true;
loading.value = false;
});
}
const isSortedBy = (col) => col === sortBy.value;
const {
apifyAndGetData,
changePage,
columns,
columnCount,
currentPage,
hasError,
isSortedBy,
loading,
pageSize,
rows,
rowCount,
sortbyfield,
sortDesc,
} = useCsvapi(props.resource);
requestApify();
apifyAndGetData();
return {
changePage,
columns,
columnCount,
currentPage,
hasError,
isSortedBy,
loading,
columns,
pageSize,
rows,
rowCount,
columnCount,
sortbyfield,
isSortedBy,
sortDesc,
currentPage,
pageSize,
changeExplorePage,
};
}
});
Expand Down
6 changes: 6 additions & 0 deletions udata-tabular-preview/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import 'vite/modulepreload-polyfill';
import { registerComponent, registerTranslation } from "@etalab/udata-front-plugins-helper";
import DataStructure from "./data-structure.vue";
import Explore from "./explore.vue";
import messages from '@intlify/unplugin-vue-i18n/messages';

/**
* @typedef {{title: string, preview_url:string, url: string}} Resource
*/

registerComponent("explore", Explore, "udata-tabular-preview", "explore");
registerComponent("data-structure", DataStructure, "udata-tabular-preview", "data-structure");
registerTranslation(messages, "udata-tabular-preview");
5 changes: 4 additions & 1 deletion udata-tabular-preview/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"The preview of this file failed to load.": "The preview of this file failed to load.",
"{count} rows": "{count} rows | {count} row | {count} rows",
"Sort ascending": "Sort ascending",
"Sort descending": "Sort descending"
"Sort descending": "Sort descending",
"The data structure of this file failed to load.": "The data structure of this file failed to load.",
"This is an Excel file, analysis on this type of files are limited.": "This is an Excel file, analysis on this type of files are limited.",
"No data structure found for this file.": "No data structure found for this file."
}
7 changes: 5 additions & 2 deletions udata-tabular-preview/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"The preview of this file failed to load.": "",
"{count} rows": "",
"Sort ascending": "",
"Sort descending": ""
}
"Sort descending": "",
"The data structure of this file failed to load.": "",
"This is an Excel file, analysis on this type of files are limited.": "",
"No data structure found for this file.": ""
}
5 changes: 4 additions & 1 deletion udata-tabular-preview/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"The preview of this file failed to load.": "La prévisualisation de ce fichier n'a pas pu être chargée.",
"{count} rows": "{count} lignes | {count} ligne | {count} lignes",
"Sort ascending": "Trier par ordre croissant",
"Sort descending": "Trier par ordre décroissant"
"Sort descending": "Trier par ordre décroissant",
"The data structure of this file failed to load.": "",
"This is an Excel file, analysis on this type of files are limited.": "",
"No data structure found for this file.": ""
}
7 changes: 5 additions & 2 deletions udata-tabular-preview/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"{count} columns": "",
"Explore data": "",
"The preview of this file failed to load.": "",
"{count} rows": "",
"Sort ascending": "",
"Sort descending": "",
"Showing the first {shown} of {count} rows": ""
}
"The data structure of this file failed to load.": "",
"This is an Excel file, analysis on this type of files are limited.": "",
"No data structure found for this file.": ""
}
7 changes: 5 additions & 2 deletions udata-tabular-preview/locales/sr.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"{count} columns": "",
"Explore data": "",
"The preview of this file failed to load.": "",
"{count} rows": "",
"Sort ascending": "",
"Sort descending": "",
"Showing the first {shown} of {count} rows": ""
}
"The data structure of this file failed to load.": "",
"This is an Excel file, analysis on this type of files are limited.": "",
"No data structure found for this file.": ""
}
Loading

0 comments on commit 0fdb324

Please sign in to comment.