Import per CSV ist möglich
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
<script>
|
||||
import Papa from '../../../papaparse.min'
|
||||
import { paginate, PaginationNav } from 'svelte-paginate'
|
||||
|
||||
export let activeRecordList = []
|
||||
let imported_data = []
|
||||
export let currentPage = 1
|
||||
let pageSize = 15
|
||||
$: paginatedItems = paginate({ items: imported_data, pageSize, currentPage })
|
||||
|
||||
let files = null
|
||||
|
||||
const VerarbeiteDateien = () => {
|
||||
for (const file of files) {
|
||||
VerarbeiteCsv(file)
|
||||
}
|
||||
}
|
||||
|
||||
const VerarbeiteCsv = file => {
|
||||
Papa.parse(file, {
|
||||
header: true,
|
||||
skipEmptyLines: true,
|
||||
complete: results => {
|
||||
let cash_work_days = {}
|
||||
results.data.forEach(item => {
|
||||
// noinspection JSNonASCIINames
|
||||
let activity = item['Aktivität']
|
||||
if (activity.trim() === 'Mittagspause') {
|
||||
return
|
||||
}
|
||||
let work_from = new Date(item['Von'])
|
||||
let work_to = new Date(item['Bis'])
|
||||
let actual_day = work_from.toISOString().substring(0, 10)
|
||||
let actual_work_hours = (work_to - work_from) / (1000 * 60 * 60)
|
||||
cash_work_days[actual_day] ??= 0
|
||||
cash_work_days[actual_day] += actual_work_hours
|
||||
})
|
||||
for (let day in cash_work_days) {
|
||||
let hours = cash_work_days[day]
|
||||
let hours_digits = Math.trunc(hours)
|
||||
let minutes_digits = Math.round((hours - hours_digits) * 60)
|
||||
let working_time = String(hours_digits).padStart(2, '0') + ':'
|
||||
+ String(minutes_digits).padStart(2, '0') + ':00'
|
||||
activeRecordList.push({ workingTime: working_time, workingDay: day })
|
||||
}
|
||||
imported_data = activeRecordList
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<fieldset>
|
||||
<legend>Download-Liste</legend>
|
||||
<div class="zelle">
|
||||
<label for="csv-file">Download der Zeiten von <i>aTimeLogger2</i></label>
|
||||
<input type="file" accept="text/csv" id="csv-file" bind:files/>
|
||||
<button type="button" on:click={VerarbeiteDateien}>Upload</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset name="record-data-for-import">
|
||||
<div>
|
||||
{#if imported_data.length < 1}
|
||||
<p>Loading...</p>
|
||||
{:else}
|
||||
<table>
|
||||
<tbody>
|
||||
{#each imported_data as item}
|
||||
<tr>
|
||||
<td>
|
||||
{item.workingDay}
|
||||
</td>
|
||||
<td>
|
||||
{item.workingTime}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<PaginationNav
|
||||
totalItems="{imported_data.length}"
|
||||
pageSize="{pageSize}"
|
||||
currentPage="{currentPage}"
|
||||
limit="{1}"
|
||||
showStepOptions="{true}"
|
||||
on:setPage="{(e) => currentPage = e.detail.page}"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -60,5 +60,16 @@ export const actions = {
|
||||
}
|
||||
actualDayObject.setDate(actualDayObject.getDate() + 1)
|
||||
})
|
||||
},
|
||||
'import-csv': async ({ request }) => {
|
||||
const form_data = await request.formData();
|
||||
for (const pair of form_data.entries()) {
|
||||
const working_day = pair[0]
|
||||
const body_data = {
|
||||
workingDay: working_day,
|
||||
workingTime: pair[1],
|
||||
}
|
||||
await WorkingHoursRepository.addOrUpdate(env.API_URL, working_day, body_data);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -36,6 +36,9 @@
|
||||
<button formaction="/working-hours/create-by-week" type="submit">per Woche
|
||||
<IconifyIcon icon={documentIcon}/>
|
||||
</button>
|
||||
<button formaction="/working-hours/import-csv" type="submit">Import per CSV
|
||||
<IconifyIcon icon={documentIcon}/>
|
||||
</button>
|
||||
</fieldset>
|
||||
{#if records === null}
|
||||
<p>Loading...</p>
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<script>
|
||||
import IconifyIcon from '@iconify/svelte'
|
||||
import checkIcon from "@iconify-icons/oi/check";
|
||||
import xIcon from "@iconify-icons/oi/x";
|
||||
import {goto} from "$app/navigation";
|
||||
// @ts-ignore
|
||||
import Papa from 'papaparse';
|
||||
|
||||
const TITLE = "Erstellung neuer Einträge für eine Woche"
|
||||
|
||||
/** @type {{ workingTime: String, workingDay: String, }[]} **/
|
||||
let imported_data = $state([])
|
||||
|
||||
|
||||
let files = $state(null)
|
||||
|
||||
const VerarbeiteDateien = () => {
|
||||
for (const file of files ?? []) {
|
||||
VerarbeiteCsv(file)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @param {File} file **/
|
||||
const VerarbeiteCsv = file => {
|
||||
Papa.parse(file, {
|
||||
header: true,
|
||||
skipEmptyLines: true,
|
||||
// @ts-ignore
|
||||
complete: results => {
|
||||
/** @type {Object<String, Number>} **/
|
||||
let cash_work_days = {}
|
||||
results.data.forEach(
|
||||
/** @param {Object<String, any>} item **/
|
||||
item => {
|
||||
// noinspection JSNonASCIINames
|
||||
let activity = item['Aktivität']
|
||||
if (activity.trim() === 'Mittagspause') {
|
||||
return
|
||||
}
|
||||
let work_from = new Date(item['Von'])
|
||||
let work_to = new Date(item['Bis'])
|
||||
let actual_day = work_from.toISOString().substring(0, 10)
|
||||
let actual_work_hours = (work_to.getTime() - work_from.getTime()) / (1000 * 60 * 60)
|
||||
cash_work_days[actual_day] ??= 0
|
||||
cash_work_days[actual_day] += actual_work_hours
|
||||
}
|
||||
)
|
||||
for (let day in cash_work_days) {
|
||||
let hours = cash_work_days[day]
|
||||
let hours_digits = Math.trunc(hours)
|
||||
let minutes_digits = Math.round((hours - hours_digits) * 60)
|
||||
let working_time = String(hours_digits).padStart(2, '0') + ':'
|
||||
+ String(minutes_digits).padStart(2, '0') + ':00'
|
||||
imported_data.push({workingTime: working_time, workingDay: day})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{TITLE}</title>
|
||||
</svelte:head>
|
||||
|
||||
|
||||
<section id="edit-record">
|
||||
<header>
|
||||
<h1>{TITLE}</h1>
|
||||
</header>
|
||||
<article>
|
||||
<form action="/working-hours?/import-csv" name="newRecord" method="POST">
|
||||
{#if imported_data.length < 1}
|
||||
<fieldset>
|
||||
<legend>Download-Liste</legend>
|
||||
<div class="zelle">
|
||||
<label for="csv-file">Download der Zeiten von <i>aTimeLogger2</i></label>
|
||||
<input type="file" accept="text/csv" id="csv-file" bind:files/>
|
||||
<button type="button" onclick={VerarbeiteDateien}>Upload</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
{:else}
|
||||
<fieldset name="record-data-for-import">
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
{#each imported_data as item}
|
||||
<tr>
|
||||
<td>
|
||||
{item.workingDay}
|
||||
</td>
|
||||
<td>
|
||||
<input type="time" readonly name="{item.workingDay}" value="{item.workingTime}">
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset name="buttons">
|
||||
<button type="submit">Übernehmen und Weiter
|
||||
<IconifyIcon icon={checkIcon} color="green"/>
|
||||
</button>
|
||||
<button type="button" class="sub-button" onclick={() => goto('/working-hours')}>Abbrechen
|
||||
<IconifyIcon icon={xIcon}/>
|
||||
</button>
|
||||
</fieldset>
|
||||
{/if}
|
||||
</form>
|
||||
</article>
|
||||
</section>
|
||||
Reference in New Issue
Block a user