Skip to content

Commit

Permalink
Merge pull request #53 from CropWatchDevelopment/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
CropWatchDevelopment authored May 13, 2024
2 parents 06bc78e + bb6516e commit a012740
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 108 deletions.
7 changes: 7 additions & 0 deletions src/lib/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,5 +240,12 @@
"permissions": "Permissions",
"settings": "Settings",
"history": "History"
},
"history": {
"title": "History and Downloads",
"data_preview": "Data Preview",
"no_data": "No data to display",
"download_selected": "Download Selected Range",
"search_text": "Filter Data Points"
}
}
9 changes: 8 additions & 1 deletion src/lib/i18n/locales/jp.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,5 +255,12 @@
"rename": " ",
"new_name": "新しい名前"
},
"close": "閉じる"
"close": "閉じる",
"history": {
"title": "履歴",
"data_preview": "データプレビュー",
"no_data": "データがありません",
"download_selected": "選択したデータをダウンロード",
"search_text": "Filter Data Points"
}
}
15 changes: 9 additions & 6 deletions src/routes/(api)/api/v1/devices/[dev_eui]/data/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const GET: RequestHandler = async ({ url, params, locals: { supabase, saf
const from = query.get('from');
const to = query.get('to');
const dataPoints = query.get('data-points');
const noLimit = query.get('no-limit' || 0);
const csv = query.get('csv');

if (!dev_eui) {
Expand All @@ -31,14 +32,16 @@ export const GET: RequestHandler = async ({ url, params, locals: { supabase, saf
.eq('dev_eui', dev_eui)
.order('created_at', { ascending: false })

if (from) {
baseQuery = baseQuery.gte('created_at', moment(from).toISOString());
}
if (to) {
baseQuery = baseQuery.lte('created_at', moment(to).toISOString());
}
if (from) {
baseQuery = baseQuery.gte('created_at', moment(from).utc().toISOString());
}
if (to) {
baseQuery = baseQuery.lte('created_at', moment(to).utc().toISOString());
}

if (!noLimit) {
baseQuery.range(startingPage, startingPage + itemsPerPage - 1);
}

// Conditionally apply `.single()` if itemsPerPage is 1
let finalQuery = itemsPerPage === 1 ? baseQuery.single() : baseQuery;
Expand Down
219 changes: 118 additions & 101 deletions src/routes/app/devices/[dev_eui]/history/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,107 +1,118 @@
<script lang="ts">
import Back from '$lib/components/ui/Back.svelte';
import historyImage from '$lib/images/UI/cw_history.svg';
import { Button, DateRangeField, MultiSelect, PeriodType } from 'svelte-ux';
import { subDays, subWeeks } from 'date-fns';
import { mdiDownload } from '@mdi/js';
import { _ } from 'svelte-i18n';
import { HighChartsTimeSeriesChart } from '$lib/charts/highcharts/timeseries.js';
import Highcharts from '$lib/actions/highcharts.action';
import { page } from '$app/stores';
import DarkCard from '$lib/components/ui/DarkCard.svelte';
import DarkCard2 from '$lib/components/ui/DarkCard2.svelte';
export let data;
export let sensorName = 'NS';
let today = new Date();
let value = {
from: subWeeks(today, 1),
to: today,
periodType: PeriodType.Day
};
let chartKey = 0;
let options = Object.keys(data.sensorData).map((key) => {
return {
value: key,
name: $_(key)
};
});
let selectedDataPoints: string[] = [];
$: chartConfig = HighChartsTimeSeriesChart(chartData.series, chartData.yAxes, '');
let chartData = {
series: [],
yAxes: []
};
// Define a list of colors for the chart lines and Y-axes
const colors = ['lightblue', 'lightgreen', 'red', 'purple', 'orange', 'grey', 'pink', 'cyan', 'yellow', 'magenta'];
function createChartSeries(res) {
const series = {};
const yAxes = {};
res.forEach((d) => {
Object.keys(d).forEach((key, i) => {
if (key !== 'created_at') {
if (!series[key]) {
let colorIndex = Object.keys(yAxes).length % colors.length; // Cycle through colors
series[key] = {
type: 'line',
yAxis: colorIndex, // Assign to new yAxis index
name: $_(key),
data: [],
color: colors[colorIndex] // Use color from the array
};
yAxes[key] = {
title: {
text: $_(key),
style: { color: colors[colorIndex] }
},
labels: {
format: '{value}', // Customize if needed
style: { color: colors[colorIndex] }
},
opposite: i % 2 === 0
};
}
series[key].data.push([new Date(d.created_at).valueOf(), d[key]]);
}
});
});
return {
series: Object.values(series),
yAxes: Object.values(yAxes)
};
}
const loadSelectedDataRange = async () => {
const response = await fetch(
`/api/v1/devices/${$page.params.dev_eui}/data?from=${value.from}&to=${value.to}&data-points=${selectedDataPoints}&page=0&count=10000`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
);
const res = await response.json();
chartData = createChartSeries(res);
chartKey++; // Increment key to force re-render
};
import Back from '$lib/components/ui/Back.svelte';
import historyImage from '$lib/images/UI/cw_history.svg';
import { Button, DateRangeField, MultiSelect, PeriodType } from 'svelte-ux';
import { subDays, subWeeks } from 'date-fns';
import { mdiDownload } from '@mdi/js';
import { _ } from 'svelte-i18n';
import { HighChartsTimeSeriesChart } from '$lib/charts/highcharts/timeseries.js';
import Highcharts from '$lib/actions/highcharts.action';
import { page } from '$app/stores';
import DarkCard2 from '$lib/components/ui/DarkCard2.svelte';
export let data;
export let sensorName = 'NS';
let today = new Date();
let value = {
from: subWeeks(today, 1),
to: today,
periodType: PeriodType.Day
};
let isLoading: boolean = false;
let chartKey = 0;
let options = Object.keys(data.sensorData).map((key) => {
return {
value: key,
name: $_(key)
};
});
let selectedDataPoints: string[] = [];
$: chartConfig = HighChartsTimeSeriesChart(chartData.series, chartData.yAxes, '');
let chartData = {
series: [],
yAxes: []
};
// Define a list of colors for the chart lines and Y-axes
const colors = [
'lightblue',
'lightgreen',
'red',
'purple',
'orange',
'grey',
'pink',
'cyan',
'yellow',
'magenta'
];
function createChartSeries(res) {
const series = {};
const yAxes = {};
res.forEach((d) => {
Object.keys(d).forEach((key, i) => {
if (key !== 'created_at') {
if (!series[key]) {
let colorIndex = Object.keys(yAxes).length % colors.length; // Cycle through colors
series[key] = {
type: 'line',
yAxis: colorIndex, // Assign to new yAxis index
name: $_(key),
data: [],
color: colors[colorIndex] // Use color from the array
};
yAxes[key] = {
title: {
text: $_(key),
style: { color: colors[colorIndex] }
},
labels: {
format: '{value}', // Customize if needed
style: { color: colors[colorIndex] }
},
opposite: i % 2 === 0
};
}
series[key].data.push([new Date(d.created_at).valueOf(), d[key]]);
}
});
});
return {
series: Object.values(series),
yAxes: Object.values(yAxes)
};
}
const loadSelectedDataRange = async () => {
const response = await fetch(
`/api/v1/devices/${$page.params.dev_eui}/data?from=${value.from}&to=${value.to}&data-points=${selectedDataPoints}&page=0&count=10000`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
);
const res = await response.json();
chartData = createChartSeries(res);
chartKey++; // Increment key to force re-render
};
const downloadCSV = (sensorName) => {
isLoading = true;
const date = new Date();
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}`;
const fileName = `${sensorName}-${formattedDate}.csv`;
fetch(
`/api/v1/devices/${$page.params.dev_eui}/data?from=${value.from}&to=${value.to}&data-points=${selectedDataPoints}&page=0&count=10000&csv=1`,
`/api/v1/devices/${$page.params.dev_eui}/data?from=${value.from}&to=${value.to}&data-points=${selectedDataPoints}&no-limit=1&csv=1`,
{
method: 'GET',
headers: {
Expand All @@ -119,14 +130,18 @@
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
isLoading = false;
})
.catch((error) => console.error('Error downloading the file:', error));
.catch((error) => {
console.error('Error downloading the file:', error);
isLoading = false;
});
};
</script>

<div class="flex flex-row bg-emerald-300 p-4 text-center justify-center">
<img src={historyImage} alt="History" class="w-10 h-10" />
<p class="text-surface-100 text-3xl ml-2">History and Downloads</p>
<p class="text-surface-100 text-3xl ml-2">{$_('history.title')}</p>
</div>

<div class="mt-4 mx-2 flex justify-between">
Expand All @@ -152,9 +167,9 @@
/>
</DarkCard2>
<DarkCard2>
<h2 class="text-xl text-neutral-content">Data Preview:</h2>
<h2 class="text-xl text-neutral-content">{$_('history.data_preview')}:</h2>
{#if chartKey === 0}
<p class="text-center text-neutral-content">No data to display</p>
<p class="text-center text-neutral-content">{$_('history.no_data')}</p>
{/if}
{#key chartKey}
<div class="chart" use:Highcharts={chartConfig} />
Expand All @@ -170,7 +185,9 @@
on:click={() => downloadCSV('sensor')}
size="lg"
class="w-full"
rounded>Download Selected Range</Button
loading={isLoading}
disabled={isLoading}
rounded>{$_('history.download_selected')}</Button
>
</div>
</div>

0 comments on commit a012740

Please sign in to comment.