diff --git a/package.json b/package.json index 431d16df..28539e79 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "license": "CC-BY-NC-SA-4.0", "dependencies": { - "@odit/lfk-client-js": "0.4.5", + "@odit/lfk-client-js": "0.6.3", "csvtojson": "^2.0.10", "gridjs": "3.3.0", "localforage": "1.9.0", @@ -21,7 +21,7 @@ "marked": "^2.0.0", "svelte-focus-trap": "1.0.1", "svelte-i18n": "3.3.2", - "svelte-select": "^3.16.1", + "svelte-select": "^3.17.0", "tailwindcss": "2.0.3", "tinro": "0.5.12", "toastify-js": "1.9.3", diff --git a/src/App.svelte b/src/App.svelte index 9871981e..335b2a7f 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -69,9 +69,11 @@ import Donations from "./components/donations/Donations.svelte"; import DonationDetail from "./components/donations/DonationDetail.svelte"; import GroupDetail from "./components/groups/GroupDetail.svelte"; -import ScanStationsOverview from "./components/scanstations/ScanStationsOverview.svelte"; -import ScanStations from "./components/scanstations/ScanStations.svelte"; -import ScanStationDetail from "./components/scanstations/ScanStationDetail.svelte"; + import ScanStationsOverview from "./components/scanstations/ScanStationsOverview.svelte"; + import ScanStations from "./components/scanstations/ScanStations.svelte"; + import ScanStationDetail from "./components/scanstations/ScanStationDetail.svelte"; + import Scans from "./components/scans/Scans.svelte"; +import ScanDetail from "./components/scans/ScanDetail.svelte"; store.init(); registerSW(); @@ -183,6 +185,14 @@ import ScanStationDetail from "./components/scanstations/ScanStationDetail.svelt + + + + + + + + diff --git a/src/components/dashboard/Dashboard.svelte b/src/components/dashboard/Dashboard.svelte index f095e11c..38505b49 100644 --- a/src/components/dashboard/Dashboard.svelte +++ b/src/components/dashboard/Dashboard.svelte @@ -172,21 +172,41 @@ {$_('tracks')} {/if} - - - - {$_('contacts')} - + {#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:GET')} + + + + Scans + + {/if} + {#if store.state.jwtinfo.userdetails.permissions.includes('CONTACT:GET')} + + + + {$_('contacts')} + + {/if} {#if store.state.jwtinfo.userdetails.permissions.includes('STATION:GET')} + xmlns="http://www.w3.org/2000/svg"> + {$_('scanstations')} {/if} diff --git a/src/components/scans/AddScanModal.svelte b/src/components/scans/AddScanModal.svelte new file mode 100644 index 00000000..58b45df7 --- /dev/null +++ b/src/components/scans/AddScanModal.svelte @@ -0,0 +1,195 @@ + + +{#if modal_open} +
{ + modal_open = false; + }}> +
+ +
+
+{/if} diff --git a/src/components/scans/ScanDetail.svelte b/src/components/scans/ScanDetail.svelte new file mode 100644 index 00000000..f054dad5 --- /dev/null +++ b/src/components/scans/ScanDetail.svelte @@ -0,0 +1,272 @@ + + +{#await promise} + Loading scan details +{:then} +
+
+
+ +
+
+
+ {runner.value?.firstname} + {runner.value?.middlename || ''} + {runner.value?.lastname} + #{original_data.id} + + {#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:DELETE')} + {#if delete_triggered} + + + {/if} + {#if !delete_triggered} + + {/if} + {/if} + {#if !delete_triggered} + + {/if} + +
+ +
+ +   + { + editable.valid = !editable.valid; + }} + name="valid" + type="checkbox" + checked={editable.valid} + class="focus:ring-indigo-500 align-bottom h-7 w-5font-medium text-indigo-600 border-gray-300 rounded" /> +   +

+ {#if editable.valid}{$_('valid')}{:else}{$_('invalid')}{/if} +

+
+ {#if editable.responseType === 'TRACKSCAN'} +
+ + {editable.track.name} + +
+
+ +
+ {/if} +
+ + + m +
+ {#if !is_distance_valid} + + {$_('the-scans-distance-must-be-greater-than-0m')} + + {/if} + +
+{:catch error} + +{/await} diff --git a/src/components/scans/Scans.svelte b/src/components/scans/Scans.svelte new file mode 100644 index 00000000..984190a2 --- /dev/null +++ b/src/components/scans/Scans.svelte @@ -0,0 +1,29 @@ + + +
+ + {$_('scans')} + {#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:CREATE')} + + {/if} + + +
+ +{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:CREATE')} + +{/if} diff --git a/src/components/scans/ScansEmptyState.svelte b/src/components/scans/ScansEmptyState.svelte new file mode 100644 index 00000000..f1964072 --- /dev/null +++ b/src/components/scans/ScansEmptyState.svelte @@ -0,0 +1,12 @@ + + +
+

+ + {$_('there-are-no-scans-yet')}
+ {$_('add-your-fist-scan')} +

+
diff --git a/src/components/scans/ScansOverview.svelte b/src/components/scans/ScansOverview.svelte new file mode 100644 index 00000000..81ccec1e --- /dev/null +++ b/src/components/scans/ScansOverview.svelte @@ -0,0 +1,201 @@ + + +{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:GET')} + {#await scans_promise} + + {:then} + {#if current_scans.length === 0} + + {:else} + +
+ + + + + + + + + + + + {#each current_scans as scan} + {#if scan.track?.name + .toLowerCase() + .includes( + searchvalue.toLowerCase() + ) || scan.runner?.firstname + .toLowerCase() + .includes( + searchvalue.toLowerCase() + ) || scan.runner?.middlename + .toLowerCase() + .includes( + searchvalue.toLowerCase() + ) || scan.runner?.lastname + .toLowerCase() + .includes( + searchvalue.toLowerCase() + ) || should_display_based_on_id(scan.id)} + + + + + + + {#if active_deletes[scan.id] === true} + + {:else} + + {/if} + + {/if} + {/each} + +
+ {$_('runner')} + + {$_('distance-track')} + + {$_('laptime')} + + {$_('status')} + + {$_('action')} +
+ + +
+ {#if scan.distance < 1000} + {scan.distance}m + {:else}{scan.distance / 1000}km{/if} + {#if scan.track} + {scan.track.name} + + {/if} +
+
+ {#if scan.responseType === "TRACKSCAN"} +
+ {format_laptime(scan.lapTime)} +
+ {:else} +
+ {$_('scan-with-fixed-distance')} +
+ {/if} +
+
+ {#if scan.valid} + {$_('valid')} + {:else} + {$_('invalid')} + {/if} +
+
+ + + + {$_('details')} + {#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:DELETE')} + + {/if} +
+
+ {/if} + {:catch error} +
+ + {$_('general_promise_error')} + {error} + +
+ {/await} +{/if} diff --git a/src/components/scans/scans.svg b/src/components/scans/scans.svg new file mode 100644 index 00000000..13a97190 --- /dev/null +++ b/src/components/scans/scans.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/locales/en.json b/src/locales/en.json index 03ff8ba2..f63bdc3a 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -6,6 +6,7 @@ "active": "Active", "add-donation": "Add donation", "add-donor": "add donor", + "add-scan": "Add scan", "add-user-group": "Add User Group", "add-your-first-contact": "Add your first contact", "add-your-first-donor": "add your first donor", @@ -15,6 +16,8 @@ "add-your-first-team": "Add your first team", "add-your-first-track": "Add your first track.", "add-your-first-user": "Add your first user", + "add-your-fist-scan": "Add your fist scan", + "adding-scan": "Adding Scan", "address": "Address", "address-is-required": "Address is required", "all-associated-donations-will-get-deleted-as-well": "All associated donations will get deleted as well", @@ -60,6 +63,7 @@ "create-a-new-fixed-donation": "Create a new fixed donation", "create-a-new-organization": "Create a new Organization", "create-a-new-runner": "Create a new Runner", + "create-a-new-scan-fixed-only": "Create a new scan (fixed only)", "create-a-new-team": "Create a new team", "create-a-new-track": "Create a new Track", "create-a-new-user": "Create a new User", @@ -98,8 +102,10 @@ "delete-group": "Delete Group", "delete-organization": "Delete Organization", "delete-runner": "Delete Runner", + "delete-scan": "Delete scan", "delete-team": "Delete Team", "delete-user": "Delete User", + "deleted-scan": "Deleted scan", "dependency_name": "Name", "description": "description", "description-optional": "Description (optional)", @@ -108,6 +114,7 @@ "distance": "Distance", "distance-donation": "distance donation", "distance-in-km": "Distance in km", + "distance-track": "Distance (+Track)", "do-you-want-to-delete-the-organization-delete_org-name": "Do you want to delete the organization {orgname}?", "do-you-want-to-delete-the-team-delete_team-name": "Do you want to delete the team {teamname}?", "do-you-want-to-delete-this-donor-with-all-related-donations": "Do you want to delete this donor with all related donations", @@ -136,6 +143,7 @@ "filter-by-organization-team": "Filter by Organization/ Team", "first-name": "First name", "first-name-is-required": "First Name is required", + "first-scan-of-the-day": "First scan of the day.", "fixed-donation": "fixed donation", "forgot_password": "Forgot your password?", "geerbte": "inherited", @@ -166,9 +174,11 @@ "inactive": "Inactive", "installed-version": "Installed version", "internal-error": "Internal Error", + "invalid": "Invalid", "invalid-mail-reset": "the provided email is invalid", "laeufer-hinzufuegen": "Add runner", "laeufer-importieren": "Läufer importieren", + "laptime": "Laptime", "last-name": "Last name", "last-name-is-required": "Last Name is required", "lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", @@ -226,6 +236,7 @@ "please-provide-a-password": "Please provide a password...", "please-provide-the-nessecary-information-to-add-a-new-donor": "Please provide the nessecary information to add a new donor", "please-provide-the-nessecary-information-to-create-a-new-donation": "Please provide the nessecary information to create a new donation", + "please-provide-the-nessecary-information-to-create-a-new-scan": "Please provide the nessecary information to create a new scan.", "please-provide-the-required-csv-xlsx-file": "Please provide the required csv/ xlsx file", "please-provide-the-required-information-for-creating-a-new-user-group": "Please provide the required information for creating a new user group.", "please-provide-the-required-information-to-add-a-new-contact": "Please provide the required information to add a new contact.", @@ -255,6 +266,11 @@ "runners-are-being-loaded": "runners are being loaded...", "save": "Save", "save-changes": "Save Changes", + "scan-added": "Scan added", + "scan-is-being-updated": "Scan is being updated", + "scan-with-fixed-distance": "Scan with fixed distance", + "scans": "Scans", + "scans-are-being-loaded": "Scans are being loaded", "search-for-an-organization-by-name-or-id": "Search for an organization (by name or id)", "search-for-an-organization-or-team-by-name-or-id": "Search for an organization or team (by name or id)", "search-for-donor-name-or-id": "Search for donor (by name or id)", @@ -276,11 +292,13 @@ "teams": "Teams", "teams-are-being-loaded": "teams are being loaded...", "the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.
please enter a valid international number...", + "the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m", "there-are-no-contacts-added-yet": "There are no contacts added yet.", "there-are-no-donors-yet": "There are no donors yet", "there-are-no-groups-yet": "There are no groups yet", "there-are-no-organizations-added-yet": "There are no organizations added yet.", "there-are-no-runners-added-yet": "There are no runners added yet.", + "there-are-no-scans-yet": "There are no scans yet", "there-are-no-teams-added-yet": "There are no teams added yet.", "there-are-no-users-added-yet": "There are no users added yet.", "this-might-take-a-moment": "This might take a moment 👀", @@ -288,6 +306,7 @@ "total-donation-amount": "total donation amount", "total-donations": "total donations", "total-scans": "total scans", + "track": "Track", "track-added": "Track added", "track-data-is-being-loaded": "Track data is being loaded", "track-is-being-added": "Track is being added...", @@ -299,6 +318,7 @@ "updated-contact": "Updated contact!", "updated-donor": "updated donor", "updated-organization": "updated organization", + "updated-scan": "updated scan", "updateing-group": "updateing group...", "updating-organization": "updating organization", "updating-permissions": "updating permissions...", @@ -310,6 +330,7 @@ "user-updated": "User updated", "username": "Username", "users": "Users", + "valid": "Valid", "valid-city-is-required": "Valid city is required", "valid-email-is-required": "valid email is required", "valid-international-phone-number-is-required": "valid international phone number is required...",