formatting, full migration to svelte-french-toast
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
|
||||
|
||||
import {
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
@@ -9,7 +9,6 @@
|
||||
} from "@odit/lfk-client-js";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
||||
import Toastify from "toastify-js";
|
||||
import Select from "svelte-select";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
@@ -78,10 +77,6 @@
|
||||
function submit() {
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: $_("runner-is-being-added"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
let postdata = {
|
||||
group: selected_team,
|
||||
firstname: firstname_input_value,
|
||||
@@ -96,6 +91,7 @@
|
||||
if (email_input_value) {
|
||||
postdata.email = email_input_value;
|
||||
}
|
||||
toast.loading($_("runner-is-being-added"));
|
||||
RunnerService.runnerControllerPost(postdata)
|
||||
.then((result) => {
|
||||
firstname_input_value = "";
|
||||
@@ -104,11 +100,8 @@
|
||||
email_input_value = "";
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: $_("runner-added"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
toast.dismiss();
|
||||
toast.success($_("runner-added"));
|
||||
dispatch("created", { runners: [result] });
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -116,8 +109,6 @@
|
||||
})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
//
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -126,58 +117,70 @@
|
||||
{#if modal_open}
|
||||
<div
|
||||
class="fixed z-10 inset-0 overflow-y-auto"
|
||||
|
||||
use:clickOutside
|
||||
on:click_outside={() => {
|
||||
modal_open = false;
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||
>
|
||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||
<div
|
||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||
data-id="modal_backdrop" />
|
||||
data-id="modal_backdrop"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
aria-hidden="true">​</span>
|
||||
aria-hidden="true">​</span
|
||||
>
|
||||
<div
|
||||
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-headline">
|
||||
aria-labelledby="modal-headline"
|
||||
>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div
|
||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
class="h-6 w-6 text-blue-600"
|
||||
fill="currentColor"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
height="24"
|
||||
><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||
{$_('create-a-new-runner')}
|
||||
{$_("create-a-new-runner")}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
{$_('please-provide-the-required-information-to-add-a-new-runner')}
|
||||
{$_(
|
||||
"please-provide-the-required-information-to-add-a-new-runner"
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="firstname"
|
||||
class="block text-sm font-medium text-gray-700">{$_('first-name')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("first-name")}</label
|
||||
>
|
||||
<input
|
||||
use:focus
|
||||
autocomplete="off"
|
||||
placeholder={$_('first-name')}
|
||||
placeholder={$_("first-name")}
|
||||
class:border-red-500={!isFirstnameValid}
|
||||
class:focus:border-red-500={!isFirstnameValid}
|
||||
class:focus:ring-red-500={!isFirstnameValid}
|
||||
@@ -185,34 +188,41 @@
|
||||
bind:this={firstname_input}
|
||||
type="text"
|
||||
name="firstname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isFirstnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('first-name-is-required')}
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("first-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="trackname"
|
||||
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("middle-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('middle-name')}
|
||||
placeholder={$_("middle-name")}
|
||||
bind:value={middlename_input_value}
|
||||
bind:this={middlename_input}
|
||||
type="text"
|
||||
name="trackname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="lastname"
|
||||
class="block text-sm font-medium text-gray-700">{$_('last-name')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("last-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('last-name')}
|
||||
placeholder={$_("last-name")}
|
||||
class:border-red-500={!isLastnameValid}
|
||||
class:focus:border-red-500={!isLastnameValid}
|
||||
class:focus:ring-red-500={!isLastnameValid}
|
||||
@@ -220,41 +230,49 @@
|
||||
bind:this={lastname_input}
|
||||
type="text"
|
||||
name="lastname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isLastnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('last-name-is-required')}
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("last-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="team"
|
||||
class="block text-sm font-medium text-gray-700">{$_('team')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("team")}</label
|
||||
>
|
||||
<Select
|
||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
itemFilter={(label, filterText, option) => label
|
||||
.toLowerCase()
|
||||
.includes(
|
||||
filterText.toLowerCase()
|
||||
) || option.value.id
|
||||
itemFilter={(label, filterText, option) =>
|
||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||
option.value.id
|
||||
.toString()
|
||||
.startsWith(filterText.toLowerCase())}
|
||||
items={orgs.concat(teams)}
|
||||
showChevron={true}
|
||||
placeholder={$_('search-for-an-organization-or-team-by-name-or-id')}
|
||||
noOptionsMessage={$_('no-organization-or-team-found')}
|
||||
on:select={(selectedValue) => (selected_team = selectedValue.detail.value.id)}
|
||||
on:clear={() => (selected_team = null)} />
|
||||
placeholder={$_(
|
||||
"search-for-an-organization-or-team-by-name-or-id"
|
||||
)}
|
||||
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||
on:select={(selectedValue) =>
|
||||
(selected_team = selectedValue.detail.value.id)}
|
||||
on:clear={() => (selected_team = null)}
|
||||
/>
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="phone"
|
||||
class="block text-sm font-medium text-gray-700">{$_('phone')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("phone")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('phone')}
|
||||
placeholder={$_("phone")}
|
||||
class:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||
@@ -262,21 +280,27 @@
|
||||
bind:this={phone_input}
|
||||
type="tel"
|
||||
name="phone"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isPhoneValidOrEmpty}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{@html $_('the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number')}
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{@html $_(
|
||||
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number"
|
||||
)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="email"
|
||||
class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>{$_("e-mail-adress")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('e-mail-adress')}
|
||||
placeholder={$_("e-mail-adress")}
|
||||
class:border-red-500={!isEmailValidOrEmpty}
|
||||
class:focus:border-red-500={!isEmailValidOrEmpty}
|
||||
class:focus:ring-red-500={!isEmailValidOrEmpty}
|
||||
@@ -284,11 +308,13 @@
|
||||
bind:this={email_input}
|
||||
type="email"
|
||||
name="email"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isEmailValidOrEmpty}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-email-is-required')}
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("valid-email-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -302,16 +328,18 @@
|
||||
class:opacity-50={!createbtnenabled}
|
||||
on:click={submit}
|
||||
type="button"
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
{$_('create')}
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>
|
||||
{$_("create")}
|
||||
</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
modal_open = false;
|
||||
}}
|
||||
type="button"
|
||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
{$_('cancel')}
|
||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>
|
||||
{$_("cancel")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
});
|
||||
async function submit() {
|
||||
dispatch("delete", { id: delete_runner.id });
|
||||
modal_open=false;
|
||||
modal_open = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
import { read as readXlsx, utils as xlsx_utils } from "xlsx";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
|
||||
import Toastify from "toastify-js";
|
||||
|
||||
import {
|
||||
ImportService,
|
||||
RunnerTeamService,
|
||||
@@ -12,6 +11,7 @@
|
||||
} from "@odit/lfk-client-js";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import Select from "svelte-select";
|
||||
import toast from "svelte-french-toast";
|
||||
export let opened_from;
|
||||
export let passed_org;
|
||||
export let passed_orgs;
|
||||
@@ -90,10 +90,7 @@
|
||||
}
|
||||
function importAction() {
|
||||
if (recent_processed === true) {
|
||||
const toast = Toastify({
|
||||
text: $_("runners-are-being-imported"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
toast.loading($_("runners-are-being-imported"));
|
||||
recent_processed = false;
|
||||
const mapped = json_output.map(function (runner) {
|
||||
return {
|
||||
@@ -115,48 +112,30 @@
|
||||
if (opened_from === "OrgOverview" || opened_from === "OrgDetail") {
|
||||
ImportService.importControllerPostOrgsJson(org, mapped)
|
||||
.then((resp) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
toast.success($_("import-finished"));
|
||||
cancelModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("error-during-import"),
|
||||
duration: 500,
|
||||
backgroundColor:
|
||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||
}).showToast();
|
||||
toast.error($_("error-during-import"));
|
||||
cancelModal();
|
||||
});
|
||||
}
|
||||
if (opened_from === "TeamDetail") {
|
||||
ImportService.importControllerPostTeamsJson(passed_team.id, mapped)
|
||||
.then((resp) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
toast.success($_("import-finished"));
|
||||
cancelModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("error-during-import"),
|
||||
duration: 500,
|
||||
backgroundColor:
|
||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||
}).showToast();
|
||||
toast.error($_("error-during-import"));
|
||||
cancelModal();
|
||||
});
|
||||
}
|
||||
@@ -169,24 +148,15 @@
|
||||
)
|
||||
.then((resp) => {
|
||||
dispatch("created", { runners: resp });
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
toast($_("import-finished"));
|
||||
cancelModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("error-during-import"),
|
||||
duration: 500,
|
||||
backgroundColor:
|
||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||
}).showToast();
|
||||
toast.error($_("error-during-import"));
|
||||
cancelModal();
|
||||
});
|
||||
}
|
||||
@@ -198,24 +168,15 @@
|
||||
)
|
||||
.then((resp) => {
|
||||
dispatch("created", { runners: resp });
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_('import-finished'),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
toast($_("import-finished"));
|
||||
cancelModal();
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.hideToast();
|
||||
toast.dismiss();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: $_("error-during-import"),
|
||||
duration: 500,
|
||||
backgroundColor:
|
||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||
}).showToast();
|
||||
toast.error($_("error-during-import"));
|
||||
cancelModal();
|
||||
});
|
||||
}
|
||||
@@ -227,43 +188,51 @@
|
||||
{#if import_modal_open}
|
||||
<div
|
||||
class="fixed z-10 inset-0 overflow-y-auto"
|
||||
|
||||
use:clickOutside
|
||||
on:click_outside={() => {
|
||||
cancelModal();
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||
>
|
||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||
<div
|
||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||
data-id="modal_backdrop" />
|
||||
data-id="modal_backdrop"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
aria-hidden="true">​</span>
|
||||
aria-hidden="true">​</span
|
||||
>
|
||||
<div
|
||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-max sm:w-full"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-headline">
|
||||
aria-labelledby="modal-headline"
|
||||
>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div
|
||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
class="h-6 w-6 text-blue-600"
|
||||
fill="currentColor"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
height="24"
|
||||
><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||
/></svg
|
||||
>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-2 sm:text-left w-full">
|
||||
<h3 class="text-lg leading-6 font-bold mt-2 text-gray-900">
|
||||
{$_('runner-import')}
|
||||
{$_("runner-import")}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
@@ -271,14 +240,15 @@
|
||||
{#if json_output.length === 0}
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
{$_('please-provide-the-required-csv-xlsx-file')}
|
||||
{$_("please-provide-the-required-csv-xlsx-file")}
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-hidden relative mt-4 mb-4">
|
||||
<input
|
||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
bind:files
|
||||
type="file" />
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
<div class="overflow-hidden relative mt-4 mb-4">
|
||||
<button
|
||||
@@ -286,47 +256,50 @@
|
||||
cancelModal();
|
||||
}}
|
||||
type="button"
|
||||
class="w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 md:ml-40 mr-0 sm:ml-0 sm:w-auto sm:text-sm">
|
||||
{$_('cancel')}
|
||||
class="w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 md:ml-40 mr-0 sm:ml-0 sm:w-auto sm:text-sm"
|
||||
>
|
||||
{$_("cancel")}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{#if json_output.length > 0}
|
||||
{#if opened_from === 'OrgOverview'}
|
||||
<p>{$_('import__target-organization')}</p>
|
||||
{#if opened_from === "OrgOverview"}
|
||||
<p>{$_("import__target-organization")}</p>
|
||||
<select
|
||||
name="team"
|
||||
bind:value={selected_org}
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2">
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
>
|
||||
{#each passed_orgs as o}
|
||||
<option value={o.id}>{o.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<p>{$_('bitte-bestaetige-diese-laeufer-fuer-den-import')}</p>
|
||||
<p>{$_("confirm-runner-import")}</p>
|
||||
{/if}
|
||||
{#if opened_from === 'RunnerOverview'}
|
||||
<p>{$_('group')}</p>
|
||||
{#if opened_from === "RunnerOverview"}
|
||||
<p>{$_("group")}</p>
|
||||
<Select
|
||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
itemFilter={(label, filterText, option) => label
|
||||
.toLowerCase()
|
||||
.includes(
|
||||
filterText.toLowerCase()
|
||||
) || option.id.value
|
||||
itemFilter={(label, filterText, option) =>
|
||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||
option.id.value
|
||||
.toString()
|
||||
.startsWith(filterText.toLowerCase())}
|
||||
items={groups}
|
||||
showChevron={true}
|
||||
placeholder={$_('search-for-an-organization-or-team-by-name-or-id')}
|
||||
noOptionsMessage={$_('no-organization-or-team-found')}
|
||||
placeholder={$_(
|
||||
"search-for-an-organization-or-team-by-name-or-id"
|
||||
)}
|
||||
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||
on:select={(selectedValue) => {
|
||||
selected_org_or_team = selectedValue.detail.value;
|
||||
}}
|
||||
on:clear={() => (selected_org_or_team = null)} />
|
||||
on:clear={() => (selected_org_or_team = null)}
|
||||
/>
|
||||
{/if}
|
||||
{#if opened_from === 'OrgDetail'}
|
||||
{#if opened_from === "OrgDetail"}
|
||||
<p>
|
||||
{$_('runnerimport_verify_runners_org', {
|
||||
{$_("runnerimport_verify_runners_org", {
|
||||
values: { org_name: passed_org.name },
|
||||
})}
|
||||
</p>
|
||||
@@ -334,9 +307,10 @@
|
||||
<input
|
||||
type="search"
|
||||
bind:value={searchvalue}
|
||||
placeholder={$_('datatable.search')}
|
||||
aria-label={$_('datatable.search')}
|
||||
class="p-2 w-full" />
|
||||
placeholder={$_("datatable.search")}
|
||||
aria-label={$_("datatable.search")}
|
||||
class="p-2 w-full"
|
||||
/>
|
||||
<div class="relative w-full mt-4 mb-4">
|
||||
<div class="w-full overflow-x-auto">
|
||||
<table class="divide-y divide-gray-200 w-full">
|
||||
@@ -344,24 +318,28 @@
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('csv_import__firstname')}
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
{$_("csv_import__firstname")}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('csv_import__middlename')}
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
{$_("csv_import__middlename")}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('csv_import__lastname')}
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
{$_("csv_import__lastname")}
|
||||
</th>
|
||||
{#if (opened_from !== 'TeamDetail' && opened_from !== 'RunnerOverview') || (opened_from === 'RunnerOverview' && selected_org_or_team.includes('ORG_'))}
|
||||
{#if (opened_from !== "TeamDetail" && opened_from !== "RunnerOverview") || (opened_from === "RunnerOverview" && selected_org_or_team.includes("ORG_"))}
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('csv_import__team')}
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||
>
|
||||
{$_("csv_import__team")}
|
||||
</th>
|
||||
{/if}
|
||||
</tr>
|
||||
@@ -374,17 +352,19 @@
|
||||
.includes(searchvalue)}
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{runner[`${$_('csv_import__firstname')}`]}
|
||||
{runner[`${$_("csv_import__firstname")}`]}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{runner[`${$_('csv_import__middlename')}`] || ''}
|
||||
{runner[`${$_("csv_import__middlename")}`] || ""}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{runner[`${$_('csv_import__lastname')}`]}
|
||||
{runner[`${$_("csv_import__lastname")}`]}
|
||||
</td>
|
||||
{#if (opened_from !== 'TeamDetail' && opened_from !== 'RunnerOverview') || (opened_from === 'RunnerOverview' && selected_org_or_team.includes('ORG_'))}
|
||||
{#if (opened_from !== "TeamDetail" && opened_from !== "RunnerOverview") || (opened_from === "RunnerOverview" && selected_org_or_team.includes("ORG_"))}
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{runner[`${$_('csv_import__team')}`] || runner[`${$_('csv_import__class')}`] || '---'}
|
||||
{runner[`${$_("csv_import__team")}`] ||
|
||||
runner[`${$_("csv_import__class")}`] ||
|
||||
"---"}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
@@ -398,16 +378,18 @@
|
||||
class:opacity-50={!importButtonEnabled}
|
||||
on:click={importAction}
|
||||
type="button"
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
{$_('import-runners')}
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>
|
||||
{$_("import-runners")}
|
||||
</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
cancelModal();
|
||||
}}
|
||||
type="button"
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
{$_('cancel')}
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>
|
||||
{$_("cancel")}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,321 +1,315 @@
|
||||
<script>
|
||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||
import store from "../../store";
|
||||
import {
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import Select from "svelte-select";
|
||||
let data_loaded = false;
|
||||
export let params;
|
||||
const runner_promise = RunnerService.runnerControllerGetOne(params.runnerid);
|
||||
$: delete_triggered = false;
|
||||
$: original_data_pdf = {};
|
||||
$: original_data = {};
|
||||
$: editable = {};
|
||||
$: group = {};
|
||||
$: changes_performed = !(
|
||||
JSON.stringify(original_data) == JSON.stringify(editable)
|
||||
);
|
||||
$: isEmailValid =
|
||||
(editable.email || "") === "" ||
|
||||
(editable.email && isEmail(editable.email || ""));
|
||||
$: isFirstnameValid = editable.firstname !== "";
|
||||
$: isLastnameValid = editable.lastname !== "";
|
||||
$: save_enabled =
|
||||
changes_performed &&
|
||||
isFirstnameValid &&
|
||||
isLastnameValid &&
|
||||
isEmailValid &&
|
||||
editable.group != null;
|
||||
$: sponsoring_contracts_show = true;
|
||||
$: cards_show = true;
|
||||
$: certificates_show = true;
|
||||
$: generate_runners = [original_data_pdf];
|
||||
runner_promise.then((data) => {
|
||||
data_loaded = true;
|
||||
original_data_pdf = Object.assign(original_data_pdf, data);
|
||||
data.group = data.group.id;
|
||||
original_data = Object.assign(original_data, data);
|
||||
editable = Object.assign(editable, original_data);
|
||||
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||
(val) => {
|
||||
const orgs = val.map((r) => {
|
||||
return { label: r.name, value: r };
|
||||
});
|
||||
groups = groups.concat(orgs);
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
const teams = val.map((r) => {
|
||||
return { label: `${r.parentGroup.name} > ${r.name}`, value: r };
|
||||
});
|
||||
groups = groups.concat(teams);
|
||||
group = groups.find((g) => g.value.id == editable.group);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
let groups = [];
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
Toastify({
|
||||
text: $_("updating-runner"),
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
let postdata = {};
|
||||
postdata = Object.assign(postdata, editable);
|
||||
if (postdata.phone === "") {
|
||||
postdata.phone = null;
|
||||
}
|
||||
RunnerService.runnerControllerPut(original_data.id, postdata)
|
||||
.then((resp) => {
|
||||
Object.assign(original_data, editable);
|
||||
original_data = original_data;
|
||||
Toastify({
|
||||
text: $_("runner-updated"),
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
function deleteRunner() {
|
||||
RunnerService.runnerControllerRemove(original_data.id, true)
|
||||
.then((resp) => {
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await runner_promise}
|
||||
{$_("loading-runners")}
|
||||
{:then}
|
||||
<section class="container p-5 select-none">
|
||||
<div class="flex flex-row mb-4">
|
||||
<div class="w-full">
|
||||
<nav class="w-full flex">
|
||||
<ol class="list-none flex flex-row items-center justify-start">
|
||||
<li class="flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
||||
fill="currentColor"
|
||||
width="24"
|
||||
height="24"
|
||||
><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||
/></svg
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="./">{$_("runners")}</a><svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="h-3 w-3 mr-2 stroke-current"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><line x1="5" y1="12" x2="19" y2="12" />
|
||||
<polyline points="12 5 19 12 12 19" /></svg
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="mr-2"
|
||||
>{original_data.firstname}
|
||||
{original_data.middlename || ""}
|
||||
{original_data.lastname}</span
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||
{original_data.firstname}
|
||||
{original_data.middlename || ""}
|
||||
{original_data.lastname}
|
||||
<span data-id="runner_actions_${editable.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteRunner}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("confirm-deletion")}</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
delete_triggered = !delete_triggered;
|
||||
}}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
|
||||
>{$_("cancel")}</button
|
||||
>
|
||||
{/if}
|
||||
<GenerateSponsoringContracts
|
||||
bind:sponsoring_contracts_show
|
||||
bind:generate_runners
|
||||
/>
|
||||
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||
<GenerateRunnerCertificates
|
||||
bind:certificates_show
|
||||
bind:generate_runners
|
||||
/>
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
on:click={() => {
|
||||
delete_triggered = true;
|
||||
}}
|
||||
type="button"
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("delete-runner")}</button
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
disabled={!save_enabled}
|
||||
class:opacity-50={!save_enabled}
|
||||
type="button"
|
||||
on:click={submit}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("save-changes")}</button
|
||||
>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="text-sm w-full">
|
||||
<label for="firstname" class="font-medium text-gray-700"
|
||||
>{$_("first-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("first-name")}
|
||||
type="text"
|
||||
class:border-red-500={!isFirstnameValid}
|
||||
class:focus:border-red-500={!isFirstnameValid}
|
||||
class:focus:ring-red-500={!isFirstnameValid}
|
||||
bind:value={editable.firstname}
|
||||
name="firstname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isFirstnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("first-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="middlename" class="font-medium text-gray-700"
|
||||
>{$_("middle-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("middle-name")}
|
||||
type="text"
|
||||
bind:value={editable.middlename}
|
||||
name="middlename"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="lastname" class="font-medium text-gray-700"
|
||||
>{$_("last-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("last-name")}
|
||||
type="text"
|
||||
bind:value={editable.lastname}
|
||||
class:border-red-500={!isLastnameValid}
|
||||
class:focus:border-red-500={!isLastnameValid}
|
||||
class:focus:ring-red-500={!isLastnameValid}
|
||||
name="lastname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isLastnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("last-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="email" class="font-medium text-gray-700"
|
||||
>{$_("e-mail-adress")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("e-mail-adress")}
|
||||
type="email"
|
||||
bind:value={editable.email}
|
||||
class:border-red-500={!isEmailValid}
|
||||
class:focus:border-red-500={!isEmailValid}
|
||||
class:focus:ring-red-500={!isEmailValid}
|
||||
name="email"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isEmailValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("valid-email-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("phone")}
|
||||
type="tel"
|
||||
bind:value={editable.phone}
|
||||
name="phone"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium text-gray-700">{$_("group")}</span>
|
||||
<Select
|
||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
itemFilter={(label, filterText, option) =>
|
||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||
items={groups}
|
||||
showChevron={true}
|
||||
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
||||
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||
bind:selectedValue={group}
|
||||
on:select={(selectedValue) => {
|
||||
editable.group = selectedValue.detail.value.id;
|
||||
}}
|
||||
on:clear={() => (editable.group = null)}
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium text-gray-700">{$_("distance")}</span>
|
||||
<br />
|
||||
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||
</div>
|
||||
</section>
|
||||
{:catch error}
|
||||
<PromiseError {error} />
|
||||
{/await}
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||
import store from "../../store";
|
||||
import {
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import Select from "svelte-select";
|
||||
import toast from "svelte-french-toast";
|
||||
let data_loaded = false;
|
||||
export let params;
|
||||
const runner_promise = RunnerService.runnerControllerGetOne(params.runnerid);
|
||||
$: delete_triggered = false;
|
||||
$: original_data_pdf = {};
|
||||
$: original_data = {};
|
||||
$: editable = {};
|
||||
$: group = {};
|
||||
$: changes_performed = !(
|
||||
JSON.stringify(original_data) == JSON.stringify(editable)
|
||||
);
|
||||
$: isEmailValid =
|
||||
(editable.email || "") === "" ||
|
||||
(editable.email && isEmail(editable.email || ""));
|
||||
$: isFirstnameValid = editable.firstname !== "";
|
||||
$: isLastnameValid = editable.lastname !== "";
|
||||
$: save_enabled =
|
||||
changes_performed &&
|
||||
isFirstnameValid &&
|
||||
isLastnameValid &&
|
||||
isEmailValid &&
|
||||
editable.group != null;
|
||||
$: sponsoring_contracts_show = true;
|
||||
$: cards_show = true;
|
||||
$: certificates_show = true;
|
||||
$: generate_runners = [original_data_pdf];
|
||||
runner_promise.then((data) => {
|
||||
data_loaded = true;
|
||||
original_data_pdf = Object.assign(original_data_pdf, data);
|
||||
data.group = data.group.id;
|
||||
original_data = Object.assign(original_data, data);
|
||||
editable = Object.assign(editable, original_data);
|
||||
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||
(val) => {
|
||||
const orgs = val.map((r) => {
|
||||
return { label: r.name, value: r };
|
||||
});
|
||||
groups = groups.concat(orgs);
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
const teams = val.map((r) => {
|
||||
return { label: `${r.parentGroup.name} > ${r.name}`, value: r };
|
||||
});
|
||||
groups = groups.concat(teams);
|
||||
group = groups.find((g) => g.value.id == editable.group);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
let groups = [];
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
toast.loading($_("updating-runner"));
|
||||
let postdata = {};
|
||||
postdata = Object.assign(postdata, editable);
|
||||
if (postdata.phone === "") {
|
||||
postdata.phone = null;
|
||||
}
|
||||
RunnerService.runnerControllerPut(original_data.id, postdata)
|
||||
.then((resp) => {
|
||||
Object.assign(original_data, editable);
|
||||
original_data = original_data;
|
||||
toast.dismiss();
|
||||
toast.success($_("runner-updated"));
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
function deleteRunner() {
|
||||
RunnerService.runnerControllerRemove(original_data.id, true)
|
||||
.then((resp) => {
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await runner_promise}
|
||||
{$_("loading-runners")}
|
||||
{:then}
|
||||
<section class="container p-5 select-none">
|
||||
<div class="flex flex-row mb-4">
|
||||
<div class="w-full">
|
||||
<nav class="w-full flex">
|
||||
<ol class="list-none flex flex-row items-center justify-start">
|
||||
<li class="flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
||||
fill="currentColor"
|
||||
width="24"
|
||||
height="24"
|
||||
><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||
/></svg
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="./">{$_("runners")}</a><svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="h-3 w-3 mr-2 stroke-current"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><line x1="5" y1="12" x2="19" y2="12" />
|
||||
<polyline points="12 5 19 12 12 19" /></svg
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="mr-2"
|
||||
>{original_data.firstname}
|
||||
{original_data.middlename || ""}
|
||||
{original_data.lastname}</span
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||
{original_data.firstname}
|
||||
{original_data.middlename || ""}
|
||||
{original_data.lastname}
|
||||
<span data-id="runner_actions_${editable.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteRunner}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("confirm-deletion")}</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
delete_triggered = !delete_triggered;
|
||||
}}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
|
||||
>{$_("cancel")}</button
|
||||
>
|
||||
{/if}
|
||||
<GenerateSponsoringContracts
|
||||
bind:sponsoring_contracts_show
|
||||
bind:generate_runners
|
||||
/>
|
||||
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||
<GenerateRunnerCertificates
|
||||
bind:certificates_show
|
||||
bind:generate_runners
|
||||
/>
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
on:click={() => {
|
||||
delete_triggered = true;
|
||||
}}
|
||||
type="button"
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("delete-runner")}</button
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
disabled={!save_enabled}
|
||||
class:opacity-50={!save_enabled}
|
||||
type="button"
|
||||
on:click={submit}
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||
>{$_("save-changes")}</button
|
||||
>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="text-sm w-full">
|
||||
<label for="firstname" class="font-medium text-gray-700"
|
||||
>{$_("first-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("first-name")}
|
||||
type="text"
|
||||
class:border-red-500={!isFirstnameValid}
|
||||
class:focus:border-red-500={!isFirstnameValid}
|
||||
class:focus:ring-red-500={!isFirstnameValid}
|
||||
bind:value={editable.firstname}
|
||||
name="firstname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isFirstnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("first-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="middlename" class="font-medium text-gray-700"
|
||||
>{$_("middle-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("middle-name")}
|
||||
type="text"
|
||||
bind:value={editable.middlename}
|
||||
name="middlename"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="lastname" class="font-medium text-gray-700"
|
||||
>{$_("last-name")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("last-name")}
|
||||
type="text"
|
||||
bind:value={editable.lastname}
|
||||
class:border-red-500={!isLastnameValid}
|
||||
class:focus:border-red-500={!isLastnameValid}
|
||||
class:focus:ring-red-500={!isLastnameValid}
|
||||
name="lastname"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isLastnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("last-name-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="email" class="font-medium text-gray-700"
|
||||
>{$_("e-mail-adress")}</label
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("e-mail-adress")}
|
||||
type="email"
|
||||
bind:value={editable.email}
|
||||
class:border-red-500={!isEmailValid}
|
||||
class:focus:border-red-500={!isEmailValid}
|
||||
class:focus:ring-red-500={!isEmailValid}
|
||||
name="email"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
{#if !isEmailValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||
>
|
||||
{$_("valid-email-is-required")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_("phone")}
|
||||
type="tel"
|
||||
bind:value={editable.phone}
|
||||
name="phone"
|
||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium text-gray-700">{$_("group")}</span>
|
||||
<Select
|
||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||
itemFilter={(label, filterText, option) =>
|
||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||
items={groups}
|
||||
showChevron={true}
|
||||
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
||||
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||
bind:selectedValue={group}
|
||||
on:select={(selectedValue) => {
|
||||
editable.group = selectedValue.detail.value.id;
|
||||
}}
|
||||
on:clear={() => (editable.group = null)}
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium text-gray-700">{$_("distance")}</span>
|
||||
<br />
|
||||
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||
</div>
|
||||
</section>
|
||||
{:catch error}
|
||||
<PromiseError {error} />
|
||||
{/await}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<img class="w-full h-44" src={runners_empty} alt="" />
|
||||
<span class="font-bold">{$_('there-are-no-runners-added-yet')}</span><br />
|
||||
<span>{$_('add-your-first-runner')}</span>
|
||||
<span class="font-bold">{$_("there-are-no-runners-added-yet")}</span><br />
|
||||
<span>{$_("add-your-first-runner")}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,267 +1,261 @@
|
||||
<script>
|
||||
import {
|
||||
RunnerOrganizationService,
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import {
|
||||
createSvelteTable,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
renderComponent,
|
||||
} from "@tanstack/svelte-table";
|
||||
import { onMount } from "svelte";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { writable } from "svelte/store";
|
||||
import store from "../../store";
|
||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||
import InputElement from "../shared/InputElement.svelte";
|
||||
import TableActions from "../shared/TableActions.svelte";
|
||||
import { groupFilter } from "../shared/tablefilters";
|
||||
import DeleteRunnerModal from "./DeleteRunnerModal.svelte";
|
||||
import Toastify from "toastify-js";
|
||||
import TableBottom from "../shared/TableBottom.svelte";
|
||||
import TableHeader from "../shared/TableHeader.svelte";
|
||||
|
||||
$: selectedRunners =
|
||||
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||
$: selected =
|
||||
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||
|
||||
$: active_delete = undefined;
|
||||
let dataLoaded = false;
|
||||
export let current_runners = [];
|
||||
$: sponsoring_contracts_show = selected.length > 0;
|
||||
$: cards_show = selected.length > 0;
|
||||
$: certificates_show = selected.length > 0;
|
||||
$: teams = [];
|
||||
$: orgs = [];
|
||||
|
||||
export const addRunners = (runners) => {
|
||||
current_runners = current_runners.concat(...runners);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
};
|
||||
|
||||
//Section table
|
||||
const columns = [
|
||||
{
|
||||
accessorKey: "id",
|
||||
header: () => "id",
|
||||
filterFn: `equalsString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "firstname",
|
||||
header: () => $_("first-name"),
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "middlename",
|
||||
header: () => $_("middle-name"),
|
||||
cell: (info) => {
|
||||
if (!info || !info.getValue()) {
|
||||
return "";
|
||||
}
|
||||
return info.getValue();
|
||||
},
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "lastname",
|
||||
header: () => $_("last-name"),
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "group",
|
||||
header: () => $_("group"),
|
||||
cell: (info) => {
|
||||
const group = info.getValue();
|
||||
if (group.responseType === "RUNNERORGANIZATION") {
|
||||
return group.name;
|
||||
}
|
||||
return `${group.parentGroup.name} > ${group.name}`;
|
||||
},
|
||||
filterFn: `group`,
|
||||
},
|
||||
{
|
||||
accessorKey: "distance",
|
||||
header: () => $_("distance"),
|
||||
cell: (info) => {
|
||||
if (info.getValue() < 1000) {
|
||||
return `${info.getValue()} m`;
|
||||
}
|
||||
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
||||
},
|
||||
enableColumnFilter: false,
|
||||
},
|
||||
{
|
||||
accessorKey: "actions",
|
||||
header: () => $_("action"),
|
||||
cell: (info) => {
|
||||
return renderComponent(TableActions, {
|
||||
detailsLink: `./${info.row.original.id}`,
|
||||
deleteAction: () => {
|
||||
active_delete =
|
||||
current_runners[
|
||||
current_runners.findIndex((r) => r.id == info.row.original.id)
|
||||
];
|
||||
},
|
||||
deleteEnabled:
|
||||
store.state.jwtinfo.userdetails.permissions.includes(
|
||||
"RUNNER:DELETE"
|
||||
),
|
||||
});
|
||||
},
|
||||
enableColumnFilter: false,
|
||||
enableSorting: false,
|
||||
},
|
||||
];
|
||||
const options = writable({
|
||||
data: [],
|
||||
columns: columns,
|
||||
filterFns: {
|
||||
group: groupFilter,
|
||||
},
|
||||
initialState: {
|
||||
pagination: {
|
||||
pageSize: 50,
|
||||
},
|
||||
},
|
||||
enableRowSelection: true,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
});
|
||||
const table = createSvelteTable(options);
|
||||
|
||||
async function deleteRunner(delete_runner_id) {
|
||||
await RunnerService.runnerControllerRemove(delete_runner_id, true);
|
||||
current_runners = current_runners.filter((r) => r.id !== delete_runner_id);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
Toastify({
|
||||
text: $_("runner-deleted"),
|
||||
duration: 3500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
teams = val;
|
||||
});
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||
(val) => {
|
||||
orgs = val;
|
||||
}
|
||||
);
|
||||
|
||||
let page = 0;
|
||||
while (page >= 0) {
|
||||
const runners = await RunnerService.runnerControllerGetAll(page, 1000);
|
||||
if (runners.length == 0) {
|
||||
page = -2;
|
||||
}
|
||||
|
||||
current_runners = current_runners.concat(...runners);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
|
||||
dataLoaded = true;
|
||||
page++;
|
||||
}
|
||||
console.log("All runners loaded");
|
||||
});
|
||||
</script>
|
||||
|
||||
<DeleteRunnerModal
|
||||
delete_runner={active_delete}
|
||||
modal_open={active_delete != undefined}
|
||||
on:delete={(event) => {
|
||||
deleteRunner(event.detail.id);
|
||||
}}
|
||||
/>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||
{#if !dataLoaded}
|
||||
<div
|
||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||
role="alert"
|
||||
>
|
||||
<p class="font-bold">{$_("runners-are-being-loaded")}</p>
|
||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="h-12 mt-2">
|
||||
<GenerateSponsoringContracts
|
||||
bind:sponsoring_contracts_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
<GenerateRunnerCards
|
||||
bind:cards_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
<GenerateRunnerCertificates
|
||||
bind:certificates_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
{#each $table.getHeaderGroups() as headerGroup}
|
||||
<tr class="select-none">
|
||||
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||
<InputElement
|
||||
type="checkbox"
|
||||
checked={$table.getIsAllRowsSelected()}
|
||||
indeterminate={$table.getIsSomeRowsSelected()}
|
||||
on:change={() => $table.toggleAllRowsSelected()}
|
||||
/>
|
||||
</th>
|
||||
{#each headerGroup.headers as header}
|
||||
<TableHeader {header} />
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each $table.getRowModel().rows as row}
|
||||
<tr>
|
||||
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||
<InputElement
|
||||
type="checkbox"
|
||||
checked={row.getIsSelected()}
|
||||
on:change={() => row.toggleSelected()}
|
||||
/>
|
||||
</td>
|
||||
{#each row.getVisibleCells() as cell}
|
||||
<td>
|
||||
<svelte:component
|
||||
this={flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="h-2" />
|
||||
{/if}
|
||||
{/if}
|
||||
<TableBottom {table} {selected} />
|
||||
<script>
|
||||
import {
|
||||
RunnerOrganizationService,
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import {
|
||||
createSvelteTable,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
renderComponent,
|
||||
} from "@tanstack/svelte-table";
|
||||
import { onMount } from "svelte";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { writable } from "svelte/store";
|
||||
import store from "../../store";
|
||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||
import InputElement from "../shared/InputElement.svelte";
|
||||
import TableActions from "../shared/TableActions.svelte";
|
||||
import { groupFilter } from "../shared/tablefilters";
|
||||
import DeleteRunnerModal from "./DeleteRunnerModal.svelte";
|
||||
import TableBottom from "../shared/TableBottom.svelte";
|
||||
import TableHeader from "../shared/TableHeader.svelte";
|
||||
|
||||
$: selectedRunners =
|
||||
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||
$: selected =
|
||||
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||
|
||||
$: active_delete = undefined;
|
||||
let dataLoaded = false;
|
||||
export let current_runners = [];
|
||||
$: sponsoring_contracts_show = selected.length > 0;
|
||||
$: cards_show = selected.length > 0;
|
||||
$: certificates_show = selected.length > 0;
|
||||
$: teams = [];
|
||||
$: orgs = [];
|
||||
|
||||
export const addRunners = (runners) => {
|
||||
current_runners = current_runners.concat(...runners);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
};
|
||||
|
||||
//Section table
|
||||
const columns = [
|
||||
{
|
||||
accessorKey: "id",
|
||||
header: () => "id",
|
||||
filterFn: `equalsString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "firstname",
|
||||
header: () => $_("first-name"),
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "middlename",
|
||||
header: () => $_("middle-name"),
|
||||
cell: (info) => {
|
||||
if (!info || !info.getValue()) {
|
||||
return "";
|
||||
}
|
||||
return info.getValue();
|
||||
},
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "lastname",
|
||||
header: () => $_("last-name"),
|
||||
filterFn: `includesString`,
|
||||
},
|
||||
{
|
||||
accessorKey: "group",
|
||||
header: () => $_("group"),
|
||||
cell: (info) => {
|
||||
const group = info.getValue();
|
||||
if (group.responseType === "RUNNERORGANIZATION") {
|
||||
return group.name;
|
||||
}
|
||||
return `${group.parentGroup.name} > ${group.name}`;
|
||||
},
|
||||
filterFn: `group`,
|
||||
},
|
||||
{
|
||||
accessorKey: "distance",
|
||||
header: () => $_("distance"),
|
||||
cell: (info) => {
|
||||
if (info.getValue() < 1000) {
|
||||
return `${info.getValue()} m`;
|
||||
}
|
||||
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
||||
},
|
||||
enableColumnFilter: false,
|
||||
},
|
||||
{
|
||||
accessorKey: "actions",
|
||||
header: () => $_("action"),
|
||||
cell: (info) => {
|
||||
return renderComponent(TableActions, {
|
||||
detailsLink: `./${info.row.original.id}`,
|
||||
deleteAction: () => {
|
||||
active_delete =
|
||||
current_runners[
|
||||
current_runners.findIndex((r) => r.id == info.row.original.id)
|
||||
];
|
||||
},
|
||||
deleteEnabled:
|
||||
store.state.jwtinfo.userdetails.permissions.includes(
|
||||
"RUNNER:DELETE"
|
||||
),
|
||||
});
|
||||
},
|
||||
enableColumnFilter: false,
|
||||
enableSorting: false,
|
||||
},
|
||||
];
|
||||
const options = writable({
|
||||
data: [],
|
||||
columns: columns,
|
||||
filterFns: {
|
||||
group: groupFilter,
|
||||
},
|
||||
initialState: {
|
||||
pagination: {
|
||||
pageSize: 50,
|
||||
},
|
||||
},
|
||||
enableRowSelection: true,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
});
|
||||
const table = createSvelteTable(options);
|
||||
|
||||
async function deleteRunner(delete_runner_id) {
|
||||
await RunnerService.runnerControllerRemove(delete_runner_id, true);
|
||||
current_runners = current_runners.filter((r) => r.id !== delete_runner_id);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
toast($_("runner-deleted"));
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
teams = val;
|
||||
});
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||
(val) => {
|
||||
orgs = val;
|
||||
}
|
||||
);
|
||||
|
||||
let page = 0;
|
||||
while (page >= 0) {
|
||||
const runners = await RunnerService.runnerControllerGetAll(page, 1000);
|
||||
if (runners.length == 0) {
|
||||
page = -2;
|
||||
}
|
||||
|
||||
current_runners = current_runners.concat(...runners);
|
||||
options.update((options) => ({
|
||||
...options,
|
||||
data: current_runners,
|
||||
}));
|
||||
|
||||
dataLoaded = true;
|
||||
page++;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<DeleteRunnerModal
|
||||
delete_runner={active_delete}
|
||||
modal_open={active_delete != undefined}
|
||||
on:delete={(event) => {
|
||||
deleteRunner(event.detail.id);
|
||||
}}
|
||||
/>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||
{#if !dataLoaded}
|
||||
<div
|
||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||
role="alert"
|
||||
>
|
||||
<p class="font-bold">{$_("runners-are-being-loaded")}</p>
|
||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="h-12 mt-2">
|
||||
<GenerateSponsoringContracts
|
||||
bind:sponsoring_contracts_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
<GenerateRunnerCards
|
||||
bind:cards_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
<GenerateRunnerCertificates
|
||||
bind:certificates_show
|
||||
bind:generate_runners={selectedRunners}
|
||||
/>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
{#each $table.getHeaderGroups() as headerGroup}
|
||||
<tr class="select-none">
|
||||
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||
<InputElement
|
||||
type="checkbox"
|
||||
checked={$table.getIsAllRowsSelected()}
|
||||
indeterminate={$table.getIsSomeRowsSelected()}
|
||||
on:change={() => $table.toggleAllRowsSelected()}
|
||||
/>
|
||||
</th>
|
||||
{#each headerGroup.headers as header}
|
||||
<TableHeader {header} />
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each $table.getRowModel().rows as row}
|
||||
<tr>
|
||||
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||
<InputElement
|
||||
type="checkbox"
|
||||
checked={row.getIsSelected()}
|
||||
on:change={() => row.toggleSelected()}
|
||||
/>
|
||||
</td>
|
||||
{#each row.getVisibleCells() as cell}
|
||||
<td>
|
||||
<svelte:component
|
||||
this={flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
/>
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="h-2" />
|
||||
{/if}
|
||||
{/if}
|
||||
<TableBottom {table} {selected} />
|
||||
|
||||
Reference in New Issue
Block a user