parent
329c1cc037
commit
757655ea63
@ -3,6 +3,7 @@
|
|||||||
import { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { DataHandler, Datatable, Th, ThFilter } from "@vincjo/datatables";
|
||||||
import CardsEmptyState from "./CardsEmptyState.svelte";
|
import CardsEmptyState from "./CardsEmptyState.svelte";
|
||||||
import CardDetailModal from "./CardDetailModal.svelte";
|
import CardDetailModal from "./CardDetailModal.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
@ -11,271 +12,192 @@
|
|||||||
export let editable = {};
|
export let editable = {};
|
||||||
export let original_data = {};
|
export let original_data = {};
|
||||||
export let current_cards = [];
|
export let current_cards = [];
|
||||||
$: filtered_cards = current_cards.filter(function (c) {
|
const handler = new DataHandler(current_cards, { rowsPerPage: 50 });
|
||||||
if (
|
const rows = handler.getRows();
|
||||||
c.code.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.firstname.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.middlename.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.lastname.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
should_display_based_on_id(c.id)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$: searchvalue = "";
|
|
||||||
$: searchvalue_lowercase = searchvalue.toLowerCase();
|
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
$: cards_show = current_cards.some((r) => r.is_selected === true);
|
$: cards_show = generate_cards.length > 0;
|
||||||
$: generate_cards = current_cards.filter((r) => r.is_selected === true);
|
$: generate_cards = [];
|
||||||
const cards_promise = RunnerCardService.runnerCardControllerGetAll().then(
|
const cards_promise = RunnerCardService.runnerCardControllerGetAll().then(
|
||||||
(val) => {
|
(val) => {
|
||||||
current_cards = val;
|
current_cards = val;
|
||||||
|
handler.setRows(val);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
function should_display_based_on_id(id) {
|
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
|
||||||
}
|
|
||||||
return id.toString() === searchvalue;
|
|
||||||
}
|
|
||||||
const getRunnerLabel = (option) =>
|
const getRunnerLabel = (option) =>
|
||||||
option?.firstname + " " + (option?.middlename || "") + " " + (option?.lastname || "{$_('non-blanko')}");
|
option?.firstname +
|
||||||
|
" " +
|
||||||
|
(option?.middlename || "") +
|
||||||
|
" " +
|
||||||
|
(option?.lastname || "{$_('non-blanko')}");
|
||||||
function open_edit_modal(card) {
|
function open_edit_modal(card) {
|
||||||
if(card.runner?.id){
|
if (card.runner?.id) {
|
||||||
runner = Object.assign(
|
runner = Object.assign(
|
||||||
{ runner },
|
{ runner },
|
||||||
{ label: getRunnerLabel(card.runner), value: card.runner }
|
{ label: getRunnerLabel(card.runner), value: card.runner }
|
||||||
);
|
);
|
||||||
card.runner = card.runner.id;
|
card.runner = card.runner.id;
|
||||||
}
|
} else {
|
||||||
else{
|
card.runner = null;
|
||||||
card.runner=null;
|
runner = null;
|
||||||
runner = null
|
|
||||||
}
|
}
|
||||||
editable = Object.assign(editable, card);
|
editable = Object.assign(editable, card);
|
||||||
original_data = Object.assign(original_data, card);
|
original_data = Object.assign(original_data, card);
|
||||||
edit_modal_open = true;
|
edit_modal_open = true;
|
||||||
}
|
}
|
||||||
// -----------------
|
|
||||||
let scrollTop = 0;
|
|
||||||
$: rendered = filtered_cards;
|
|
||||||
let innerHeight = 0;
|
|
||||||
let ele;
|
|
||||||
$: updateSlice(scrollTop);
|
|
||||||
$: innerHeight = `${filtered_cards.length * 25}px`;
|
|
||||||
$: if (ele) updateSlice();
|
|
||||||
function updateSlice() {
|
|
||||||
const height = ele ? parseInt(ele.clientHeight) : 100;
|
|
||||||
const init = scrollTop / 25;
|
|
||||||
const end = Math.ceil((scrollTop + height) / 25);
|
|
||||||
rendered = filtered_cards.slice(init, end + 15);
|
|
||||||
}
|
|
||||||
function updateScroll($event) {
|
|
||||||
scrollTop = $event.target.scrollTop;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:UPDATE")}
|
||||||
table tbody {
|
|
||||||
display: block;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead, table tbody tr {
|
|
||||||
display: table;
|
|
||||||
width: 100%;
|
|
||||||
table-layout: fixed;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:UPDATE')}
|
|
||||||
<CardDetailModal
|
<CardDetailModal
|
||||||
bind:current_cards
|
bind:current_cards
|
||||||
bind:edit_modal_open
|
bind:edit_modal_open
|
||||||
bind:runner
|
bind:runner
|
||||||
bind:editable
|
bind:editable
|
||||||
bind:original_data />
|
bind:original_data
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
{#await cards_promise}
|
{#await cards_promise}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">{$_('loading-cards')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("loading-cards")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:then}
|
||||||
{#if current_cards.length === 0}
|
{#if current_cards.length === 0}
|
||||||
<CardsEmptyState />
|
<CardsEmptyState />
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
<div class="h-12">
|
||||||
type="search"
|
<GenerateRunnerCards bind:cards_show bind:generate_cards />
|
||||||
bind:value={searchvalue}
|
</div>
|
||||||
placeholder={$_('datatable.search')}
|
<Datatable {handler}>
|
||||||
aria-label={$_('datatable.search')}
|
<table>
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
<thead>
|
||||||
<div class="h-12">
|
|
||||||
<GenerateRunnerCards
|
|
||||||
bind:cards_show
|
|
||||||
bind:generate_cards />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
|
||||||
<thead class="bg-gray-50">
|
|
||||||
<tr>
|
<tr>
|
||||||
<th
|
<th>
|
||||||
scope="col"
|
<input
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
type="checkbox"
|
||||||
<span
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
checked={generate_cards.length == current_cards.length}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
const newstate = !current_cards.some((r) => r.is_selected === true);
|
if (generate_cards.length != current_cards.length) {
|
||||||
current_cards = current_cards.map((r) => {
|
generate_cards = current_cards;
|
||||||
r.is_selected = newstate;
|
} else {
|
||||||
return r;
|
generate_cards = [];
|
||||||
});
|
}
|
||||||
}}
|
}}
|
||||||
class="underline cursor-pointer select-none">{#if current_cards.some((r) => r.is_selected === true)}
|
/>
|
||||||
{$_('deselect-all')}
|
|
||||||
{:else}{$_('select-all')}{/if}
|
|
||||||
</span>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('code')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('runner')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('status')}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_('action')}</span>
|
|
||||||
</th>
|
</th>
|
||||||
|
<Th {handler} orderBy="code">{$_('code')}</Th>
|
||||||
|
<Th {handler} orderBy="runner">{$_('runner')}</Th>
|
||||||
|
<Th {handler} orderBy="status">{$_('status')}</Th>
|
||||||
|
<th>{$_("action")}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<ThFilter {handler} filterBy="code" />
|
||||||
|
<ThFilter {handler} filterBy="runner" />
|
||||||
|
<ThFilter {handler} filterBy="status" />
|
||||||
|
<th />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200 virtual-wrapper"
|
<tbody>
|
||||||
on:scroll={updateScroll}
|
{#each $rows as row}
|
||||||
style="height: 70vh; width:100%"
|
<tr>
|
||||||
bind:this={ele}
|
<td>
|
||||||
>
|
<input
|
||||||
{#each filtered_cards as card, index}
|
type="checkbox"
|
||||||
{#if card.code
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
.toLowerCase()
|
checked={generate_cards.filter((i) => i.id == row.id)
|
||||||
.includes(
|
.length > 0}
|
||||||
searchvalue.toLowerCase()
|
on:click={() => {
|
||||||
) || card.runner?.firstname
|
if (
|
||||||
.toLowerCase()
|
generate_cards.findIndex((i) => i.id == row.id) == -1
|
||||||
.includes(
|
) {
|
||||||
searchvalue.toLowerCase()
|
generate_cards.push(row);
|
||||||
) || card.runner?.middlename
|
generate_cards = generate_cards;
|
||||||
.toLowerCase()
|
} else {
|
||||||
.includes(
|
generate_cards = generate_cards.filter(
|
||||||
searchvalue.toLowerCase()
|
(r) => r.id != row.id
|
||||||
) || card.runner?.lastname
|
);
|
||||||
.toLowerCase()
|
}
|
||||||
.includes(
|
console.log(generate_cards);
|
||||||
searchvalue.toLowerCase()
|
}}
|
||||||
) || should_display_based_on_id(card.id)}
|
/>
|
||||||
<tr data-rowid="card_{card.id}">
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td>{row.code}</td>
|
||||||
<input
|
<td>{row.runner}</td>
|
||||||
bind:checked={card.is_selected}
|
<td>{row.enabled}</td>
|
||||||
type="checkbox"
|
<td>
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
{#if active_deletes[row.id] === true}
|
||||||
</td>
|
<button
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
on:click={() => {
|
||||||
<div class="flex items-center">{card.code}</div>
|
active_deletes[row.id] = false;
|
||||||
</td>
|
}}
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
tabindex="0"
|
||||||
<div class="flex items-center">
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
{#if card.runner}
|
>{$_("cancel-delete")}</button
|
||||||
<a
|
>
|
||||||
href="../runners/{card.runner.id}"
|
<button
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{card.runner.firstname}
|
on:click={() => {
|
||||||
{card.runner.middlename || ''}
|
RunnerCardService.runnerCardControllerRemove(row.id, true)
|
||||||
{card.runner.lastname}</a>
|
.then((resp) => {
|
||||||
{:else}{$_('non-blanko')}{/if}
|
current_cards = current_cards.filter(
|
||||||
</div>
|
(obj) => obj.id !== row.id
|
||||||
</td>
|
);
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
})
|
||||||
<div class="flex items-center">
|
.catch((err) => {});
|
||||||
{#if card.enabled}
|
}}
|
||||||
<span
|
tabindex="0"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('enabled')}</span>
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
{:else}
|
>{$_("confirm-delete")}</button
|
||||||
<span
|
>
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('disabled')}</span>
|
{:else}
|
||||||
{/if}
|
<a
|
||||||
</div>
|
href="./{row.id}"
|
||||||
</td>
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</a
|
||||||
{#if active_deletes[card.id] === true}
|
>
|
||||||
<td
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:DELETE")}
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<button
|
||||||
<button
|
on:click={() => {
|
||||||
on:click={() => {
|
active_deletes[row.id] = true;
|
||||||
active_deletes[card.id] = false;
|
}}
|
||||||
}}
|
tabindex="0"
|
||||||
tabindex="0"
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
>{$_("delete")}</button
|
||||||
<button
|
>
|
||||||
on:click={() => {
|
{/if}
|
||||||
RunnerCardService.runnerCardControllerRemove(card.id, false).then(
|
{/if}
|
||||||
(resp) => {
|
</td>
|
||||||
current_cards = current_cards.filter(
|
</tr>
|
||||||
(obj) => obj.id !== card.id
|
{/each}
|
||||||
);
|
|
||||||
Toastify({
|
|
||||||
text: $_('card-deleted'),
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor:
|
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
open_edit_modal(card);
|
|
||||||
}}
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</button>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[card.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</Datatable>
|
||||||
{/if}
|
{/if}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
||||||
<span class="inline-block align-middle mr-8">
|
<span class="inline-block align-middle mr-8">
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
<b class="capitalize">{$_("general_promise_error")}</b>
|
||||||
{error}
|
{error}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table tbody {
|
||||||
|
display: block;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead,
|
||||||
|
table tbody tr {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user