From ad66bdd9056dd97a7de11b1bf6d748dd3e6cc9fe Mon Sep 17 00:00:00 2001
From: pjaudiomv <34245618+pjaudiomv@users.noreply.github.com>
Date: Sun, 9 Jun 2024 11:31:42 -0400
Subject: [PATCH] seperate for each export type (#76)
---
eslint.config.js | 2 +-
src/components/DownloadLinks.svelte | 23 ----
src/components/ExportCSV.svelte | 21 ++++
src/components/ExportForm.svelte | 43 ++++---
src/components/ExportKML.svelte | 92 ++++++++++++++
src/components/ExportXLSX.svelte | 21 ++++
src/components/ExportXML.svelte | 18 +++
src/components/ExportYAML.svelte | 18 +++
src/lib/DataUtils.ts | 179 ----------------------------
src/utils/DataUtils.ts | 59 +++++++++
10 files changed, 254 insertions(+), 222 deletions(-)
delete mode 100644 src/components/DownloadLinks.svelte
create mode 100644 src/components/ExportCSV.svelte
create mode 100644 src/components/ExportKML.svelte
create mode 100644 src/components/ExportXLSX.svelte
create mode 100644 src/components/ExportXML.svelte
create mode 100644 src/components/ExportYAML.svelte
delete mode 100644 src/lib/DataUtils.ts
create mode 100644 src/utils/DataUtils.ts
diff --git a/eslint.config.js b/eslint.config.js
index 9e032e6..69b8a62 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -31,7 +31,7 @@ export default [
ignores: ['build/', '.svelte-kit/', 'dist/', '*.lock']
},
{
- files: ['**/*.ts'],
+ files: ['**/*.ts', '**/*.svelte'],
rules: {
'@typescript-eslint/no-explicit-any': 'off'
}
diff --git a/src/components/DownloadLinks.svelte b/src/components/DownloadLinks.svelte
deleted file mode 100644
index 8054c4b..0000000
--- a/src/components/DownloadLinks.svelte
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-{#if csvDownloadUrl}
- Download CSV
-{/if}
-{#if xlsxDownloadUrl}
- Download XLSX
-{/if}
-{#if xmlDownloadUrl}
- Download XML
-{/if}
-{#if kmlDownloadUrl}
- Download KML
-{/if}
-{#if yamlDownloadUrl}
- Download YAML
-{/if}
diff --git a/src/components/ExportCSV.svelte b/src/components/ExportCSV.svelte
new file mode 100644
index 0000000..6a06462
--- /dev/null
+++ b/src/components/ExportCSV.svelte
@@ -0,0 +1,21 @@
+
+
+Download CSV
diff --git a/src/components/ExportForm.svelte b/src/components/ExportForm.svelte
index 923d9a8..e376267 100644
--- a/src/components/ExportForm.svelte
+++ b/src/components/ExportForm.svelte
@@ -1,34 +1,27 @@
+
+Download KML
diff --git a/src/components/ExportXLSX.svelte b/src/components/ExportXLSX.svelte
new file mode 100644
index 0000000..66c76e8
--- /dev/null
+++ b/src/components/ExportXLSX.svelte
@@ -0,0 +1,21 @@
+
+
+Download XLSX
diff --git a/src/components/ExportXML.svelte b/src/components/ExportXML.svelte
new file mode 100644
index 0000000..65023bc
--- /dev/null
+++ b/src/components/ExportXML.svelte
@@ -0,0 +1,18 @@
+
+
+Download XML
diff --git a/src/components/ExportYAML.svelte b/src/components/ExportYAML.svelte
new file mode 100644
index 0000000..78368fb
--- /dev/null
+++ b/src/components/ExportYAML.svelte
@@ -0,0 +1,18 @@
+
+
+Download YAML
diff --git a/src/lib/DataUtils.ts b/src/lib/DataUtils.ts
deleted file mode 100644
index 04fb928..0000000
--- a/src/lib/DataUtils.ts
+++ /dev/null
@@ -1,179 +0,0 @@
-import fetchJsonp from 'fetch-jsonp';
-import * as XLSX from 'xlsx';
-import * as js2xmlparser from 'js2xmlparser';
-import * as yaml from 'js-yaml';
-
-interface Meeting {
- meeting_name: string;
- longitude: string;
- latitude: string;
- weekday_tinyint: string;
- start_time: string;
- lang_enum: string;
- location_text: string;
- location_street: string;
- location_city_subsection: string;
- location_municipality: string;
- location_neighborhood: string;
- location_province: string;
- location_postal_code_1: string;
- location_nation: string;
- location_info: string;
-}
-
-export async function fetchData(query: string): Promise {
- try {
- if (!query.includes('/client_interface/json')) {
- return Promise.reject(new Error('Query does not contain a valid json endpoint.'));
- }
- const updatedQuery = query.replace('/client_interface/json/', '/client_interface/jsonp/');
- const response = await fetchJsonp(updatedQuery, {
- jsonpCallback: 'callback',
- timeout: 10000 // 10 seconds timeout
- });
- const data = await response.json();
- if (!Array.isArray(data) || data.length === 0) {
- return Promise.reject(new Error('No data found'));
- }
- return data;
- } catch (error) {
- throw new Error(error instanceof Error ? error.message : 'Error loading data');
- }
-}
-
-export function exportCSV(data: any[]): string {
- const processedData = processExportData(data);
- const wb = XLSX.utils.book_new();
- const ws = XLSX.utils.json_to_sheet(processedData);
- XLSX.utils.book_append_sheet(wb, ws, 'Data');
- const csvString = XLSX.write(wb, { bookType: 'csv', type: 'string' });
- const blob = new Blob([csvString], { type: 'text/csv' });
- return URL.createObjectURL(blob);
-}
-
-export function exportYAML(data: any[]): string {
- const processedData = processExportData(data);
- const yamlString = yaml.dump(processedData);
- const blob = new Blob([yamlString], { type: 'application/x-yaml' });
- return URL.createObjectURL(blob);
-}
-
-export function exportXML(data: any[]): string {
- const processedData = processExportData(data);
- const xmlResult = js2xmlparser.parse('root', processedData);
- const blob = new Blob([xmlResult], { type: 'text/xml' });
- return URL.createObjectURL(blob);
-}
-
-export function exportXLSX(data: any[]): string {
- const processedData = processExportData(data);
- const wb = XLSX.utils.book_new();
- const ws = XLSX.utils.json_to_sheet(processedData);
- XLSX.utils.book_append_sheet(wb, ws, 'Data');
- const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
- const blob = new Blob([s2ab(wbout)], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
- return URL.createObjectURL(blob);
-}
-
-export function exportKML(data: Meeting[]): string {
- const placemarks = data.map(createPlacemark).filter(Boolean).join('\n');
- const kmlContent = `
-
-
- ${placemarks}
-
-`;
- const blob = new Blob([kmlContent], { type: 'application/vnd.google-earth.kml+xml' });
- return URL.createObjectURL(blob);
-}
-
-function s2ab(s: string): ArrayBuffer {
- const buf = new ArrayBuffer(s.length);
- const view = new Uint8Array(buf);
- for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xff;
- return buf;
-}
-
-// This is for Bus/Train/Custom fields
-function processExportData(data: any[]): any[] {
- return data.map((row) =>
- Object.keys(row).reduce((acc, key) => {
- let value: string | number = row[key];
- if (typeof value === 'string' && value.includes('#@-@#')) {
- [, value] = value.split('#@-@#');
- }
- acc[key] = value;
- return acc;
- }, {} as any)
- );
-}
-
-function createPlacemark(meeting: Meeting): string {
- const name = meeting.meeting_name.trim() || 'NA Meeting';
- const lng = parseFloat(meeting.longitude);
- const lat = parseFloat(meeting.latitude);
- if (!lng || !lat) return '';
- const description = prepareSimpleLine(meeting);
- const address = prepareSimpleLine(meeting, false);
- return `
-
- ${name}
- ${address ? `${address}` : ''}
- ${description ? `${description}` : ''}
-
- ${lng},${lat}
-
-
- `.trim();
-}
-
-function prepareSimpleLine(meeting: Meeting, withDate: boolean = true): string {
- const getLocationInfo = () => {
- const locationInfo: string[] = [];
- const addInfo = (property: keyof Meeting) => {
- const value = meeting[property]?.trim() ?? '';
- if (value) locationInfo.push(value);
- };
- addInfo('location_text');
- addInfo('location_street');
- addInfo('location_city_subsection');
- addInfo('location_municipality');
- addInfo('location_neighborhood');
- addInfo('location_province');
- addInfo('location_postal_code_1');
- addInfo('location_nation');
- addInfo('location_info');
- return locationInfo.join(', ');
- };
-
- const getDateString = () => {
- const dayOfWeekInt = parseInt(meeting.weekday_tinyint?.trim() ?? '0');
- const adjustedDay = dayOfWeekInt % 7;
- // January 1, 2023, was a Sunday.
- const baseDate = new Date('2023-01-01');
- baseDate.setDate(baseDate.getDate() + adjustedDay);
- const lang = meeting.lang_enum ? (meeting.lang_enum === 'dk' ? 'da' : meeting.lang_enum) : window.navigator.language;
- const twelveHrLangs: string[] = ['en', 'es'];
- if (dayOfWeekInt && withDate) {
- let dateString = baseDate.toLocaleDateString(lang, { weekday: 'long' });
- if (!isNaN(baseDate.getTime())) {
- dateString += `, ${baseDate.toLocaleTimeString(lang, {
- hour: 'numeric',
- minute: 'numeric',
- hour12: twelveHrLangs.includes(lang)
- })}`;
- }
- return dateString;
- }
- return '';
- };
- const locationInfo = getLocationInfo();
- const dateString = getDateString();
- if (withDate && dateString && locationInfo) {
- return `${dateString}, ${locationInfo}`;
- } else if (dateString) {
- return dateString;
- } else {
- return locationInfo;
- }
-}
diff --git a/src/utils/DataUtils.ts b/src/utils/DataUtils.ts
new file mode 100644
index 0000000..f1437c6
--- /dev/null
+++ b/src/utils/DataUtils.ts
@@ -0,0 +1,59 @@
+import fetchJsonp from 'fetch-jsonp';
+
+export interface Meeting {
+ meeting_name: string;
+ longitude: string;
+ latitude: string;
+ weekday_tinyint: string;
+ start_time: string;
+ lang_enum: string;
+ location_text: string;
+ location_street: string;
+ location_city_subsection: string;
+ location_municipality: string;
+ location_neighborhood: string;
+ location_province: string;
+ location_postal_code_1: string;
+ location_nation: string;
+ location_info: string;
+}
+
+export async function fetchData(query: string): Promise {
+ try {
+ if (!query.includes('/client_interface/json')) {
+ return Promise.reject(new Error('Query does not contain a valid json endpoint.'));
+ }
+ const updatedQuery = query.replace('/client_interface/json/', '/client_interface/jsonp/');
+ const response = await fetchJsonp(updatedQuery, {
+ jsonpCallback: 'callback',
+ timeout: 10000 // 10 seconds timeout
+ });
+ const data = await response.json();
+ if (!Array.isArray(data) || data.length === 0) {
+ return Promise.reject(new Error('No data found'));
+ }
+ return data;
+ } catch (error) {
+ throw new Error(error instanceof Error ? error.message : 'Error loading data');
+ }
+}
+
+export function processExportData(data: any[]): any[] {
+ return data.map((row) =>
+ Object.keys(row).reduce((acc, key) => {
+ let value: string | number = row[key];
+ if (typeof value === 'string' && value.includes('#@-@#')) {
+ [, value] = value.split('#@-@#');
+ }
+ acc[key] = value;
+ return acc;
+ }, {} as any)
+ );
+}
+
+export function s2ab(s: string): ArrayBuffer {
+ const buf = new ArrayBuffer(s.length);
+ const view = new Uint8Array(buf);
+ for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xff;
+ return buf;
+}