feature/50-contact-management #67

Merged
philipp merged 20 commits from feature/50-contact-management into dev 2021-02-18 15:13:37 +00:00
6 changed files with 230 additions and 374 deletions
Showing only changes of commit c1251d3332 - Show all commits

View File

@ -57,10 +57,9 @@
$: 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...",
text: $_("contact-is-being-updated"),
duration: 2500,
}).showToast();
editable.address.country = "DE";
@ -78,7 +77,7 @@
original_data = editable;
Object.assign(original_data, editable);
Toastify({
text: "Updated contact!",
text: $_("updated-contact"),
duration: 2500,
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast();
@ -97,7 +96,7 @@
</script>
{#await promise}
Loading contact details...
{$_('loading-contact-details')}
{:then}
<section class="container p-5 select-none">
<div class="flex flex-row mb-4">
@ -163,8 +162,7 @@
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>
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}
@ -268,7 +266,7 @@
{#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...
{$_('valid-international-phone-number-is-required')}
</span>
{/if}
</div>
@ -302,14 +300,16 @@
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>
<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>
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
<input
autocomplete="off"
placeholder="Address"
@ -323,17 +323,17 @@
{#if !isAddress1Valid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Address is required
{$_('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>
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
<input
autocomplete="off"
placeholder="Apartment, suite, etc."
placeholder={$_('apartment-suite-etc')}
bind:value={editable.address.address2}
type="text"
name="address2"
@ -342,10 +342,10 @@
<div class="col-span-6">
<label
for="zipcode"
class="block text-sm font-medium text-gray-700">ZIP/ postal code</label>
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
<input
autocomplete="off"
placeholder="ZIP/ postal code"
placeholder={$_('zip-postal-code')}
class:border-red-500={!iszipcodevalid}
class:focus:border-red-500={!iszipcodevalid}
class:focus:ring-red-500={!iszipcodevalid}
@ -356,17 +356,17 @@
{#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
{$_('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>
class="block text-sm font-medium text-gray-700">{$_('city')}</label>
<input
autocomplete="off"
placeholder="City"
placeholder={$_('city')}
class:border-red-500={!iscityvalid}
class:focus:border-red-500={!iscityvalid}
class:focus:ring-red-500={!iscityvalid}
@ -377,7 +377,7 @@
{#if !iscityvalid}
<span
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
Valid city is required
{$_('valid-city-is-required')}
</span>
{/if}
</div>

View File

@ -1,164 +0,0 @@
<script>
import { t, _ } from "svelte-i18n";
import Toastify from "toastify-js";
import { GroupContactService } from "@odit/lfk-client-js";
const promise = GroupContactService.groupContactControllerGetAll();
import { users as usersstore } from "../store.js";
import store from "../store";
import TeamsEmptyState from "./TeamsEmptyState.svelte";
$: searchvalue = "";
$: active_deletes = [];
export let contacts = [];
usersstore.subscribe((val) => {
contacts = val;
});
promise.then((data) => {
usersstore.set(data);
});
</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">teams are being loaded...</p>
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
</div>
{:then}
{#if contacts.length === 0}
<TeamsEmptyState />
{: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">
{$_('organization')}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Contact
</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 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.name}
</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.parentGroup}
<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 groups{/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.contact}
{JSON.stringify(t.contact)}
{:else}no contact specified{/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, true)
.then((resp) => {
contacts = contacts.filter((obj) => obj.id !== t.id);
Toastify({
text: 'Contact deleted',
duration: 500,
backgroundColor:
'linear-gradient(to right, #00b09b, #96c93d)',
}).showToast();
})
.catch((err) => {
//
});
}}
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}

View File

@ -17,7 +17,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">
Create Contact
{$_('create-a-new-contact')}
</button>
{/if}
</span>

View File

@ -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 contacts added yet.</span><br />
<span>Add your first contact</span>
<span class="font-bold">{$_('there-are-no-contacts-added-yet')}</span><br />
<span>{$_('add-your-first-contact')}</span>
</p>
</div>

View File

@ -93,7 +93,9 @@
{g.name}</a>
{/if}
{/each}
{:else}no groups{/if}
{:else}
{$_('contact-is-not-a-member-in-any-group')}
{/if}
</div>
</div>
</div>
@ -121,8 +123,7 @@
active_deletes[t.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={() => {
GroupContactService.groupContactControllerRemove(t.id, false).then(
@ -140,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}

View File

@ -3,24 +3,36 @@
"404title": "Error 404",
"about": "About",
"action": "Action",
"add-your-first-contact": "Add your first contact",
"add-your-first-track": "Add your first track",
"address": "Address",
"address-is-required": "Address is required",
"apartment-suite-etc": "Apartment, suite, etc.",
"application_name": "Lauf für Kaya! - Admin",
"attention": "Attention!",
"author": "Author",
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Please confirm these runners for import",
"browse": "Browse",
"by": "by",
"cancel": "Cancel",
"cancel-delete": "Cancel Delete",
"cancel-keep-team": "Cancel, keep team",
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
"changelog": "Changelog",
"city": "City",
"close": "Close",
"confirm-delete": "Confirm Delete",
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
"confirm-deletion": "Confirm Deletion",
"contact": "Contact",
"contact-information": "Contact Information",
"contact-is-being-updated": "Contact is being updated...",
"contact-is-not-a-member-in-any-group": "Contact is not a member in any group",
"contacts": "Contacts",
"count_organizations": "# Organizations",
"count_teams": "# Teams",
"create": "Create",
"create-a-new-contact": "Create a new contact",
"create-a-new-runner": "Create a new Runner",
"create-a-new-track": "Create a new Track",
"create-organization": "Create Organization",
@ -49,6 +61,7 @@
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
},
"delete": "Delete",
"delete-contact": "Delete Contact",
"delete-organization": "Delete Organization",
"delete-runner": "Delete Runner",
"delete-team": "Delete Team",
@ -60,6 +73,7 @@
"dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌",
"drag-and-drop-your-files-or": "Drag & Drop your files or",
"e-mail-adress": "E-Mail Adress",
"edit": "Edit",
"edit-permissions": "edit permissions",
"email_address_or_username": "Email / username",
"error_on_login": "Error on login",
@ -106,6 +120,7 @@
"lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.",
"license": "License",
"licenses-are-being-loaded": "Licenses are being loaded...",
"loading-contact-details": "Loading contact details...",
"loading-runners": "loading runners...",
"log_in": "Log in",
"log_in_to_your_account": "Log in to your account",
@ -157,7 +172,9 @@
"team": "Team",
"team-name": "Team name",
"teams": "Teams",
"teams-are-being-loaded": "Teams are being loaded...",
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
"there-are-no-contacts-added-yet": "There are no contacts added yet.",
"this-might-take-a-moment": "This might take a moment 👀",
"total-distance": "total distance",
"total-donations": "total donations",
@ -168,15 +185,18 @@
"track-length-in-m": "Track Length in m",
"track-name": "Track name",
"tracks": "Tracks",
"updated-contact": "Updated contact!",
"updating-runner": "Updating runner...",
"updating-user": "updating user...",
"user-updated": "User updated",
"username": "Username",
"users": "Users",
"valid-city-is-required": "Valid city is required",
"valid-email-is-required": "valid email is required",
"valid-international-phone-number-is-required": "valid international phone number is required...",
"valid-zipcode-postal-code-is-required": "Valid zipcode/ postal code is required",
"welcome_wavinghand": "Welcome 👋",
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
"your_profile": "Your Profile",
"contacts": "Contacts",
"create-a-new-contact": "Create a new contact"
"zip-postal-code": "ZIP/ postal code"
}