Compare commits

..

32 Commits

Author SHA1 Message Date
77690702c0 🚀RELEASE v0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 21:17:35 +01:00
e0093480d9 Merge branch 'feature/12-user-management' into dev 2021-01-11 21:17:12 +01:00
c7679b7a67 [tmp] - disable darkmode + re-enable sw 2021-01-11 21:17:05 +01:00
e6ac34bde8 🐞 [tmp] - nginx.conf - disable .js file caching
Some checks failed
continuous-integration/drone/push Build was killed
2021-01-11 21:10:40 +01:00
8c4b595c30 Merge branch 'dev' into feature/12-user-management 2021-01-11 21:08:44 +01:00
be629e5c6b 🕕 set manual refresh time to 2min
Some checks failed
continuous-integration/drone/push Build was killed
2021-01-11 21:08:39 +01:00
63569684a3 ℹ update jwtinfo store on token refresh 2021-01-11 21:08:14 +01:00
5937a0d7ce 🔒 added rendering based on permission level
ref #12
2021-01-11 21:07:30 +01:00
4512272c1c UserDetail - delete
ref #12
2021-01-11 21:06:47 +01:00
ce1f3842e0 🖊 UserDetail - reactivity on edit + update functionality
ref #12
2021-01-11 20:41:57 +01:00
ee01c3a059 🚀RELEASE v0.1.6
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 18:19:45 +01:00
81c1537bad 🔒 UserDetail - added basic layout for permission change
ref #12
2021-01-10 18:14:11 +01:00
98ecfab032 UserDetail multiselect layout for groups
ref #12
2021-01-10 18:02:36 +01:00
b948b8c1a4 UserDetail - placeholder for permission picker 🔒
ref #12
2021-01-10 17:55:13 +01:00
f856c6ae37 📧 UserDetail - email input
ref #12
2021-01-10 17:54:50 +01:00
2dd2580530 Merge branch 'dev' into feature/12-user-management 2021-01-10 17:34:12 +01:00
330755c63e 🚀RELEASE v0.1.5
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 17:18:55 +01:00
9cf0174b41 Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev
close #30
2021-01-10 17:18:33 +01:00
16f572480a add versionbuilder script to release hook
ref #30
2021-01-10 17:18:16 +01:00
b8a9e4f272 📅 dynamic copyright year in Footer component
ref #30
2021-01-10 17:17:07 +01:00
c089bb3929 ⤵ load dynamic build info in Footer component
ref #30
2021-01-10 17:16:51 +01:00
3caa1fc277 🔨 sample build of index.html with versionbuilder script
ref #30
2021-01-10 17:16:07 +01:00
43b406592e 👀 improved Footer layout + display on Login component
ref #30
2021-01-10 17:15:46 +01:00
1dd6674faa added versionbuilder.js script
ref #30
2021-01-10 17:15:01 +01:00
4674b52717 🚀RELEASE v0.1.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-10 15:30:59 +01:00
cd5831251a Merge commit '45ec97066f425ac2ac66914be649cbd5a1038e10' into dev
close #20
2021-01-10 15:30:42 +01:00
45ec97066f 🌎 add remaining translation keys for filepond
ref #20
2021-01-10 15:30:13 +01:00
b08c0f145a add basic i18n logic to filepond
ref #20
2021-01-10 15:26:52 +01:00
f0c100aee4 UsersOverview - user delete
ref #12
2021-01-10 15:16:02 +01:00
0e31ba212f About - change license modal icon to "legal"
Some checks failed
continuous-integration/drone/push Build was killed
2021-01-10 15:04:05 +01:00
692c906cd2 🌎 About - i18n 2021-01-10 15:03:32 +01:00
4f3837ac45 new license file version [CI SKIP] 2021-01-10 13:47:30 +00:00
18 changed files with 488 additions and 186 deletions

View File

@@ -2,8 +2,56 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.2.0](https://git.odit.services/lfk/frontend/compare/0.1.6...0.2.0)
- 🔒 added rendering based on permission level [`5937a0d`](https://git.odit.services/lfk/frontend/commit/5937a0d7ce970d38ddb0e4c6a02d11f8c8b53e9b)
- ❌ UserDetail - delete [`4512272`](https://git.odit.services/lfk/frontend/commit/4512272c1c2a5c861d8ac4c9908244df125dc3d9)
- 🖊 UserDetail - reactivity on edit + update functionality [`ce1f384`](https://git.odit.services/lfk/frontend/commit/ce1f3842e0f581d9e94ea6079cf223d945f7465d)
- [tmp] - disable darkmode + re-enable sw [`c7679b7`](https://git.odit.services/lfk/frontend/commit/c7679b7a67b362a7fbf796f612892bdfac50731c)
- 🕕 set manual refresh time to 2min [`be629e5`](https://git.odit.services/lfk/frontend/commit/be629e5c6b076bf9a28dcc953e97478d244d8413)
- 🐞 [tmp] - nginx.conf - disable .js file caching [`e6ac34b`](https://git.odit.services/lfk/frontend/commit/e6ac34bde8d288a45e83fc6723a2bbe952f2622a)
- update jwtinfo store on token refresh [`6356968`](https://git.odit.services/lfk/frontend/commit/63569684a392bf0c24c9c2efd7945114d1a230a5)
#### [0.1.6](https://git.odit.services/lfk/frontend/compare/0.1.5...0.1.6)
> 10 January 2021
- ✨ UsersOverview - user delete [`f0c100a`](https://git.odit.services/lfk/frontend/commit/f0c100aee47d6a5aeb0995db79b268f33bf316e9)
- 🔒 UserDetail - added basic layout for permission change [`81c1537`](https://git.odit.services/lfk/frontend/commit/81c1537bada2c87127385d9110d48459cd1b505f)
- 🚀RELEASE v0.1.6 [`ee01c3a`](https://git.odit.services/lfk/frontend/commit/ee01c3a059c435add68938657955cbd2c5851c50)
- 📧 UserDetail - email input [`f856c6a`](https://git.odit.services/lfk/frontend/commit/f856c6ae3792c93aee148339d89e3978db6e9293)
- ✨ UserDetail multiselect layout for groups [`98ecfab`](https://git.odit.services/lfk/frontend/commit/98ecfab0325e35c5418775f7162049b56e5f332f)
- UserDetail - placeholder for permission picker 🔒 [`b948b8c`](https://git.odit.services/lfk/frontend/commit/b948b8c1a48e5b4bc6a083139d26100ef4499970)
#### [0.1.5](https://git.odit.services/lfk/frontend/compare/0.1.4...0.1.5)
> 10 January 2021
- Merge commit '16f572480ad55425890061f9dad65fe85f2f39ad' into dev [`#30`](https://git.odit.services/lfk/frontend/issues/30)
- 🚀RELEASE v0.1.5 [`330755c`](https://git.odit.services/lfk/frontend/commit/330755c63e3405533a5da79c84ef4f379eb43e1c)
- ⤵ load dynamic build info in Footer component [`c089bb3`](https://git.odit.services/lfk/frontend/commit/c089bb39298fb1067093c2fa81101130c214947c)
- 📅 dynamic copyright year in Footer component [`b8a9e4f`](https://git.odit.services/lfk/frontend/commit/b8a9e4f272f925999b9a032dd009f7498acbfae0)
- 👀 improved Footer layout + display on Login component [`43b4065`](https://git.odit.services/lfk/frontend/commit/43b406592ebe115cea04a8dbf36874c0a5bdd7e9)
- ✨ added versionbuilder.js script [`1dd6674`](https://git.odit.services/lfk/frontend/commit/1dd6674faad686c0048a62b4cd25ab21b5c8b04f)
- ⚡ add versionbuilder script to release hook [`16f5724`](https://git.odit.services/lfk/frontend/commit/16f572480ad55425890061f9dad65fe85f2f39ad)
- 🔨 sample build of index.html with versionbuilder script [`3caa1fc`](https://git.odit.services/lfk/frontend/commit/3caa1fc277b99ee767c1e1fc4a28fd247d98e659)
#### [0.1.4](https://git.odit.services/lfk/frontend/compare/0.1.3...0.1.4)
> 10 January 2021
- Merge commit '45ec97066f425ac2ac66914be649cbd5a1038e10' into dev [`#20`](https://git.odit.services/lfk/frontend/issues/20)
- 🌎 add remaining translation keys for filepond [`45ec970`](https://git.odit.services/lfk/frontend/commit/45ec97066f425ac2ac66914be649cbd5a1038e10)
- add basic i18n logic to filepond [`b08c0f1`](https://git.odit.services/lfk/frontend/commit/b08c0f145a13d295b2a51c7a6da76faceb80a90c)
- 🚀RELEASE v0.1.4 [`4674b52`](https://git.odit.services/lfk/frontend/commit/4674b52717e388122e113553b8a136c649ce030c)
- 🌎 About - i18n [`692c906`](https://git.odit.services/lfk/frontend/commit/692c906cd26bdb7f7d730b90734d23748e0ab451)
- ✨ About - change license modal icon to "legal" [`0e31ba2`](https://git.odit.services/lfk/frontend/commit/0e31ba212f99d90b133bc242e5b4d163aa99b93b)
- new license file version [CI SKIP] [`4f3837a`](https://git.odit.services/lfk/frontend/commit/4f3837ac45a5df9a7476fd68ec9c069dc6b128cd)
#### [0.1.3](https://git.odit.services/lfk/frontend/compare/0.1.2...0.1.3) #### [0.1.3](https://git.odit.services/lfk/frontend/compare/0.1.2...0.1.3)
> 10 January 2021
- 🌎 improved i18n for AddUserModal and UserDetail [`1c356a4`](https://git.odit.services/lfk/frontend/commit/1c356a41f54a954afaa69ed524f62c1676f7bbee) - 🌎 improved i18n for AddUserModal and UserDetail [`1c356a4`](https://git.odit.services/lfk/frontend/commit/1c356a41f54a954afaa69ed524f62c1676f7bbee)
- 🧹 simplified UsersOverview table [`e1d5d54`](https://git.odit.services/lfk/frontend/commit/e1d5d54cfb1fb20e56f0e971e2cfd196e9a913ac) - 🧹 simplified UsersOverview table [`e1d5d54`](https://git.odit.services/lfk/frontend/commit/e1d5d54cfb1fb20e56f0e971e2cfd196e9a913ac)
- 🌎 added i18n for UsersOverview [`3754f09`](https://git.odit.services/lfk/frontend/commit/3754f09b2f395a82ff8c3a9c655ab8a782e7eb71) - 🌎 added i18n for UsersOverview [`3754f09`](https://git.odit.services/lfk/frontend/commit/3754f09b2f395a82ff8c3a9c655ab8a782e7eb71)
@@ -11,6 +59,7 @@ All notable changes to this project will be documented in this file. Dates are d
- AddUserModal - data validation [`264e0d7`](https://git.odit.services/lfk/frontend/commit/264e0d7ed98c5000da543af154d6e36a6b956e4a) - AddUserModal - data validation [`264e0d7`](https://git.odit.services/lfk/frontend/commit/264e0d7ed98c5000da543af154d6e36a6b956e4a)
- ✨ sample layout for advanced search [`5ec1dfa`](https://git.odit.services/lfk/frontend/commit/5ec1dfa8b0da4619f14e73794b9a9e22872aa330) - ✨ sample layout for advanced search [`5ec1dfa`](https://git.odit.services/lfk/frontend/commit/5ec1dfa8b0da4619f14e73794b9a9e22872aa330)
- userdetail - dynamic buttons [`ded3198`](https://git.odit.services/lfk/frontend/commit/ded31980bfbf9f09afa2818bdcc8cc3e40748441) - userdetail - dynamic buttons [`ded3198`](https://git.odit.services/lfk/frontend/commit/ded31980bfbf9f09afa2818bdcc8cc3e40748441)
- 🚀RELEASE v0.1.3 [`ccb5125`](https://git.odit.services/lfk/frontend/commit/ccb5125a48486ef55709419eccd7d9e912a1e64c)
- 🔍 UsersOverview table - basic fuzzy search [`b9e0be4`](https://git.odit.services/lfk/frontend/commit/b9e0be448398d087005e220d08e34461490be14e) - 🔍 UsersOverview table - basic fuzzy search [`b9e0be4`](https://git.odit.services/lfk/frontend/commit/b9e0be448398d087005e220d08e34461490be14e)
#### [0.1.2](https://git.odit.services/lfk/frontend/compare/0.1.2-1...0.1.2) #### [0.1.2](https://git.odit.services/lfk/frontend/compare/0.1.2-1...0.1.2)

View File

@@ -9,7 +9,7 @@ http {
location / { location / {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
} }
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { location ~* \.(?:ico|css|gif|jpe?g|png)$ {
expires 1y; expires 1y;
add_header Pragma public; add_header Pragma public;
add_header Cache-Control "public"; add_header Cache-Control "public";

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-frontend", "name": "@odit/lfk-frontend",
"version": "0.1.3", "version": "0.2.0",
"scripts": { "scripts": {
"i18n-order": "node order.js", "i18n-order": "node order.js",
"dev": "snowpack dev", "dev": "snowpack dev",
@@ -51,7 +51,7 @@
"publish": false "publish": false
}, },
"hooks": { "hooks": {
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md" "after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add public/index.html"
} }
} }
} }

View File

@@ -13,6 +13,7 @@
</head> </head>
<body> <body>
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.2.0-RELEASE_INFO</span>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/env.js"></script> <script src="/env.js"></script>
<script defer type="module" src="/_dist_/index.js"></script> <script defer type="module" src="/_dist_/index.js"></script>

File diff suppressed because one or more lines are too long

View File

@@ -49,7 +49,7 @@
OpenAPI.BASE = config.baseurl; OpenAPI.BASE = config.baseurl;
import { register as registerSW } from "./swmodule"; import { register as registerSW } from "./swmodule";
store.init(); store.init();
// registerSW(); registerSW();
</script> </script>
<Route> <Route>

View File

@@ -50,14 +50,14 @@
<div <div
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"> class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
<svg <svg
class="h-6 w-6 text-blue-600"
fill="none"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 640 512"><path
fill="currentColor" fill="currentColor"
d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z" /></svg> class="h-6 w-6 text-blue-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="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z" /></svg>
</div> </div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg leading-6 font-medium"> <h3 class="text-lg leading-6 font-medium">
@@ -79,7 +79,7 @@
}} }}
type="button" 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"> 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">
Close {$_('close')}
</button> </button>
</div> </div>
</div> </div>
@@ -112,13 +112,12 @@
<h2 class="text-4xl font-display font-semibold md:text-5xl"> <h2 class="text-4xl font-display font-semibold md:text-5xl">
{$_('credits')} {$_('credits')}
</h2> </h2>
<div <div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
<p class="text-center">{$_('oss_credit_description')}</p> <p class="text-center">{$_('oss_credit_description')}</p>
</div> </div>
<div class="w-screen leading-8 pl-5 mt-5"> <div class="w-screen leading-8 pl-5 mt-5">
{#await license_promise} {#await license_promise}
<p class="text-center w-full">Licenses are being loaded...</p> <p class="text-center w-full">{$_('licenses-are-being-loaded')}</p>
{:then} {:then}
<table> <table>
<thead> <thead>
@@ -164,9 +163,7 @@
</div> </div>
{/await} {/await}
</div> </div>
<h2 class="text-4xl font-display font-semibold md:text-5xl"> <h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2>
Fragen
</h2>
<div class="mt-6 border-t-2 border-gray-100 pt-10"> <div class="mt-6 border-t-2 border-gray-100 pt-10">
<dl class="md:grid md:grid-cols-2 md:gap-8"> <dl class="md:grid md:grid-cols-2 md:gap-8">
<div> <div>

View File

@@ -2,7 +2,7 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { clickOutside } from "./outsideclick"; import { clickOutside } from "./outsideclick";
import { focusTrap } from "svelte-focus-trap"; import { focusTrap } from "svelte-focus-trap";
import { tracks as tracksstore } from "../store.js"; import { tracks as usersstore } from "../store.js";
import { UserService } from "@odit/lfk-client-js"; import { UserService } from "@odit/lfk-client-js";
import isEmail from "validator/es/lib/isEmail"; import isEmail from "validator/es/lib/isEmail";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
@@ -68,11 +68,11 @@
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)", backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
}).showToast(); }).showToast();
let storeval = []; let storeval = [];
tracksstore.subscribe((val) => { usersstore.subscribe((val) => {
storeval = val; storeval = val;
}); });
storeval.push(result); storeval.push(result);
tracksstore.set(storeval); usersstore.set(storeval);
}) })
.catch((err) => { .catch((err) => {
// //

View File

@@ -1,6 +1,7 @@
<script> <script>
import "filepond/dist/filepond.css"; import "filepond/dist/filepond.css";
import FilePond from "svelte-filepond"; import FilePond from "svelte-filepond";
import { _ } from "svelte-i18n";
let pond; let pond;
// pond.getFiles() will return the active files // pond.getFiles() will return the active files
// the name to use for the internal file input // the name to use for the internal file input
@@ -11,12 +12,60 @@
function handleAddFile(err, fileItem) { function handleAddFile(err, fileItem) {
// console.log("A file has been added", 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> </script>
<div class="app"> <div class="app">
<FilePond <FilePond
bind:this={pond} bind:this={pond}
{name} {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" server="/api"
allowMultiple={false} allowMultiple={false}
credits={false} credits={false}

View File

@@ -1,15 +1,35 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
$: releaseinfo = "";
setTimeout(() => {
releaseinfo = document
.getElementById("buildinfo")
.textContent.replace("RELEASE_INFO-", "")
.replace("-RELEASE_INFO", "");
}, 1500);
const year = new Date().getFullYear();
</script> </script>
<footer class="container"> <footer class="p-5 w-full">
<hr class="mt-2 mb-4 border-b-1 border-gray-300" />
<p class="text-sm text-gray-500 mt-4"> <p class="text-sm text-gray-500 mt-4">
Lauf für Kaya! Läufersystem - Copyright © 2020 + proudly powered by Lauf für Kaya! Läufersystem - Copyright ©
{year}
+ proudly powered by
<a <a
class="underline" class="underline"
href="https://odit.services" href="https://odit.services"
rel="noopener,noreferrer" rel="noopener,noreferrer"
target="_blank">ODIT.Services</a> target="_blank">ODIT.Services</a>
</p> </p>
<p class="text-sm text-gray-500 mt-4">
<a
class="underline"
target="_blank"
rel="noopener, noreferrer"
href="https://git.odit.services/lfk/frontend/">LfK!Frontend</a>@<a
class="underline"
target="_blank"
rel="noopener, noreferrer"
href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a>
</p>
</footer> </footer>

View File

@@ -4,6 +4,7 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
store.init(); store.init();
import { OpenAPI, AuthService } from "@odit/lfk-client-js"; import { OpenAPI, AuthService } from "@odit/lfk-client-js";
import Footer from "./Footer.svelte";
import Toastify from "toastify-js"; import Toastify from "toastify-js";
// ------ // ------
let username = "demo"; let username = "demo";
@@ -140,3 +141,4 @@
</div> </div>
</div> </div>
</div> </div>
<Footer />

View File

@@ -1,28 +1,50 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import lodashIsEqual from "lodash.isequal"; import lodashIsEqual from "lodash.isequal";
import store from "../store";
import { UserService } from "@odit/lfk-client-js"; import { UserService } from "@odit/lfk-client-js";
import "gridjs/dist/theme/mermaid.css"; import "gridjs/dist/theme/mermaid.css";
import PromiseError from "./PromiseError.svelte"; import PromiseError from "./PromiseError.svelte";
export let params; export let params;
const user_promise = UserService.userControllerGetOne(params.userid); const user_promise = UserService.userControllerGetOne(params.userid);
let data_loaded = false; let data_loaded = false;
let original_data = undefined; $: delete_triggered = false;
$: original_data = {};
$: editable_userdata = undefined; $: editable_userdata = undefined;
user_promise.then((data) => { user_promise.then((data) => {
data_loaded = true; data_loaded = true;
original_data = data; original_data = Object.assign(original_data, data);
editable_userdata = data; editable_userdata = data;
}); });
// $: changes_performed = lodashIsEqual(original_data, editable_userdata); $: changes_performed = !lodashIsEqual(original_data, editable_userdata);
$: changes_performed = !lodashIsEqual({ test: 1 }, { test: 1 });
function submit() { function submit() {
if (data_loaded === true && changes_performed === true) { if (data_loaded === true && changes_performed === true) {
console.log("ok, submitting..."); console.log("ok, submitting...");
console.log(editable_userdata);
UserService.userControllerPut(original_data.id, editable_userdata)
.then((resp) => {
console.log(resp);
Object.assign(original_data, editable_userdata);
original_data = editable_userdata;
Object.assign(original_data, editable_userdata);
})
.catch((err) => {
console.log(err);
});
} else { } else {
console.log("no changes performed"); console.log("no changes performed");
} }
} }
function deleteUser() {
UserService.userControllerRemove(original_data.id, true)
.then((resp) => {
console.log(resp);
location.replace("./");
})
.catch((err) => {
console.log(err);
});
}
</script> </script>
{#await user_promise} {#await user_promise}
@@ -63,36 +85,47 @@
<polyline points="12 5 19 12 12 19" /></svg> <polyline points="12 5 19 12 12 19" /></svg>
</li> </li>
<li class="flex items-center"> <li class="flex items-center">
<span class="mr-2">{user.firstname} <span class="mr-2">{original_data.firstname}
{user.middlename || ''} {original_data.middlename || ''}
{user.lastname}</span> {original_data.lastname}</span>
</li> </li>
</ol> </ol>
</nav> </nav>
</div> </div>
</div> </div>
<div class="mb-8 text-3xl font-extrabold leading-tight"> <div class="mb-8 text-3xl font-extrabold leading-tight">
{user.firstname} {original_data.firstname}
{user.middlename || ''} {original_data.middlename || ''}
{user.lastname} {original_data.lastname}
<span data-id="user_actions_${user.id}"> <span data-id="user_actions_${editable_userdata.id}">
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
{#if delete_triggered}
<button <button
class="hidden w-full 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" on:click={deleteUser}
data-userid="${user.id}" 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>
onclick="user__delete_cancel()">{$_('cancel')}</button>
<button <button
class="hidden w-full 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" on:click={() => {
data-userid="${user.id}" delete_triggered = !delete_triggered;
onclick="user__delete_confirm()">{$_('confirm-delete')}</button> }}
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 <button
on:click={() => {
delete_triggered = true;
}}
type="button" 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-user')}</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-user')}</button>
{/if}
{/if}
{#if !delete_triggered}
<button <button
disabled={!changes_performed} disabled={!changes_performed}
class:opacity-50={!changes_performed} class:opacity-50={!changes_performed}
type="button" type="button"
on:click={submit} 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> 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> </span>
</div> </div>
@@ -101,7 +134,7 @@
<img <img
alt={$_('profile-picture')} alt={$_('profile-picture')}
class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100" class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100"
src={user.profilePic} /> src={editable_userdata.profilePic} />
<!-- <span <!-- <span
class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg
class="h-full w-full text-gray-300" class="h-full w-full text-gray-300"
@@ -165,6 +198,79 @@
name="lastname" 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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" /> class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div> </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_userdata.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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
</div>
<div class="text-sm w-full">
<span class="font-medium">{$_('groups')}</span>
<select
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2"
multiple>
<option>Admins</option>
<option>Finanzen</option>
<option>...</option>
</select>
</div>
<div class="text-sm w-full">
<span class="font-medium">Permissions</span>
<div
class="border-4 border-dashed rounded h-96 mb-4 p-5 text-lg text-center">
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden">
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<button
type="button"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">&gt;</button>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<button
type="button"
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">&lt;</button>
</div>
</div>
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden">
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<div
class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center">
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
DEMO_PERMISSION
</p>
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
DEMO_PERMISSION
</p>
</div>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">
<div
class="border-4 border-dashed rounded mb-4 p-5 text-lg text-center">
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
DEMO_PERMISSION
</p>
<p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input">
DEMO_PERMISSION
</p>
</div>
</div>
</div>
TODO: permission picker 🔒
</div>
</div>
</section> </section>
{:catch error} {:catch error}
<PromiseError {error} /> <PromiseError {error} />

View File

@@ -1,13 +1,16 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import store from "../store";
import AddUserModal from "./AddUserModal.svelte"; import AddUserModal from "./AddUserModal.svelte";
export let modal_open = false; export let modal_open = false;
import UsersOverview from "./UsersOverview.svelte"; import UsersOverview from "./UsersOverview.svelte";
console.log(store.state.jwtinfo.userdetails.permissions);
</script> </script>
<section class="container p-5"> <section class="container p-5">
<span class="mb-1 text-3xl font-extrabold leading-tight"> <span class="mb-1 text-3xl font-extrabold leading-tight">
{$_('users')} {$_('users')}
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')}
<button <button
on:click={() => { on:click={() => {
modal_open = true; modal_open = true;
@@ -16,8 +19,12 @@
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"> 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-user')} {$_('create-user')}
</button> </button>
{/if}
</span> </span>
<p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p> <p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p>
<UsersOverview /> <UsersOverview />
</section> </section>
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')}
<AddUserModal bind:modal_open /> <AddUserModal bind:modal_open />
{/if}

View File

@@ -5,8 +5,10 @@
const users_promise = UserService.userControllerGetAll(); const users_promise = UserService.userControllerGetAll();
import "gridjs/dist/theme/mermaid.css"; import "gridjs/dist/theme/mermaid.css";
import { users as usersstore } from "../store.js"; import { users as usersstore } from "../store.js";
import store from "../store";
import UsersEmptyState from "./UsersEmptyState.svelte"; import UsersEmptyState from "./UsersEmptyState.svelte";
$: searchvalue = ""; $: searchvalue = "";
$: active_deletes = [];
$: userscache = []; $: userscache = [];
$: advanced_search = false; $: advanced_search = false;
usersstore.subscribe((val) => { usersstore.subscribe((val) => {
@@ -18,6 +20,7 @@
}); });
</script> </script>
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:GET')}
{#await users_promise} {#await users_promise}
<div <div
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2" class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
@@ -120,16 +123,51 @@
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a> class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
{/each} {/each}
</td> </td>
{#if active_deletes[u.id] === true}
<td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button
on:click={() => {
active_deletes[u.id] = false;
}}
tabindex="0"
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) => {
console.log(resp);
// user deleted
users_promise.then((data) => {
console.log(data);
usersstore.set(data);
});
})
.catch((err) => {
// error deleting user
});
}}
tabindex="0"
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
Delete</button>
</td>
{:else}
<td <td
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<a <a
href="./{u.id}" href="./{u.id}"
class="text-indigo-600 hover:text-indigo-900">Edit</a> class="text-indigo-600 hover:text-indigo-900">Edit</a>
<span {#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
<button
on:click={() => {
active_deletes[u.id] = true;
}}
tabindex="0" tabindex="0"
href="#" 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</span> {/if}
</td> </td>
{/if}
</tr> </tr>
{/if} {/if}
{/each} {/each}
@@ -145,3 +183,4 @@
</span> </span>
</div> </div>
{/await} {/await}
{/if}

View File

@@ -6,10 +6,12 @@
"add-your-first-track": "Add your first track", "add-your-first-track": "Add your first track",
"application_name": "Lauf für Kaya! - Admin", "application_name": "Lauf für Kaya! - Admin",
"author": "Author", "author": "Author",
"browse": "Browse",
"by": "by", "by": "by",
"cancel": "Cancel", "cancel": "Cancel",
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity", "cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
"changelog": "Changelog", "changelog": "Changelog",
"close": "Close",
"confirm-delete": "Confirm Delete", "confirm-delete": "Confirm Delete",
"count_organizations": "# Organizations", "count_organizations": "# Organizations",
"count_teams": "# Teams", "count_teams": "# Teams",
@@ -38,16 +40,38 @@
"dependency_name": "Name", "dependency_name": "Name",
"dont-have-your-email-connected": "Don't have your email connected?", "dont-have-your-email-connected": "Don't have your email connected?",
"dont-panic-were-resetting-it": "Don't panic, we're resetting it ✌", "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", "e-mail-adress": "E-Mail Adress",
"email_address_or_username": "Email / username", "email_address_or_username": "Email / username",
"error_on_login": "Error on login", "error_on_login": "Error on login",
"faq": "FAQ", "faq": "FAQ",
"filepond__abort": "Abort",
"filepond__cancel": "Cancel",
"filepond__error-during-load": "Error during load",
"filepond__error-during-remove": "Error during remove",
"filepond__error-during-revert": "Error during revert",
"filepond__error-during-upload": "Error during upload",
"filepond__field-contains-invalid-files": "Field contains invalid files",
"filepond__loading": "Loading",
"filepond__remove": "Remove",
"filepond__retry": "Retry",
"filepond__size-not-available": "Size not available",
"filepond__tap-to-cancel": "tap to cancel",
"filepond__tap-to-retry": "tap to retry",
"filepond__tap-to-undo": "tap to undo",
"filepond__undo": "Undo",
"filepond__upload": "Upload",
"filepond__upload-cancelled": "Upload cancelled",
"filepond__upload-complete": "Upload complete",
"filepond__uploading": "Uploading",
"filepond__waiting-for-size": "Waiting for size",
"first-name": "First name", "first-name": "First name",
"first-name-is-required": "First Name is required", "first-name-is-required": "First Name is required",
"forgot_password?": "Forgot your password?", "forgot_password?": "Forgot your password?",
"general-stats": "General Stats", "general-stats": "General Stats",
"general_promise_error": "😢 Error", "general_promise_error": "😢 Error",
"goback": "Go Home", "goback": "Go Home",
"groups": "Groups",
"hallo": "hello", "hallo": "hello",
"installed-version": "Installed version", "installed-version": "Installed version",
"invalid-mail-reset": "the provided email is invalid", "invalid-mail-reset": "the provided email is invalid",
@@ -55,6 +79,7 @@
"last-name-is-required": "Last Name is required", "last-name-is-required": "Last Name is required",
"lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.", "lfk-is-os": "The \"Lauf für Kaya!\" Frontend is (like all other projects for the \"LfK!\" Also) an open source project.",
"license": "License", "license": "License",
"licenses-are-being-loaded": "Licenses are being loaded...",
"log_in": "Log in", "log_in": "Log in",
"log_in_to_your_account": "Log in to your account", "log_in_to_your_account": "Log in to your account",
"login_is_checked": "Login is being checked...", "login_is_checked": "Login is being checked...",

View File

@@ -27,6 +27,8 @@ const store = () => {
AuthService.authControllerRefresh({ token: state.auth.refresh_token }).then((auth) => { AuthService.authControllerRefresh({ token: state.auth.refresh_token }).then((auth) => {
console.log('got new auth'); console.log('got new auth');
OpenAPI.TOKEN = auth.access_token; OpenAPI.TOKEN = auth.access_token;
const jwtinfo = JSON.parse(atob(auth.access_token.split('.')[1]));
state.jwtinfo = jwtinfo;
localForage.setItem('logindata', auth); localForage.setItem('logindata', auth);
}); });
}, },
@@ -39,8 +41,8 @@ const store = () => {
// //
state.refreshInterval = setInterval(() => { state.refreshInterval = setInterval(() => {
this.refreshAuth(); this.refreshAuth();
// 4min // 2min
}, 4 * 60000); }, 2 * 60000);
// //
return state; return state;
}); });

View File

@@ -2,7 +2,7 @@ module.exports = {
purge: { purge: {
content: [ './src/**/*.svelte' ] content: [ './src/**/*.svelte' ]
}, },
darkMode: 'media', // darkMode: 'media',
variants: {}, variants: {},
plugins: [], plugins: [],
theme: { theme: {

5
versionbuilder.js Normal file
View File

@@ -0,0 +1,5 @@
const fs = require('fs');
const package = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
const original = fs.readFileSync(`./public/index.html`, { encoding: 'utf-8' });
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + package.version + '-RELEASE_INFO');
fs.writeFileSync(`./public/index.html`, out);