Merge commit '6d0bca6d6783d3f7bbff5d413b158c6b60720bd8' into feature/48-usergroup-management
ref #48
This commit is contained in:
commit
e442b92a5f
79 files changed
+2710
-841
No files matched your search
@@ -1,162 +0,0 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
export let modal_open;
|
||||
export let current_organizations;
|
||||
let name_input_dom;
|
||||
function focus(el) {
|
||||
el.focus();
|
||||
}
|
||||
$: name = "";
|
||||
$: processed_last_submit = true;
|
||||
$: isOrgnameValid = name.trim().length !== 0;
|
||||
$: createbtnenabled = isOrgnameValid;
|
||||
(() => {
|
||||
document.onkeydown = (e) => {
|
||||
e = e || window.event;
|
||||
if (e.key === "Escape") {
|
||||
modal_open = false;
|
||||
}
|
||||
if (e.keyCode === 13) {
|
||||
if (createbtnenabled === true) {
|
||||
createbtnenabled = false;
|
||||
submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
function submit() {
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: "Organization is being added...",
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
RunnerOrganizationService.runnerOrganizationControllerPost({
|
||||
name,
|
||||
address: undefined,
|
||||
contact: undefined,
|
||||
})
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
name = "";
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: "Organization added",
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
current_organizations = current_organizations.concat([result]);
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
//
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if modal_open}
|
||||
<div
|
||||
class="fixed z-10 inset-0 overflow-y-auto"
|
||||
use:focusTrap
|
||||
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">
|
||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||
<div
|
||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||
data-id="modal_backdrop" />
|
||||
</div>
|
||||
<span
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
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-lg sm:w-full"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
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">
|
||||
<svg
|
||||
class="h-6 w-6 text-blue-600"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path
|
||||
d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z" /></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 Organization
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
Please provide the required information to add a new
|
||||
organization.
|
||||
</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">Name</label>
|
||||
<input
|
||||
use:focus
|
||||
autocomplete="off"
|
||||
placeholder="Name"
|
||||
class:border-red-500={!isOrgnameValid}
|
||||
class:focus:border-red-500={!isOrgnameValid}
|
||||
class:focus:ring-red-500={!isOrgnameValid}
|
||||
bind:value={name}
|
||||
bind:this={name_input_dom}
|
||||
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" />
|
||||
{#if !isOrgnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Organization name is required
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<button
|
||||
disabled={!createbtnenabled}
|
||||
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')}
|
||||
</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')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,74 +0,0 @@
|
||||
<script>
|
||||
import "filepond/dist/filepond.css";
|
||||
import FilePond from "svelte-filepond";
|
||||
import { _ } from "svelte-i18n";
|
||||
let pond;
|
||||
// pond.getFiles() will return the active files
|
||||
// the name to use for the internal file input
|
||||
let name = "filepond";
|
||||
function handleInit() {
|
||||
// console.log("FilePond has initialised");
|
||||
}
|
||||
function handleAddFile(err, fileItem) {
|
||||
// console.log("A file has been added", fileItem);
|
||||
}
|
||||
const labelInvalidField = $_("filepond__field-contains-invalid-files");
|
||||
const labelFileWaitingForSize = $_("filepond__waiting-for-size");
|
||||
const labelFileSizeNotAvailable = $_("filepond__size-not-available");
|
||||
const labelFileLoading = $_("filepond__loading");
|
||||
const labelFileLoadError = $_("filepond__error-during-load");
|
||||
const labelFileProcessing = $_("filepond__uploading");
|
||||
const labelFileProcessingComplete = $_("filepond__upload-complete");
|
||||
const labelFileProcessingAborted = $_("filepond__upload-cancelled");
|
||||
const labelFileProcessingError = $_("filepond__error-during-upload");
|
||||
const labelFileProcessingRevertError = $_("filepond__error-during-revert");
|
||||
const labelFileRemoveError = $_("filepond__error-during-remove");
|
||||
const labelTapToCancel = $_("filepond__tap-to-cancel");
|
||||
const labelTapToRetry = $_("filepond__tap-to-retry");
|
||||
const labelTapToUndo = $_("filepond__tap-to-undo");
|
||||
const labelButtonRemoveItem = $_("filepond__remove");
|
||||
const labelButtonAbortItemLoad = $_("filepond__abort");
|
||||
const labelButtonRetryItemLoad = $_("filepond__retry");
|
||||
const labelButtonAbortItemProcessing = $_("filepond__cancel");
|
||||
const labelButtonUndoItemProcessing = $_("filepond__undo");
|
||||
const labelButtonRetryItemProcessing = $_("filepond__retry");
|
||||
const labelButtonProcessItem = $_("filepond__upload");
|
||||
const labelIdle =
|
||||
$_("drag-and-drop-your-files-or") +
|
||||
` <span class="filepond--label-action"> ` +
|
||||
$_("browse") +
|
||||
` </span>`;
|
||||
</script>
|
||||
|
||||
<div class="app">
|
||||
<FilePond
|
||||
bind:this={pond}
|
||||
{name}
|
||||
{labelFileWaitingForSize}
|
||||
{labelFileSizeNotAvailable}
|
||||
{labelFileLoading}
|
||||
{labelFileLoadError}
|
||||
{labelFileProcessing}
|
||||
{labelFileProcessingComplete}
|
||||
{labelFileProcessingAborted}
|
||||
{labelFileProcessingError}
|
||||
{labelFileProcessingRevertError}
|
||||
{labelFileRemoveError}
|
||||
{labelTapToCancel}
|
||||
{labelTapToRetry}
|
||||
{labelTapToUndo}
|
||||
{labelButtonRemoveItem}
|
||||
{labelButtonAbortItemLoad}
|
||||
{labelButtonRetryItemLoad}
|
||||
{labelButtonAbortItemProcessing}
|
||||
{labelButtonUndoItemProcessing}
|
||||
{labelButtonRetryItemProcessing}
|
||||
{labelButtonProcessItem}
|
||||
{labelIdle}
|
||||
{labelInvalidField}
|
||||
server="/api"
|
||||
allowMultiple={false}
|
||||
credits={false}
|
||||
oninit={handleInit}
|
||||
onaddfile={handleAddFile} />
|
||||
</div>
|
||||
@@ -1,239 +0,0 @@
|
||||
<script>
|
||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import store from "../store";
|
||||
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
|
||||
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
$: delete_triggered = false;
|
||||
$: save_enabled = !data_changed;
|
||||
export let params;
|
||||
let orgdata = {};
|
||||
let original = {};
|
||||
$: data_loaded = false;
|
||||
$: data_changed = JSON.stringify(orgdata) === JSON.stringify(original);
|
||||
const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne(
|
||||
params.orgid
|
||||
).then((value) => {
|
||||
data_loaded = true;
|
||||
orgdata = Object.assign(orgdata, value);
|
||||
original = Object.assign(original, value);
|
||||
});
|
||||
let modal_open = false;
|
||||
let delete_org = {};
|
||||
function deleteOrganization() {
|
||||
// RunnerOrganizationService.runnerOrganizationControllerRemove(
|
||||
// original.id,
|
||||
// false
|
||||
// )
|
||||
// .then((resp) => {
|
||||
// Toastify({
|
||||
// text: "Organization deleted",
|
||||
// duration: 500,
|
||||
// backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
// }).showToast();
|
||||
// location.replace("./");
|
||||
// })
|
||||
// .catch((err) => {
|
||||
modal_open = true;
|
||||
delete_org = original;
|
||||
// });
|
||||
}
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
Toastify({
|
||||
text: "updating organization",
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
RunnerOrganizationService.runnerOrganizationControllerPut(
|
||||
original.id,
|
||||
orgdata
|
||||
)
|
||||
.then((resp) => {
|
||||
Object.assign(original, orgdata);
|
||||
original = orgdata;
|
||||
Object.assign(original, orgdata);
|
||||
//
|
||||
Toastify({
|
||||
text: "updated organization",
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
export let import_modal_open = false;
|
||||
</script>
|
||||
|
||||
<ImportRunnerModal
|
||||
on:cancelDelete={(event) => {
|
||||
import_modal_open = false;
|
||||
}}
|
||||
current_runners={[]}
|
||||
passed_team={{}}
|
||||
passed_orgs={[]}
|
||||
passed_org={orgdata}
|
||||
opened_from="OrgDetail"
|
||||
bind:import_modal_open />
|
||||
<ConfirmOrgDeletion bind:modal_open bind:delete_org />
|
||||
{#if data_loaded}
|
||||
<section class="container p-5">
|
||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||
{original.name}
|
||||
<span data-id="org_actions_${orgdata.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:IMPORT')}
|
||||
<button
|
||||
on:click={() => {
|
||||
import_modal_open = true;
|
||||
}}
|
||||
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')}
|
||||
</button>
|
||||
{/if}
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteOrganization}
|
||||
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-delete')}</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}
|
||||
{#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-organization')}</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
on:click={submit}
|
||||
disabled={!save_enabled}
|
||||
class:opacity-50={!save_enabled}
|
||||
type="button"
|
||||
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="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="mr-2 flex items-center">
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="h-3 w-3 stroke-current"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"><path
|
||||
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||
<polyline points="9 22 9 12 15 12 15 22" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="/">Home</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="mr-2 flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="./">Orgs</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">Org-Details #{params.orgid}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="name" class="font-medium text-gray-700">Name</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Name"
|
||||
type="text"
|
||||
bind:value={orgdata.name}
|
||||
name="name"
|
||||
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="contact"
|
||||
class="font-medium text-gray-700">{$_('contact')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('contact')}
|
||||
type="text"
|
||||
bind:value={orgdata.contact}
|
||||
name="contact"
|
||||
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="address"
|
||||
class="font-medium text-gray-700">{$_('address')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('address')}
|
||||
type="text"
|
||||
bind:value={orgdata.address}
|
||||
name="address"
|
||||
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>
|
||||
</section>
|
||||
{:else}
|
||||
{#await promise}
|
||||
organization detail is being loaded...
|
||||
{:catch error}
|
||||
<PromiseError />
|
||||
{/await}
|
||||
{/if}
|
||||
@@ -1,5 +0,0 @@
|
||||
<script>
|
||||
import { _, locale } from "svelte-i18n";
|
||||
</script>
|
||||
|
||||
<div>$locale $_('hallo')</div>
|
||||
@@ -11,18 +11,13 @@
|
||||
if (isEmail(usersEmail)) {
|
||||
AuthService.authControllerGetResetToken({ email: usersEmail })
|
||||
.then((resp) => {
|
||||
console.log(resp);
|
||||
console.log(resp.resetToken);
|
||||
Toastify({
|
||||
text: $_("mail-validation-in-progress"),
|
||||
duration: 3500,
|
||||
}).showToast();
|
||||
reset_mail_sent = true;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.body.name);
|
||||
console.log(err.body.message);
|
||||
});
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
Toastify({
|
||||
text: $_("invalid-mail-reset"),
|
||||
@@ -40,9 +35,7 @@
|
||||
{$_('application_name')}
|
||||
</p>
|
||||
<p class="mt-2 mb-2 text-sm text-center text-gray-900">
|
||||
Passwort-Reset Mail wurde an
|
||||
{usersEmail}
|
||||
geschickt
|
||||
{$_('password-reset-mail-sent', { values: { usersEmail: usersEmail } })}
|
||||
</p>
|
||||
<div class="mt-6">
|
||||
<div class="mt-6">
|
||||
@@ -63,7 +56,7 @@
|
||||
{$_('application_name')}
|
||||
</p>
|
||||
<p class="mt-6 text-sm text-center text-gray-900">
|
||||
{$_('forgot_password?')}
|
||||
{$_('forgot_password')}
|
||||
</p>
|
||||
<p class="mt-2 mb-2 text-sm text-center text-gray-900">
|
||||
{$_('dont-panic-were-resetting-it')}
|
||||
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
import store from "../store.js";
|
||||
import store from "../../store.js";
|
||||
import localForage from "localforage";
|
||||
import { _ } from "svelte-i18n";
|
||||
store.init();
|
||||
import { OpenAPI, AuthService } from "@odit/lfk-client-js";
|
||||
import Footer from "./Footer.svelte";
|
||||
import Footer from "../general/Footer.svelte";
|
||||
import Toastify from "toastify-js";
|
||||
// ------
|
||||
let username = "demo";
|
||||
@@ -136,7 +136,7 @@
|
||||
<a
|
||||
href="/forgot_password"
|
||||
class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm">
|
||||
{$_('forgot_password?')}
|
||||
{$_('forgot_password')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
File renamed without changes.
File renamed without changes.
+2
-2
@@ -7,12 +7,12 @@
|
||||
<div class="w-full bg-white flex items-center justify-center ">
|
||||
<div class="max-w-sm m-8">
|
||||
<div class="text-black text-5xl md:text-15xl font-black">
|
||||
Internal Error
|
||||
{$_('internal-error')}
|
||||
</div>
|
||||
<div class="w-16 h-1 bg-purple-light my-3 md:my-6" />
|
||||
<p
|
||||
class="text-grey-darker text-2xl md:text-3xl font-light mb-8 leading-normal">
|
||||
Something went wrong in the UI logic
|
||||
{$_('generic-ui-logic-error')}
|
||||
</p>
|
||||
<a
|
||||
href="/"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,436 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import {
|
||||
GroupContactService,
|
||||
RunnerTeamService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
||||
import Toastify from "toastify-js";
|
||||
export let modal_open;
|
||||
export let current_contacts;
|
||||
$: selected_team = [];
|
||||
let firstname_input;
|
||||
let lastname_input;
|
||||
let middlename_input;
|
||||
let phone_input;
|
||||
let email_input;
|
||||
let address_input1;
|
||||
let address_input2;
|
||||
let address_zipcode;
|
||||
let address_city;
|
||||
let teams = [];
|
||||
let orgs = [];
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
teams = val;
|
||||
});
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
||||
orgs = val;
|
||||
});
|
||||
function focus(el) {
|
||||
el.focus();
|
||||
}
|
||||
$: middlename_input_value = "";
|
||||
$: phone_input_value = "";
|
||||
$: email_input_value = "";
|
||||
$: lastname_input_value = "";
|
||||
$: firstname_input_value = "";
|
||||
$: address_input1_value = "";
|
||||
$: address_input2_value = "";
|
||||
$: address_zipcode_value = "";
|
||||
$: address_city_value = "";
|
||||
$: processed_last_submit = true;
|
||||
$: address_checked = true;
|
||||
$: isPhoneValidOrEmpty =
|
||||
(phone_input_value.includes("+") &&
|
||||
isMobilePhone(
|
||||
phone_input_value
|
||||
.replaceAll("(", "")
|
||||
.replaceAll(")", "")
|
||||
.replaceAll("-", "")
|
||||
.replaceAll(" ", "")
|
||||
)) ||
|
||||
phone_input_value === "";
|
||||
$: isEmailValidOrEmpty =
|
||||
isEmail(email_input_value) || email_input_value === "";
|
||||
$: isLastnameValid = lastname_input_value.trim().length !== 0;
|
||||
$: isFirstnameValid = firstname_input_value.trim().length !== 0;
|
||||
$: isAddress1Valid = address_input1_value.trim().length !== 0;
|
||||
$: iszipcodevalid = address_zipcode_value.trim().length !== 0;
|
||||
$: iscityvalid = address_city_value.trim().length !== 0;
|
||||
$: createbtnenabled =
|
||||
isFirstnameValid &&
|
||||
isLastnameValid &&
|
||||
isEmailValidOrEmpty &&
|
||||
isPhoneValidOrEmpty &&
|
||||
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||
address_checked === false);
|
||||
(() => {
|
||||
document.onkeydown = (e) => {
|
||||
e = e || window.event;
|
||||
if (e.key === "Escape") {
|
||||
modal_open = false;
|
||||
}
|
||||
if (e.keyCode === 13) {
|
||||
if (createbtnenabled === true) {
|
||||
createbtnenabled = false;
|
||||
submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
function submit() {
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: "Contact is being added...",
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
let address = {};
|
||||
if (address_checked === true) {
|
||||
address = {
|
||||
address1: address_input1_value,
|
||||
address2: address_input2_value || "",
|
||||
postalcode: address_zipcode_value,
|
||||
city: address_city_value,
|
||||
country: "DE",
|
||||
};
|
||||
}
|
||||
let postdata = {
|
||||
groups: selected_team,
|
||||
firstname: firstname_input_value,
|
||||
lastname: lastname_input_value,
|
||||
address,
|
||||
};
|
||||
if (middlename_input_value) {
|
||||
postdata.middlename = middlename_input_value;
|
||||
}
|
||||
if (phone_input_value) {
|
||||
postdata.phone = phone_input_value;
|
||||
}
|
||||
if (email_input_value) {
|
||||
postdata.email = email_input_value;
|
||||
}
|
||||
GroupContactService.groupContactControllerPost(postdata)
|
||||
.then((result) => {
|
||||
firstname_input_value = "";
|
||||
lastname_input_value = "";
|
||||
middlename_input_value = "";
|
||||
email_input_value = "";
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: "Contact added",
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
current_contacts.push(result);
|
||||
current_contacts = current_contacts;
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
//
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if modal_open}
|
||||
<div
|
||||
class="fixed z-10 inset-0 overflow-y-auto"
|
||||
use:focusTrap
|
||||
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">
|
||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||
<div
|
||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||
data-id="modal_backdrop" />
|
||||
</div>
|
||||
<span
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
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-lg sm:w-full"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
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">
|
||||
<svg
|
||||
class="h-6 w-6 text-blue-600"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z" /></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-contact')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
{$_('please-provide-the-required-information-to-add-a-new-contact')}
|
||||
</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>
|
||||
<input
|
||||
use:focus
|
||||
autocomplete="off"
|
||||
placeholder={$_('first-name')}
|
||||
class:border-red-500={!isFirstnameValid}
|
||||
class:focus:border-red-500={!isFirstnameValid}
|
||||
class:focus:ring-red-500={!isFirstnameValid}
|
||||
bind:value={firstname_input_value}
|
||||
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" />
|
||||
{#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="col-span-6">
|
||||
<label
|
||||
for="trackname"
|
||||
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
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" />
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="lastname"
|
||||
class="block text-sm font-medium text-gray-700">Last Name</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Last Name"
|
||||
class:border-red-500={!isLastnameValid}
|
||||
class:focus:border-red-500={!isLastnameValid}
|
||||
class:focus:ring-red-500={!isLastnameValid}
|
||||
bind:value={lastname_input_value}
|
||||
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" />
|
||||
{#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="col-span-6">
|
||||
<label
|
||||
for="team"
|
||||
class="block text-sm font-medium text-gray-700">{$_('team')}</label>
|
||||
<select
|
||||
name="team"
|
||||
multiple
|
||||
bind:value={selected_team}
|
||||
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 teams as team}
|
||||
<option value={team.id}>
|
||||
{team.parentGroup.name}
|
||||
>
|
||||
{team.name}
|
||||
</option>
|
||||
{/each}
|
||||
{#each orgs as org}
|
||||
<option value={org.id}>{org.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="phone"
|
||||
class="block text-sm font-medium text-gray-700">{$_('phone')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('phone')}
|
||||
class:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||
bind:value={phone_input_value}
|
||||
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" />
|
||||
{#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')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="email"
|
||||
class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('e-mail-adress')}
|
||||
class:border-red-500={!isEmailValidOrEmpty}
|
||||
class:focus:border-red-500={!isEmailValidOrEmpty}
|
||||
class:focus:ring-red-500={!isEmailValidOrEmpty}
|
||||
bind:value={email_input_value}
|
||||
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" />
|
||||
{#if !isEmailValidOrEmpty}
|
||||
<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="flex items-start">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
bind:checked={address_checked}
|
||||
id="comments"
|
||||
name="comments"
|
||||
type="checkbox"
|
||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label
|
||||
for="comments"
|
||||
class="font-medium text-gray-700">{$_('address')}</label>
|
||||
</div>
|
||||
</div>
|
||||
{#if address_checked === true}
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address1"
|
||||
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Address"
|
||||
class:border-red-500={!isAddress1Valid}
|
||||
class:focus:border-red-500={!isAddress1Valid}
|
||||
class:focus:ring-red-500={!isAddress1Valid}
|
||||
bind:value={address_input1_value}
|
||||
bind:this={address_input1}
|
||||
type="text"
|
||||
name="address1"
|
||||
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 !isAddress1Valid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('address-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address2"
|
||||
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('apartment-suite-etc')}
|
||||
bind:value={address_input2_value}
|
||||
bind:this={address_input2}
|
||||
type="text"
|
||||
name="address2"
|
||||
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="zipcode"
|
||||
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('zip-postal-code')}
|
||||
class:border-red-500={!iszipcodevalid}
|
||||
class:focus:border-red-500={!iszipcodevalid}
|
||||
class:focus:ring-red-500={!iszipcodevalid}
|
||||
bind:value={address_zipcode_value}
|
||||
bind:this={address_zipcode}
|
||||
type="text"
|
||||
name="zipcode"
|
||||
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 !iszipcodevalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-zipcode-postal-code-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="city"
|
||||
class="block text-sm font-medium text-gray-700">City</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="City"
|
||||
class:border-red-500={!iscityvalid}
|
||||
class:focus:border-red-500={!iscityvalid}
|
||||
class:focus:ring-red-500={!iscityvalid}
|
||||
bind:value={address_city_value}
|
||||
bind:this={address_city}
|
||||
type="text"
|
||||
name="city"
|
||||
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 !iscityvalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-city-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<button
|
||||
disabled={!createbtnenabled}
|
||||
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')}
|
||||
</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')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,394 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../../store";
|
||||
import {
|
||||
GroupContactService,
|
||||
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";
|
||||
let data_loaded = false;
|
||||
let orgs = [];
|
||||
let teams = [];
|
||||
export let params;
|
||||
$: delete_triggered = false;
|
||||
$: original_data = {};
|
||||
$: editable = {};
|
||||
$: 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 &&
|
||||
isPhoneValidOrEmpty &&
|
||||
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||
editable.address_checked === false);
|
||||
const promise = GroupContactService.groupContactControllerGetOne(
|
||||
params.contact
|
||||
).then((data) => {
|
||||
data_loaded = true;
|
||||
original_data = Object.assign(original_data, data);
|
||||
editable = Object.assign(editable, original_data);
|
||||
editable.groups = editable.groups.map((g) => g.id);
|
||||
original_data.groups = original_data.groups.map((g) => g.id);
|
||||
editable.address_checked = editable.address.address1 !== null;
|
||||
original_data.address_checked = editable.address.address1 !== null;
|
||||
if(editable.address_checked===false){
|
||||
editable.address = {
|
||||
address1: "",
|
||||
address2: "",
|
||||
city: "",
|
||||
postalcode: "",
|
||||
country: ""
|
||||
}
|
||||
}
|
||||
});
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
||||
orgs = val;
|
||||
});
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
teams = val;
|
||||
});
|
||||
$: isPhoneValidOrEmpty =
|
||||
editable.phone?.includes("+") ||
|
||||
editable.phone === "" ||
|
||||
editable.phone === null;
|
||||
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
||||
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
||||
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
Toastify({
|
||||
text: $_("contact-is-being-updated"),
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
editable.address.country = "DE";
|
||||
if (editable.address_checked === false) {
|
||||
editable.address = null;
|
||||
}
|
||||
if (editable.email) editable.email = editable.email;
|
||||
if (editable.phone) editable.phone = editable.phone;
|
||||
if (editable.middlename) editable.middlename = editable.middlename;
|
||||
GroupContactService.groupContactControllerPut(original_data.id, editable)
|
||||
.then((resp) => {
|
||||
Object.assign(original_data, editable);
|
||||
original_data=original_data;
|
||||
Toastify({
|
||||
text: $_("updated-contact"),
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
function deleteContact() {
|
||||
GroupContactService.groupContactControllerRemove(original_data.id, true)
|
||||
.then((resp) => {
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await promise}
|
||||
{$_('loading-contact-details')}
|
||||
{: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
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center ml-2">
|
||||
<a class="mr-2" href="./">{$_('contacts')}</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="contact_actions_${editable.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CONTACT:DELETE')}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteContact}
|
||||
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}
|
||||
{#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-contact')}</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"
|
||||
class:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||
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" />
|
||||
{#if !isPhoneValidOrEmpty}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-international-phone-number-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium text-gray-700">{$_('groups')}</span>
|
||||
<select
|
||||
bind:value={editable.groups}
|
||||
name="team"
|
||||
multiple
|
||||
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 teams as team}
|
||||
<option value={team.id}>
|
||||
{team.parentGroup.name}
|
||||
>
|
||||
{team.name}
|
||||
</option>
|
||||
{/each}
|
||||
{#each orgs as org}
|
||||
<option value={org.id}>{org.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="flex items-start mt-2">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
bind:checked={editable.address_checked}
|
||||
id="comments"
|
||||
name="comments"
|
||||
type="checkbox"
|
||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label
|
||||
for="comments"
|
||||
class="font-medium text-gray-700">{$_('address')}</label>
|
||||
</div>
|
||||
</div>
|
||||
{#if editable.address_checked === true}
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address1"
|
||||
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Address"
|
||||
class:border-red-500={!isAddress1Valid}
|
||||
class:focus:border-red-500={!isAddress1Valid}
|
||||
class:focus:ring-red-500={!isAddress1Valid}
|
||||
bind:value={editable.address.address1}
|
||||
type="text"
|
||||
name="address1"
|
||||
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 !isAddress1Valid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('address-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address2"
|
||||
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('apartment-suite-etc')}
|
||||
bind:value={editable.address.address2}
|
||||
type="text"
|
||||
name="address2"
|
||||
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="zipcode"
|
||||
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('zip-postal-code')}
|
||||
class:border-red-500={!iszipcodevalid}
|
||||
class:focus:border-red-500={!iszipcodevalid}
|
||||
class:focus:ring-red-500={!iszipcodevalid}
|
||||
bind:value={editable.address.postalcode}
|
||||
type="text"
|
||||
name="zipcode"
|
||||
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 !iszipcodevalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-zipcode-postal-code-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="city"
|
||||
class="block text-sm font-medium text-gray-700">{$_('city')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('city')}
|
||||
class:border-red-500={!iscityvalid}
|
||||
class:focus:border-red-500={!iscityvalid}
|
||||
class:focus:ring-red-500={!iscityvalid}
|
||||
bind:value={editable.address.city}
|
||||
type="text"
|
||||
name="city"
|
||||
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 !iscityvalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-city-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
{:catch error}
|
||||
<PromiseError {error} />
|
||||
{/await}
|
||||
@@ -0,0 +1,29 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../../store";
|
||||
import AddContactModal from "./AddContactModal.svelte";
|
||||
import ContactsOverview from "./ContactsOverview.svelte";
|
||||
export let modal_open = false;
|
||||
let current_contacts = [];
|
||||
</script>
|
||||
|
||||
<section class="container p-5">
|
||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||
{$_('contacts')}
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CONTACT:CREATE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
modal_open = true;
|
||||
}}
|
||||
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-a-new-contact')}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
<ContactsOverview bind:current_contacts />
|
||||
</section>
|
||||
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CONTACT:CREATE')}
|
||||
<AddContactModal bind:current_contacts bind:modal_open />
|
||||
{/if}
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import AddContactModal from "./AddContactModal.svelte";
|
||||
import team_empty from "../teams/team_empty.svg";
|
||||
let modal_open = false;
|
||||
let current_contacts = [];
|
||||
</script>
|
||||
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<img class="w-full h-44" src={team_empty} alt="" />
|
||||
<span class="font-bold">{$_('there-are-no-contacts-added-yet')}</span><br />
|
||||
<span>{$_('add-your-first-contact')}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AddContactModal bind:modal_open bind:current_contacts />
|
||||
@@ -0,0 +1,177 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import { GroupContactService } from "@odit/lfk-client-js";
|
||||
const promise = GroupContactService.groupContactControllerGetAll().then(
|
||||
(result) => {
|
||||
current_contacts = result;
|
||||
}
|
||||
);
|
||||
import store from "../../store";
|
||||
import ContactsEmptyState from "./ContactsEmptyState.svelte";
|
||||
$: searchvalue = "";
|
||||
$: active_deletes = [];
|
||||
export let current_contacts = [];
|
||||
</script>
|
||||
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('TEAM:GET')}
|
||||
{#await promise}
|
||||
<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">{$_('contacts-are-being-loaded')}</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
{#if current_contacts.length === 0}
|
||||
<ContactsEmptyState />
|
||||
{:else}
|
||||
<input
|
||||
type="search"
|
||||
bind:value={searchvalue}
|
||||
placeholder={$_('datatable.search')}
|
||||
aria-label={$_('datatable.search')}
|
||||
class="gridjs-input gridjs-search-input mb-4" />
|
||||
<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>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('name')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('groups')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
{$_('address')}
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">{$_('action')}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
{#each current_contacts as t}
|
||||
{#if Object.values(t)
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.includes(searchvalue)}
|
||||
<tr data-rowid="team_{t.id}">
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{t.firstname}
|
||||
{t.middlename || ''}
|
||||
{t.lastname}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{#if t.groups.length > 0}
|
||||
{#each t.groups as g}
|
||||
{#if g.responseType === 'RUNNERORGANIZATION'}
|
||||
<a
|
||||
href="../orgs/{g.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
|
||||
{:else}
|
||||
<a
|
||||
href="../teams/{g.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.parentGroup.name}
|
||||
>
|
||||
{g.name}</a>
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
{$_('contact-is-not-a-member-in-any-group')}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{#if t.address.address1 !== null}
|
||||
{t.address.address1}<br />
|
||||
{t.address.address2 || ''}<br />
|
||||
{t.address.postalcode}
|
||||
{t.address.city}
|
||||
{t.address.country}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{#if active_deletes[t.id] === true}
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[t.id] = false;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
GroupContactService.groupContactControllerRemove(t.id, false).then(
|
||||
(resp) => {
|
||||
current_contacts = current_contacts.filter(
|
||||
(obj) => obj.id !== t.id
|
||||
);
|
||||
Toastify({
|
||||
text: $_('contact-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">
|
||||
<a
|
||||
href="./{t.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('TEAM:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[t.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>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
{:catch error}
|
||||
<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">
|
||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
||||
{error}
|
||||
</span>
|
||||
</div>
|
||||
{/await}
|
||||
{/if}
|
||||
@@ -1,11 +1,10 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import localForage from "localforage";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import { router } from "tinro";
|
||||
import NoComponentLoaded from "./NoComponentLoaded.svelte";
|
||||
import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
|
||||
import { AuthService } from "@odit/lfk-client-js";
|
||||
let dropdown1 = false;
|
||||
$: navOpen = false;
|
||||
function logout() {
|
||||
localForage.clear();
|
||||
@@ -131,6 +130,13 @@
|
||||
<span>UserGroups</span>
|
||||
</a>
|
||||
{/if}
|
||||
<a
|
||||
class:bg-gray-100={$router.path === '/contacts/'}
|
||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||
href="/contacts/">
|
||||
<svg fill="currentColor" class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"/></svg>
|
||||
<span>{$_('contacts')}</span>
|
||||
</a>
|
||||
<a
|
||||
class:bg-gray-100={$router.path === '/settings/'}
|
||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import StatCards from "./StatCards.svelte";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
let navOpen = false;
|
||||
</script>
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
on:click={() => {
|
||||
navOpen = false;
|
||||
}}>
|
||||
<!-- <div class="border-4 border-dashed rounded h-96" /> -->
|
||||
<h1 class="text-3xl leading-tight">
|
||||
<span class="font-extrabold">{$_('dashboard-title')}</span> <span>
|
||||
<span class="font-extrabold">{$_('dashboard-title')}</span>
|
||||
<span>
|
||||
-
|
||||
{$_('dashboard-greeting')},
|
||||
<span
|
||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
export let modal_open;
|
||||
(function () {
|
||||
File renamed without changes.
@@ -1,11 +1,14 @@
|
||||
<script>
|
||||
import { _, getLocaleFromNavigator } from "svelte-i18n";
|
||||
import * as css from "./simple.css";
|
||||
import marked from "marked";
|
||||
import Footer from "./Footer.svelte";
|
||||
import * as css from "../base/simple.css";
|
||||
let html = "";
|
||||
async function load() {
|
||||
let md = await fetch("/imprint_" + getLocaleFromNavigator() + ".md");
|
||||
if((await md.text()).includes("<meta")){
|
||||
md.ok=false
|
||||
}
|
||||
if (!md.ok) {
|
||||
md = await fetch("/imprint_en.md");
|
||||
}
|
||||
File renamed without changes.
@@ -1,11 +1,14 @@
|
||||
<script>
|
||||
import { _, getLocaleFromNavigator } from "svelte-i18n";
|
||||
import * as css from "./simple.css";
|
||||
import marked from "marked";
|
||||
import Footer from "./Footer.svelte";
|
||||
import * as css from "../base/simple.css";
|
||||
let html = "";
|
||||
async function load() {
|
||||
let md = await fetch("/privacy_" + getLocaleFromNavigator() + ".md");
|
||||
if((await md.text()).includes("<meta")){
|
||||
md.ok=false
|
||||
}
|
||||
if (!md.ok) {
|
||||
md = await fetch("/privacy_en.md");
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import FormLayout from "./FormLayout.svelte";
|
||||
import FormLayout from "../base/FormLayout.svelte";
|
||||
</script>
|
||||
|
||||
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
|
||||
@@ -32,4 +32,4 @@ import FormLayout from "./FormLayout.svelte";
|
||||
</div>
|
||||
<FormLayout />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
File renamed without changes.
@@ -0,0 +1,281 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
export let modal_open;
|
||||
export let current_organizations;
|
||||
let name_input_dom;
|
||||
function focus(el) {
|
||||
el.focus();
|
||||
}
|
||||
$: name = "";
|
||||
$: processed_last_submit = true;
|
||||
$: isOrgnameValid = name.trim().length !== 0;
|
||||
$: isAddress1Valid = address_input1_value.trim().length !== 0;
|
||||
$: iszipcodevalid = address_zipcode_value.trim().length !== 0;
|
||||
$: iscityvalid = address_city_value.trim().length !== 0;
|
||||
$: createbtnenabled =
|
||||
isOrgnameValid &&
|
||||
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||
address_checked === false);
|
||||
$: address_input1_value = "";
|
||||
$: address_input2_value = "";
|
||||
$: address_zipcode_value = "";
|
||||
$: address_city_value = "";
|
||||
$: address_checked = true;
|
||||
|
||||
let address_input1;
|
||||
let address_input2;
|
||||
let address_zipcode;
|
||||
let address_city;
|
||||
|
||||
(() => {
|
||||
document.onkeydown = (e) => {
|
||||
e = e || window.event;
|
||||
if (e.key === "Escape") {
|
||||
modal_open = false;
|
||||
}
|
||||
if (e.keyCode === 13) {
|
||||
if (createbtnenabled === true) {
|
||||
createbtnenabled = false;
|
||||
submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
function submit() {
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: $_("organization-is-being-added"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
let address = {};
|
||||
if (address_checked === true) {
|
||||
address = {
|
||||
address1: address_input1_value,
|
||||
address2: address_input2_value || "",
|
||||
postalcode: address_zipcode_value,
|
||||
city: address_city_value,
|
||||
country: "DE",
|
||||
};
|
||||
}
|
||||
RunnerOrganizationService.runnerOrganizationControllerPost({
|
||||
name,
|
||||
address: address,
|
||||
contact: undefined,
|
||||
})
|
||||
.then((result) => {
|
||||
name = "";
|
||||
modal_open = false;
|
||||
Toastify({
|
||||
text: $_("organization-added"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
current_organizations = current_organizations.concat([result]);
|
||||
})
|
||||
.catch((err) => {})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if modal_open}
|
||||
<div
|
||||
class="fixed z-10 inset-0 overflow-y-auto"
|
||||
use:focusTrap
|
||||
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">
|
||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||
<div
|
||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||
data-id="modal_backdrop" />
|
||||
</div>
|
||||
<span
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
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-lg sm:w-full"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
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">
|
||||
<svg
|
||||
class="h-6 w-6 text-blue-600"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path
|
||||
d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z" /></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-organization')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
{$_('please-provide-the-required-information-to-add-a-new-organization')}
|
||||
</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">{$_('name')}</label>
|
||||
<input
|
||||
use:focus
|
||||
autocomplete="off"
|
||||
placeholder={$_('name')}
|
||||
class:border-red-500={!isOrgnameValid}
|
||||
class:focus:border-red-500={!isOrgnameValid}
|
||||
class:focus:ring-red-500={!isOrgnameValid}
|
||||
bind:value={name}
|
||||
bind:this={name_input_dom}
|
||||
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" />
|
||||
{#if !isOrgnameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('organization-name-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex items-start">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
bind:checked={address_checked}
|
||||
id="comments"
|
||||
name="comments"
|
||||
type="checkbox"
|
||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label
|
||||
for="comments"
|
||||
class="font-medium text-gray-700">Address</label>
|
||||
</div>
|
||||
</div>
|
||||
{#if address_checked === true}
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address1"
|
||||
class="block text-sm font-medium text-gray-700">Address</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Address"
|
||||
class:border-red-500={!isAddress1Valid}
|
||||
class:focus:border-red-500={!isAddress1Valid}
|
||||
class:focus:ring-red-500={!isAddress1Valid}
|
||||
bind:value={address_input1_value}
|
||||
bind:this={address_input1}
|
||||
type="text"
|
||||
name="address1"
|
||||
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 !isAddress1Valid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Address is required
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address2"
|
||||
class="block text-sm font-medium text-gray-700">Apartment,
|
||||
suite, etc.</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Apartment, suite, etc."
|
||||
bind:value={address_input2_value}
|
||||
bind:this={address_input2}
|
||||
type="text"
|
||||
name="address2"
|
||||
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="zipcode"
|
||||
class="block text-sm font-medium text-gray-700">ZIP/ postal
|
||||
code</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="ZIP/ postal code"
|
||||
class:border-red-500={!iszipcodevalid}
|
||||
class:focus:border-red-500={!iszipcodevalid}
|
||||
class:focus:ring-red-500={!iszipcodevalid}
|
||||
bind:value={address_zipcode_value}
|
||||
bind:this={address_zipcode}
|
||||
type="text"
|
||||
name="zipcode"
|
||||
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 !iszipcodevalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Valid zipcode/ postal code is required
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="city"
|
||||
class="block text-sm font-medium text-gray-700">City</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="City"
|
||||
class:border-red-500={!iscityvalid}
|
||||
class:focus:border-red-500={!iscityvalid}
|
||||
class:focus:ring-red-500={!iscityvalid}
|
||||
bind:value={address_city_value}
|
||||
bind:this={address_city}
|
||||
type="text"
|
||||
name="city"
|
||||
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 !iscityvalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Valid city is required
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<button
|
||||
disabled={!createbtnenabled}
|
||||
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')}
|
||||
</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')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
+12
-10
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
@@ -25,9 +25,7 @@
|
||||
}).showToast();
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
});
|
||||
.catch((err) => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -68,13 +66,17 @@
|
||||
</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">
|
||||
Attention!
|
||||
{$_('attention')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
Do you want to delete the organization
|
||||
{delete_org.name}?<br />All associated teams and runners will
|
||||
be deleted too!
|
||||
{$_(
|
||||
'do-you-want-to-delete-the-organization-delete_org-name',
|
||||
{
|
||||
values: { orgname: delete_org.name },
|
||||
}
|
||||
)}<br />
|
||||
{$_('all-associated-teams-and-runners-will-be-deleted-too')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,13 +87,13 @@
|
||||
on:click={deleteOrg}
|
||||
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">
|
||||
Confirm, delete organization and associated teams+runners.
|
||||
{$_('confirm-delete-organization-and-associated-teams-runners')}
|
||||
</button>
|
||||
<button
|
||||
on:click={cancelDelete}
|
||||
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, keep organization
|
||||
{$_('cancel-keep-organization')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,361 @@
|
||||
<script>
|
||||
import {
|
||||
GroupContactService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import store from "../../store";
|
||||
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
|
||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
$: delete_triggered = false;
|
||||
$: address_valid_or_none =
|
||||
(isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||
editable.address_checked === false;
|
||||
$: save_enabled = data_changed && address_valid_or_none;
|
||||
let original = "";
|
||||
let original_object = {};
|
||||
let contacts = [];
|
||||
export let params;
|
||||
$: editable = {};
|
||||
$: data_loaded = false;
|
||||
$: data_changed = !(JSON.stringify(editable) === original);
|
||||
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
||||
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
||||
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
||||
|
||||
const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne(
|
||||
params.orgid
|
||||
).then((value) => {
|
||||
data_loaded = true;
|
||||
if (value.contact) {
|
||||
if (value.contact !== "null") {
|
||||
value.contact = value.contact.id;
|
||||
}
|
||||
}
|
||||
value.address_checked = value.address.address1 !== null;
|
||||
if(value.address_checked===false){
|
||||
value.address = {
|
||||
address1: "",
|
||||
address2: "",
|
||||
city: "",
|
||||
postalcode: "",
|
||||
country: ""
|
||||
}
|
||||
}
|
||||
editable = Object.assign(editable, value);
|
||||
editable = editable;
|
||||
original_object = Object.assign(editable, value);
|
||||
original = JSON.stringify(value);
|
||||
});
|
||||
GroupContactService.groupContactControllerGetAll().then((val) => {
|
||||
contacts = val;
|
||||
});
|
||||
let modal_open = false;
|
||||
let delete_org = {};
|
||||
function deleteOrganization() {
|
||||
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
||||
original_object.id,
|
||||
false
|
||||
)
|
||||
.then((resp) => {
|
||||
Toastify({
|
||||
text: $_("organization-deleted"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {
|
||||
modal_open = true;
|
||||
delete_org = original_object;
|
||||
});
|
||||
}
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
Toastify({
|
||||
text: $_("updating-organization"),
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
let postdata = Object.assign({}, editable);
|
||||
if (postdata.address_checked === false) {
|
||||
postdata.address = null;
|
||||
}
|
||||
console.log(postdata)
|
||||
postdata.contact = postdata.contact === "null" ? null : postdata.contact;
|
||||
RunnerOrganizationService.runnerOrganizationControllerPut(
|
||||
original_object.id,
|
||||
postdata
|
||||
)
|
||||
.then((resp) => {
|
||||
original = JSON.stringify(editable);
|
||||
Toastify({
|
||||
text: $_("updated-organization"),
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
export let import_modal_open = false;
|
||||
</script>
|
||||
|
||||
<ImportRunnerModal
|
||||
on:cancelDelete={(event) => {
|
||||
import_modal_open = false;
|
||||
}}
|
||||
current_runners={[]}
|
||||
passed_team={{}}
|
||||
passed_orgs={[]}
|
||||
passed_org={editable}
|
||||
opened_from="OrgDetail"
|
||||
bind:import_modal_open />
|
||||
<ConfirmOrgDeletion bind:modal_open bind:delete_org />
|
||||
{#if data_loaded}
|
||||
<section class="container p-5">
|
||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||
{original_object.name}
|
||||
<span data-id="org_actions_${editable.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:IMPORT')}
|
||||
<button
|
||||
on:click={() => {
|
||||
import_modal_open = true;
|
||||
}}
|
||||
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')}
|
||||
</button>
|
||||
{/if}
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteOrganization}
|
||||
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-delete')}</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}
|
||||
{#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-organization')}</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !delete_triggered}
|
||||
<button
|
||||
on:click={submit}
|
||||
disabled={!save_enabled}
|
||||
class:opacity-50={!save_enabled}
|
||||
type="button"
|
||||
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="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="mr-2 flex items-center">
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="h-3 w-3 stroke-current"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"><path
|
||||
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||
<polyline points="9 22 9 12 15 12 15 22" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="/">{$_('home')}</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="mr-2 flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<a class="mr-2" href="./">{$_('organizations')}</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">Org-Details #{params.orgid}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="name" class="font-medium text-gray-700">{$_('name')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('name')}
|
||||
type="text"
|
||||
bind:value={editable.name}
|
||||
name="name"
|
||||
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="contact"
|
||||
class="font-medium text-gray-700">{$_('contact')}</label>
|
||||
<select
|
||||
name="contact"
|
||||
bind:value={editable.contact}
|
||||
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">
|
||||
<option value="null">no contact</option>
|
||||
{#each contacts as c}
|
||||
<option value={c.id}>
|
||||
{c.firstname}
|
||||
{c.middlename || ''}
|
||||
{c.lastname}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="flex items-start mt-2">
|
||||
<div class="flex items-center h-5">
|
||||
<input
|
||||
bind:checked={editable.address_checked}
|
||||
id="comments"
|
||||
name="comments"
|
||||
type="checkbox"
|
||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label
|
||||
for="comments"
|
||||
class="font-medium text-gray-700">{$_('address')}</label>
|
||||
</div>
|
||||
</div>
|
||||
{#if editable.address_checked === true}
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address1"
|
||||
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder="Address"
|
||||
class:border-red-500={!isAddress1Valid}
|
||||
class:focus:border-red-500={!isAddress1Valid}
|
||||
class:focus:ring-red-500={!isAddress1Valid}
|
||||
bind:value={editable.address.address1}
|
||||
type="text"
|
||||
name="address1"
|
||||
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 !isAddress1Valid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('address-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="address2"
|
||||
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('apartment-suite-etc')}
|
||||
bind:value={editable.address.address2}
|
||||
type="text"
|
||||
name="address2"
|
||||
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="zipcode"
|
||||
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('zip-postal-code')}
|
||||
class:border-red-500={!iszipcodevalid}
|
||||
class:focus:border-red-500={!iszipcodevalid}
|
||||
class:focus:ring-red-500={!iszipcodevalid}
|
||||
bind:value={editable.address.postalcode}
|
||||
type="text"
|
||||
name="zipcode"
|
||||
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 !iszipcodevalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-zipcode-postal-code-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="city"
|
||||
class="block text-sm font-medium text-gray-700">{$_('city')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('city')}
|
||||
class:border-red-500={!iscityvalid}
|
||||
class:focus:border-red-500={!iscityvalid}
|
||||
class:focus:ring-red-500={!iscityvalid}
|
||||
bind:value={editable.address.city}
|
||||
type="text"
|
||||
name="city"
|
||||
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 !iscityvalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('valid-city-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
{:else}
|
||||
{#await promise}
|
||||
{$_('organization-detail-is-being-loaded')}
|
||||
{:catch error}
|
||||
<PromiseError />
|
||||
{/await}
|
||||
{/if}
|
||||
@@ -3,7 +3,7 @@
|
||||
let modal_open = false;
|
||||
let delete_org = {};
|
||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import OrgsEmptyState from "./OrgsEmptyState.svelte";
|
||||
import Toastify from "toastify-js";
|
||||
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
|
||||
@@ -30,7 +30,7 @@
|
||||
<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">organizations are being loaded...</p>
|
||||
<p class="font-bold">{$_('organizations-are-being-loaded')}</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
@@ -51,20 +51,20 @@
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Name
|
||||
{$_('name')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Address
|
||||
{$_('address')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Contact
|
||||
{$_('contact')}
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">Action</span>
|
||||
<span class="sr-only">{$_('action')}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -78,8 +78,7 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{o.name}
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,11 +87,14 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900">
|
||||
{#if o.address}
|
||||
{JSON.stringify(o.address)}
|
||||
{:else}no address specified{/if}
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{#if o.address.address1 !== null}
|
||||
{o.address.address1}<br />
|
||||
{o.address.address2 || ''}<br />
|
||||
{o.address.postalcode}
|
||||
{o.address.city}
|
||||
{o.address.country}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,11 +102,14 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{#if o.contact}
|
||||
{JSON.stringify(o.contact)}
|
||||
{:else}no contact specified{/if}
|
||||
<a
|
||||
href="../contacts/{o.contact.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{o.contact.firstname}
|
||||
{o.contact.middlename || ''}
|
||||
{o.contact.lastname}</a>
|
||||
{:else}{$_('no-contact-specified')}{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -117,8 +122,7 @@
|
||||
active_deletes[o.id] = false;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">Cancel
|
||||
Delete</button>
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
RunnerOrganizationService.runnerOrganizationControllerRemove(o.id, false)
|
||||
@@ -137,22 +141,21 @@
|
||||
});
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
|
||||
Delete</button>
|
||||
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">
|
||||
<a
|
||||
href="./{o.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">Edit</a>
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('ORGANIZATION:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[o.id] = true;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</button>
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import AddOrgModal from "./AddOrgModal.svelte";
|
||||
export let modal_open = false;
|
||||
import OrgOverview from "./OrgOverview.svelte";
|
||||
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||
let current_organizations = [];
|
||||
export let import_modal_open = false;
|
||||
</script>
|
||||
@@ -33,7 +33,6 @@
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">manage runner organizations</p>
|
||||
<OrgOverview bind:current_organizations />
|
||||
</section>
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<img class="w-full h-44" src={org_empty} alt="" />
|
||||
<span class="font-bold">There are no organizations added yet.</span><br />
|
||||
<span>Add your first organization</span>
|
||||
<span
|
||||
class="font-bold">{$_('there-are-no-organizations-added-yet')}</span><br />
|
||||
<span>{$_('add-your-first-organization')}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -28,7 +28,7 @@
|
||||
Role
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">Edit</span>
|
||||
<span class="sr-only">{$_('edit')}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -71,7 +71,7 @@
|
||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<a
|
||||
href="#"
|
||||
class="text-indigo-600 hover:text-indigo-900">Edit</a>
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+13
-11
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import {
|
||||
RunnerService,
|
||||
@@ -36,13 +36,15 @@
|
||||
$: firstname_input_value = "";
|
||||
$: processed_last_submit = true;
|
||||
$: isPhoneValidOrEmpty =
|
||||
isMobilePhone(
|
||||
phone_input_value
|
||||
.replaceAll("(", "")
|
||||
.replaceAll(")", "")
|
||||
.replaceAll("-", "")
|
||||
.replaceAll(" ", "")
|
||||
) || phone_input_value === "";
|
||||
(phone_input_value.includes("+") &&
|
||||
isMobilePhone(
|
||||
phone_input_value
|
||||
.replaceAll("(", "")
|
||||
.replaceAll(")", "")
|
||||
.replaceAll("-", "")
|
||||
.replaceAll(" ", "")
|
||||
)) ||
|
||||
phone_input_value === "";
|
||||
$: isEmailValidOrEmpty =
|
||||
isEmail(email_input_value) || email_input_value === "";
|
||||
$: isLastnameValid = lastname_input_value.trim().length !== 0;
|
||||
@@ -70,7 +72,7 @@
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: "Runner is being added...",
|
||||
text: $_("runner-is-being-added"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
let postdata = {
|
||||
@@ -96,7 +98,7 @@
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: "Runner added",
|
||||
text: $_("runner-added"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
@@ -258,7 +260,7 @@
|
||||
{#if !isPhoneValidOrEmpty}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
{$_('the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number')}
|
||||
{@html $_('the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
+7
-7
@@ -2,7 +2,7 @@
|
||||
import csv from "csvtojson";
|
||||
import { read as readXlsx, utils as xlsx_utils } from "xlsx";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import Toastify from "toastify-js";
|
||||
import {
|
||||
@@ -77,7 +77,7 @@
|
||||
function importAction() {
|
||||
if (recent_processed === true) {
|
||||
const toast = Toastify({
|
||||
text: "Runners are being imported...",
|
||||
text: $_("runners-are-being-imported"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
recent_processed = false;
|
||||
@@ -104,7 +104,7 @@
|
||||
toast.hideToast();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: "Import finished",
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
@@ -121,7 +121,7 @@
|
||||
toast.hideToast();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: "Import finished",
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
@@ -144,7 +144,7 @@
|
||||
toast.hideToast();
|
||||
recent_processed = true;
|
||||
Toastify({
|
||||
text: "Import finished",
|
||||
text: $_("import-finished"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
@@ -201,7 +201,7 @@
|
||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||
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-lg sm:w-full"
|
||||
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">
|
||||
@@ -253,7 +253,7 @@
|
||||
<p>{$_('bitte-bestaetige-diese-laeufer-fuer-den-import')}</p>
|
||||
{/if}
|
||||
{#if opened_from === 'RunnerOverview'}
|
||||
<p>Group</p>
|
||||
<p>{$_('group')}</p>
|
||||
<select
|
||||
name="team"
|
||||
bind:value={selected_org_or_team}
|
||||
@@ -1,14 +1,14 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import lodashIsEqual from "lodash.isequal";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import {
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
let data_loaded = false;
|
||||
export let params;
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import AddRunnerModal from "./AddRunnerModal.svelte";
|
||||
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
||||
import RunnersOverview from "./RunnersOverview.svelte";
|
||||
@@ -19,7 +19,7 @@
|
||||
}}
|
||||
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">
|
||||
Läufer hinzufügen
|
||||
{$_('laeufer-hinzufuegen')}
|
||||
</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
@@ -27,7 +27,7 @@
|
||||
}}
|
||||
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">
|
||||
Läufer importieren
|
||||
{$_('laeufer-importieren')}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
+2
-6
@@ -1,16 +1,12 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
// import AddUserModal from "./AddUserModal.svelte";
|
||||
import runners_empty from "./runners_empty.svg";
|
||||
// let modal_open = false;
|
||||
</script>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- <AddUserModal bind:modal_open /> -->
|
||||
+85
-51
@@ -1,10 +1,13 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { RunnerService,RunnerTeamService,
|
||||
RunnerOrganizationService, } from "@odit/lfk-client-js";
|
||||
import store from "../store";
|
||||
import {
|
||||
RunnerService,
|
||||
RunnerTeamService,
|
||||
RunnerOrganizationService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import store from "../../store";
|
||||
import RunnersEmptyState from "./RunnersEmptyState.svelte";
|
||||
import Select from 'svelte-select';
|
||||
import Select from "svelte-select";
|
||||
$: searchvalue = "";
|
||||
$: active_deletes = [];
|
||||
export let current_runners = [];
|
||||
@@ -13,17 +16,19 @@
|
||||
});
|
||||
$: selectedFilter_teams = null;
|
||||
$: selectedFilter = null;
|
||||
$: filter__teams = selectedFilter_teams||[];
|
||||
$: filter__orgs = selectedFilter||[];
|
||||
$:filterGroupIDs=filter__teams.concat(filter__orgs).map(i=>i.value)
|
||||
$: filter__teams = selectedFilter_teams || [];
|
||||
$: filter__orgs = selectedFilter || [];
|
||||
$: filterGroupIDs = filter__teams.concat(filter__orgs).map((i) => i.value);
|
||||
$: teams = [];
|
||||
$: orgs = [];
|
||||
$:mappedteams=teams.map(function(g){
|
||||
return {value:g.id,label:g.parentGroup.name+" > "+g.name}
|
||||
})
|
||||
$:selectgroups=(orgs.map(function(g){
|
||||
return {value:g.id,label:g.name}
|
||||
})).concat(mappedteams)
|
||||
$: mappedteams = teams.map(function (g) {
|
||||
return { value: g.id, label: g.parentGroup.name + " > " + g.name };
|
||||
});
|
||||
$: selectgroups = orgs
|
||||
.map(function (g) {
|
||||
return { value: g.id, label: g.name };
|
||||
})
|
||||
.concat(mappedteams);
|
||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||
teams = val;
|
||||
});
|
||||
@@ -31,10 +36,10 @@
|
||||
orgs = val;
|
||||
});
|
||||
function should_display_based_on_id(id) {
|
||||
if(searchvalue.toString().slice(-1)==="*"){
|
||||
return id.toString().startsWith(searchvalue.replace("*",""))
|
||||
if (searchvalue.toString().slice(-1) === "*") {
|
||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
||||
}
|
||||
return id.toString()===searchvalue;
|
||||
return id.toString() === searchvalue;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -43,7 +48,7 @@
|
||||
<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="font-bold">{$_('runners-are-being-loaded')}</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
@@ -57,10 +62,18 @@
|
||||
aria-label={$_('datatable.search')}
|
||||
class="gridjs-input gridjs-search-input mb-4" />
|
||||
<div class="block mb-1">
|
||||
<label for="country" class="text-sm font-medium text-gray-700">Filter by Organization/ Team</label>
|
||||
<Select on:select={(event)=>{
|
||||
selectedFilter=event.detail
|
||||
}} selectedValue={selectedFilter} placeholder="Filter by Organization/ Team" containerClasses="mt-1 py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" items={selectgroups} isMulti={true}></Select>
|
||||
<label
|
||||
for="country"
|
||||
class="text-sm font-medium text-gray-700">{$_('filter-by-organization-team')}</label>
|
||||
<Select
|
||||
on:select={(event) => {
|
||||
selectedFilter = event.detail;
|
||||
}}
|
||||
selectedValue={selectedFilter}
|
||||
placeholder={$_('filter-by-organization-team')}
|
||||
containerClasses="mt-1 py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
items={selectgroups}
|
||||
isMulti={true} />
|
||||
</div>
|
||||
<div
|
||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||
@@ -94,20 +107,34 @@
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
{#each current_runners as runner}
|
||||
{#if runner.firstname.toLowerCase().includes(searchvalue.toLowerCase())||runner.middlename.toLowerCase().includes(searchvalue.toLowerCase())||runner.lastname.toLowerCase().includes(searchvalue.toLowerCase())||should_display_based_on_id(runner.id)}
|
||||
{#if filterGroupIDs.includes(runner.group.id)||filterGroupIDs.includes(runner.group.parentGroup?.id)||filterGroupIDs.length===0}
|
||||
<tr data-rowid="user_{runner.id}" data-groupid={runner.group.id}>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{runner.firstname}
|
||||
{runner.middlename || ''}
|
||||
{runner.lastname}
|
||||
{#if runner.firstname
|
||||
.toLowerCase()
|
||||
.includes(
|
||||
searchvalue.toLowerCase()
|
||||
) || runner.middlename
|
||||
.toLowerCase()
|
||||
.includes(
|
||||
searchvalue.toLowerCase()
|
||||
) || runner.lastname
|
||||
.toLowerCase()
|
||||
.includes(
|
||||
searchvalue.toLowerCase()
|
||||
) || should_display_based_on_id(runner.id)}
|
||||
{#if filterGroupIDs.includes(runner.group.id) || filterGroupIDs.includes(runner.group.parentGroup?.id) || filterGroupIDs.length === 0}
|
||||
<tr
|
||||
data-rowid="user_{runner.id}"
|
||||
data-groupid={runner.group.id}>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{runner.firstname}
|
||||
{runner.middlename || ''}
|
||||
{runner.lastname}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{#if runner.email}
|
||||
<div class="text-sm text-gray-500">{runner.email}</div>
|
||||
@@ -115,6 +142,13 @@
|
||||
{#if runner.phone}
|
||||
<div class="text-sm text-gray-500">{runner.phone}</div>
|
||||
{/if}
|
||||
{#if runner.address.address1 !== null}
|
||||
{runner.address.address1}<br />
|
||||
{runner.address.address2 || ''}<br />
|
||||
{runner.address.postalcode}
|
||||
{runner.address.city}
|
||||
{runner.address.country}
|
||||
{/if}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{#if runner.group.responseType === 'RUNNERTEAM'}
|
||||
@@ -151,24 +185,24 @@
|
||||
}}
|
||||
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">
|
||||
<a
|
||||
href="./{runner.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">Edit</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[runner.id] = true;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
</td>
|
||||
{:else}
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<a
|
||||
href="./{runner.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[runner.id] = true;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import {
|
||||
RunnerOrganizationService,
|
||||
@@ -110,11 +110,11 @@
|
||||
</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 team
|
||||
{$_('create-a-new-team')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
Please provide the required information to add a new team.
|
||||
{$_('please-provide-the-required-information-to-add-a-new-team')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
@@ -137,7 +137,7 @@
|
||||
{#if !isTeamNameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
team name is required
|
||||
{$_('team-name-is-required')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
+8
-10
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { RunnerTeamService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
@@ -22,9 +22,7 @@
|
||||
}).showToast();
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
});
|
||||
.catch((err) => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -65,13 +63,13 @@
|
||||
</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">
|
||||
Attention!
|
||||
{$_('attention')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
Do you want to delete the team
|
||||
{delete_team.name}?<br />All associated runners will be
|
||||
deleted too!
|
||||
{$_('do-you-want-to-delete-the-team-delete_team-name', {
|
||||
values: { teamname: delete_team.name },
|
||||
})}<br />{$_('all-associated-runners-will-be-deleted-too')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,13 +80,13 @@
|
||||
on:click={deleteTeam}
|
||||
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">
|
||||
Confirm, delete team and associated runners.
|
||||
{$_('confirm-delete-team-and-associated-runners')}
|
||||
</button>
|
||||
<button
|
||||
on:click={cancelDelete}
|
||||
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, keep team
|
||||
{$_('cancel-keep-team')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,22 +1,24 @@
|
||||
<script>
|
||||
import {
|
||||
GroupContactService,
|
||||
RunnerOrganizationService,
|
||||
RunnerTeamService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import store from "../store";
|
||||
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
import store from "../../store";
|
||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
||||
export let params;
|
||||
let [teamdata, original, delete_team, orgs, modal_open] = [
|
||||
let [teamdata, original, delete_team, orgs, contacts, modal_open] = [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
[],
|
||||
[],
|
||||
false,
|
||||
];
|
||||
export let params;
|
||||
export let import_modal_open = false;
|
||||
$: delete_triggered = false;
|
||||
$: save_enabled = !data_changed;
|
||||
@@ -27,12 +29,20 @@
|
||||
params.teamid
|
||||
).then((value) => {
|
||||
data_loaded = true;
|
||||
if (value.contact) {
|
||||
if (value.contact !== "null") {
|
||||
value.contact = value.contact.id;
|
||||
}
|
||||
}
|
||||
teamdata = Object.assign(teamdata, value);
|
||||
original = Object.assign(original, value);
|
||||
});
|
||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
||||
orgs = val;
|
||||
});
|
||||
GroupContactService.groupContactControllerGetAll().then((val) => {
|
||||
contacts = val;
|
||||
});
|
||||
function deleteTeam() {
|
||||
RunnerTeamService.runnerTeamControllerRemove(original.id, false)
|
||||
.then((resp) => {
|
||||
@@ -55,7 +65,9 @@
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
teamdata.parentGroup = teamdata.parentGroup.id;
|
||||
RunnerTeamService.runnerTeamControllerPut(original.id, teamdata)
|
||||
let postdata = teamdata;
|
||||
postdata.contact = postdata.contact === "null" ? null : postdata.contact;
|
||||
RunnerTeamService.runnerTeamControllerPut(original.id, postdata)
|
||||
.then((resp) => {
|
||||
Object.assign(original, teamdata);
|
||||
original = teamdata;
|
||||
@@ -68,7 +80,6 @@
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -216,13 +227,19 @@
|
||||
<label
|
||||
for="contact"
|
||||
class="font-medium text-gray-700">{$_('contact')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('contact')}
|
||||
type="text"
|
||||
bind:value={teamdata.contact}
|
||||
<select
|
||||
name="contact"
|
||||
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" />
|
||||
bind:value={teamdata.contact}
|
||||
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">
|
||||
<option value="null">no contact</option>
|
||||
{#each contacts as c}
|
||||
<option value={c.id}>
|
||||
{c.firstname}
|
||||
{c.middlename || ''}
|
||||
{c.lastname}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<label for="org" class="font-medium text-gray-700">Parent Organization</label>
|
||||
@@ -1,11 +1,10 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import AddTeamModal from "./AddTeamModal.svelte";
|
||||
export let modal_open = false;
|
||||
import TeamsOverview from "./TeamsOverview.svelte";
|
||||
console.log(store.state.jwtinfo.userdetails.permissions);
|
||||
let current_teams=[];
|
||||
let current_teams = [];
|
||||
</script>
|
||||
|
||||
<section class="container p-5">
|
||||
@@ -18,11 +17,13 @@
|
||||
}}
|
||||
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 Team
|
||||
{$_('create-team')}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">everything is more fun together 🏃♂️🏃♀️🏃♂️</p>
|
||||
<p class="mb-8 text-lg text-gray-500">
|
||||
{$_('everything-is-more-fun-together')}
|
||||
</p>
|
||||
<TeamsOverview bind:current_teams />
|
||||
</section>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<img class="w-full h-44" src={team_empty} alt="" />
|
||||
<span class="font-bold">There are no teams added yet.</span><br />
|
||||
<span>Add your first team</span>
|
||||
<span class="font-bold">{$_('there-are-no-teams-added-yet')}</span><br />
|
||||
<span>{$_('add-your-first-team')}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
import Toastify from "toastify-js";
|
||||
import { RunnerTeamService } from "@odit/lfk-client-js";
|
||||
const teams_promise = RunnerTeamService.runnerTeamControllerGetAll();
|
||||
import { users as usersstore } from "../store.js";
|
||||
import store from "../store";
|
||||
import store, { users as usersstore } from "../../store.js";
|
||||
import TeamsEmptyState from "./TeamsEmptyState.svelte";
|
||||
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
||||
$: searchvalue = "";
|
||||
@@ -32,7 +31,7 @@
|
||||
<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">teams are being loaded...</p>
|
||||
<p class="font-bold">{$_('teams-are-being-loaded')}</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
@@ -53,7 +52,7 @@
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Name
|
||||
{$_('name')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
@@ -63,10 +62,10 @@
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Contact
|
||||
{$_('contact')}
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">Action</span>
|
||||
<span class="sr-only">{$_('action')}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -94,7 +93,7 @@
|
||||
<a
|
||||
href="../orgs/{t.parentGroup.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{t.parentGroup.name}</a>
|
||||
{:else}no organization specified{/if}
|
||||
{:else}{$_('no-organization-specified')}{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -104,8 +103,12 @@
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{#if t.contact}
|
||||
{JSON.stringify(t.contact)}
|
||||
{:else}no contact specified{/if}
|
||||
<a
|
||||
href="../contacts/{t.contact.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{t.contact.firstname}
|
||||
{t.contact.middlename || ''}
|
||||
{t.contact.lastname}</a>
|
||||
{:else}{$_('no-contact-specified')}{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,7 +129,7 @@
|
||||
.then((resp) => {
|
||||
current_teams = current_teams.filter((obj) => obj.id !== t.id);
|
||||
Toastify({
|
||||
text: 'Organization deleted',
|
||||
text: $_('organization-deleted'),
|
||||
duration: 500,
|
||||
backgroundColor:
|
||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
||||
@@ -138,22 +141,21 @@
|
||||
});
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
|
||||
Delete</button>
|
||||
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">
|
||||
<a
|
||||
href="./{t.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">Edit</a>
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('TEAM:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[t.id] = true;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</button>
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
File renamed without changes.
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { tracks as tracksstore } from "../store.js";
|
||||
import { tracks as tracksstore } from "../../store.js";
|
||||
import { TrackService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import "toastify-js/src/toastify.css";
|
||||
@@ -51,7 +51,6 @@
|
||||
track_min_duration = 0;
|
||||
tracklength = 0;
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: $_("track-added"),
|
||||
duration: 500,
|
||||
@@ -64,12 +63,9 @@
|
||||
storeval.push(result);
|
||||
tracksstore.set(storeval);
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
})
|
||||
.catch((err) => {})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
//
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
@@ -142,7 +138,7 @@
|
||||
{#if isTracknameValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Track name must not be empty
|
||||
{$_('track-name-must-not-be-empty')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -167,7 +163,7 @@
|
||||
{#if isTracklengthValid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
Track length must be greater than 0
|
||||
{$_('track-length-must-be-greater-than-0')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -192,7 +188,7 @@
|
||||
{#if !trackMintimevalid}
|
||||
<span
|
||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
||||
minimum lap time must be a positive number or 0
|
||||
{$_('minimum-lap-time-must-be-a-positive-number-or-0')}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -215,7 +211,7 @@
|
||||
}}
|
||||
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
|
||||
{$_('cancel')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -4,9 +4,9 @@
|
||||
import TracksEmptyState from "./TracksEmptyState.svelte";
|
||||
import { TrackService } from "@odit/lfk-client-js";
|
||||
const tracks_promise = TrackService.trackControllerGetAll();
|
||||
import { getlang } from "./datatable_i18n";
|
||||
import { getlang } from "../base/datatable_i18n";
|
||||
import { Grid, html } from "gridjs";
|
||||
import { tracks as tracksstore } from "../store.js";
|
||||
import { tracks as tracksstore } from "../../store.js";
|
||||
$: trackscache = [];
|
||||
$: blocked = [];
|
||||
let table;
|
||||
@@ -61,9 +61,7 @@
|
||||
elem.childNodes[1].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[1].childNodes[0].value}</td>`;
|
||||
elem.childNodes[2].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[2].childNodes[0].value}</td>`;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
.catch((err) => {});
|
||||
}
|
||||
};
|
||||
window.track__delete_handler = () => {
|
||||
@@ -92,9 +90,7 @@
|
||||
tracksstore.set(newStoreVal);
|
||||
renderdatatable();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
.catch((err) => {});
|
||||
};
|
||||
window.track__edit_handler = () => {
|
||||
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
|
||||
@@ -124,16 +120,30 @@
|
||||
track.minimumLapTime || 0,
|
||||
html(`
|
||||
<div class="hidden" data-id="triggered_table_actions_${track.id}">
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_save()">Save</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_cancel()">Cancel</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__edit_save()">${$_("save")}</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__edit_cancel()">${$_("cancel")}</button>
|
||||
</div>
|
||||
<div data-id="default_table_actions_${track.id}">
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__edit_handler()">Edit</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_handler()">Delete</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__edit_handler()">${$_("edit")}</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__delete_handler()">${$_("delete")}</button>
|
||||
</div>
|
||||
<div class="hidden" data-id="deleteconfirmation_table_actions_${track.id}">
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_cancel()">Cancel</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${track.id}" onclick="track__delete_confirm()">Confirm</button>
|
||||
<div class="hidden" data-id="deleteconfirmation_table_actions_${
|
||||
track.id
|
||||
}">
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__delete_cancel()">${$_("cancel")}</button>
|
||||
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
|
||||
track.id
|
||||
}" onclick="track__delete_confirm()">${$_("confirm")}</button>
|
||||
</div>
|
||||
`),
|
||||
]);
|
||||
File renamed without changes.
@@ -14,11 +14,11 @@
|
||||
}}
|
||||
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 Track
|
||||
{$_('create-track')}
|
||||
</button>
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">
|
||||
configure the tracks & minimum lap times
|
||||
{$_('configure-the-tracks-and-minimum-lap-times')}
|
||||
</p>
|
||||
<Tracks />
|
||||
</section>
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { clickOutside } from "../base/outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { UserService } from "@odit/lfk-client-js";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
@@ -47,7 +47,7 @@
|
||||
if (processed_last_submit === true) {
|
||||
processed_last_submit = false;
|
||||
const toast = Toastify({
|
||||
text: "User is being added...",
|
||||
text: $_("user-is-being-added"),
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
UserService.userControllerPost({
|
||||
@@ -67,19 +67,16 @@
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
text: "User added",
|
||||
text: $_("user-added"),
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
current_users.push(result);
|
||||
current_users = current_users;
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
})
|
||||
.catch((err) => {})
|
||||
.finally(() => {
|
||||
processed_last_submit = true;
|
||||
//
|
||||
toast.hideToast();
|
||||
});
|
||||
}
|
||||
@@ -125,11 +122,11 @@
|
||||
</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 User
|
||||
{$_('create-a-new-user')}
|
||||
</h3>
|
||||
<div class="mt-2 mb-6">
|
||||
<p class="text-sm text-gray-500">
|
||||
Please provide the required information to add a new user.
|
||||
{$_('please-provide-the-required-information-to-add-a-new-user')}
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
@@ -1,11 +1,11 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import lodashIsEqual from "lodash.isequal";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import { UserService, UserGroupService } from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
export let params;
|
||||
const user_promise = UserService.userControllerGetOne(params.userid);
|
||||
let data_loaded = false;
|
||||
+14
-9
@@ -6,7 +6,7 @@
|
||||
CreatePermission,
|
||||
} from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
import PromiseError from "../base/PromiseError.svelte";
|
||||
export let params;
|
||||
let [
|
||||
grantedPermissions_initial,
|
||||
@@ -51,7 +51,7 @@
|
||||
);
|
||||
});
|
||||
Toastify({
|
||||
text: "Permissions updated!",
|
||||
text: $_("permissions-updated"),
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
@@ -134,14 +134,14 @@
|
||||
<polyline points="12 5 19 12 12 19" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="mr-2">Permissions</span>
|
||||
<span class="mr-2">{$_('permissions')}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8 text-3xl font-extrabold">
|
||||
Permissions:
|
||||
{$_('permissions')}:
|
||||
{original_data.firstname}
|
||||
{original_data.middlename || ''}
|
||||
{original_data.lastname}
|
||||
@@ -156,16 +156,21 @@
|
||||
{:else}
|
||||
<button
|
||||
type="button"
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm">Applying
|
||||
Changes</button>
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('applying-changes')}</button>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="flex flex-wrap -mx-1 overflow-hidden">
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">verfügbare</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">erteilte</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">geerbte</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">
|
||||
{$_('verfuegbare')}
|
||||
</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">
|
||||
{$_('erteilte')}
|
||||
</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/3">
|
||||
{$_('geerbte')}
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="flex flex-wrap -mx-1 overflow-hidden">
|
||||
@@ -1,10 +1,9 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../store";
|
||||
import store from "../../store";
|
||||
import AddUserModal from "./AddUserModal.svelte";
|
||||
export let modal_open = false;
|
||||
import UsersOverview from "./UsersOverview.svelte";
|
||||
console.log(store.state.jwtinfo.userdetails.permissions);
|
||||
let current_users=[];
|
||||
</script>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<img class="w-full h-44" src={users_empty} alt="" />
|
||||
<span class="font-bold">There are no users added yet.</span><br />
|
||||
<span>Add your first user</span>
|
||||
<span class="font-bold">{$_('there-are-no-users-added-yet')}</span><br />
|
||||
<span>{$_('add-your-first-user')}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
import { _ } from "svelte-i18n";
|
||||
import { UserService } from "@odit/lfk-client-js";
|
||||
const users_promise = UserService.userControllerGetAll();
|
||||
import { users as usersstore } from "../store.js";
|
||||
import store from "../store";
|
||||
import store, { users as usersstore } from "../../store.js";
|
||||
import UsersEmptyState from "./UsersEmptyState.svelte";
|
||||
$: searchvalue = "";
|
||||
$: active_deletes = [];
|
||||
export let current_users=[];
|
||||
export let current_users = [];
|
||||
$: advanced_search = false;
|
||||
usersstore.subscribe((val) => {
|
||||
current_users=val;
|
||||
current_users = val;
|
||||
});
|
||||
users_promise.then((data) => {
|
||||
usersstore.set(data);
|
||||
@@ -32,12 +31,12 @@
|
||||
<!-- {#if advanced_search}
|
||||
advanced search
|
||||
{:else} -->
|
||||
<input
|
||||
type="search"
|
||||
bind:value={searchvalue}
|
||||
placeholder={$_('datatable.search')}
|
||||
aria-label={$_('datatable.search')}
|
||||
class="gridjs-input gridjs-search-input mb-4" />
|
||||
<input
|
||||
type="search"
|
||||
bind:value={searchvalue}
|
||||
placeholder={$_('datatable.search')}
|
||||
aria-label={$_('datatable.search')}
|
||||
class="gridjs-input gridjs-search-input mb-4" />
|
||||
<!-- {/if} -->
|
||||
<!-- <button
|
||||
on:click={() => {
|
||||
@@ -57,20 +56,20 @@
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Name
|
||||
{$_('name')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Status
|
||||
{$_('status')}
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||
Groups
|
||||
{$_('groups')}
|
||||
</th>
|
||||
<th scope="col" class="relative px-6 py-3">
|
||||
<span class="sr-only">Action</span>
|
||||
<span class="sr-only">{$_('action')}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -92,8 +91,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{u.firstname}
|
||||
{u.middlename || ''}
|
||||
{u.lastname}
|
||||
@@ -107,10 +105,10 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
{#if u.enabled}
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Active</span>
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('active')}</span>
|
||||
{:else}
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('inactive')}</span>
|
||||
{/if}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
@@ -128,35 +126,31 @@
|
||||
active_deletes[u.id] = false;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">Cancel
|
||||
Delete</button>
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
UserService.userControllerRemove(u.id, true)
|
||||
.then((resp) => {
|
||||
current_users=current_users.filter(obj=>obj.id!==u.id);
|
||||
current_users = current_users.filter((obj) => obj.id !== u.id);
|
||||
})
|
||||
.catch((err) => {
|
||||
// error deleting user
|
||||
});
|
||||
.catch((err) => {});
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
|
||||
Delete</button>
|
||||
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">
|
||||
<a
|
||||
href="./{u.id}"
|
||||
class="text-indigo-600 hover:text-indigo-900">Edit</a>
|
||||
class="text-indigo-600 hover:text-indigo-900">{$_('edit')}</a>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[u.id] = true;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</button>
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
File renamed without changes.
Reference in new issue
Block a user