Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
7cd24cd51d | |||
c81b34c1d0 | |||
7b1acc494d | |||
6ff90694e2 | |||
157c7c66b5 | |||
93249258c6 | |||
01c01a46fa | |||
0e2a10fe94 | |||
0b9f3de47c | |||
bc239eead1 | |||
7a09869b0c | |||
bdc0de6ada | |||
b497cebe76 | |||
0fa107a75b | |||
35b18d72fd | |||
4b80f30afb | |||
ad34e455ce | |||
01fdd0bee2 | |||
32ffa345cd | |||
6fc3c16073 | |||
7d58657c80 | |||
fcd657c10e | |||
4ab77c5557 | |||
2bbaa500f4 | |||
722a20e141 | |||
041c24a837 | |||
39a3baa00b | |||
f7acbb1eaa | |||
e6fbf7aa5b | |||
87926e69db | |||
36a084eab6 | |||
a9e319e0c0 | |||
ea23b97231 | |||
7df76f9642 | |||
f6db117a5e | |||
23c3cd605d | |||
77690702c0 | |||
e0093480d9 | |||
c7679b7a67 | |||
e6ac34bde8 | |||
8c4b595c30 | |||
be629e5c6b | |||
63569684a3 | |||
5937a0d7ce | |||
4512272c1c | |||
ce1f3842e0 | |||
ee01c3a059 | |||
81c1537bad | |||
98ecfab032 | |||
b948b8c1a4 | |||
f856c6ae37 | |||
2dd2580530 | |||
330755c63e | |||
9cf0174b41 | |||
16f572480a | |||
b8a9e4f272 | |||
c089bb3929 | |||
3caa1fc277 | |||
43b406592e | |||
1dd6674faa | |||
4674b52717 | |||
cd5831251a | |||
45ec97066f | |||
b08c0f145a | |||
f0c100aee4 | |||
0e31ba212f | |||
692c906cd2 | |||
4f3837ac45 |
24
.drone.yml
24
.drone.yml
@@ -4,18 +4,6 @@ type: docker
|
||||
name: build:dev
|
||||
|
||||
steps:
|
||||
- name: build dev
|
||||
image: plugins/docker
|
||||
depends_on: [clone]
|
||||
settings:
|
||||
username:
|
||||
from_secret: DOCKER_REGISTRY_USER
|
||||
password:
|
||||
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||
repo: registry.odit.services/lfk/frontend
|
||||
tags:
|
||||
- dev
|
||||
registry: registry.odit.services
|
||||
- name: run full license export
|
||||
depends_on: ["clone"]
|
||||
image: node:alpine
|
||||
@@ -33,6 +21,18 @@ steps:
|
||||
remote: git@git.odit.services:lfk/frontend.git
|
||||
ssh_key:
|
||||
from_secret: GITLAB_SSHKEY
|
||||
- name: build dev
|
||||
image: plugins/docker
|
||||
depends_on: [clone]
|
||||
settings:
|
||||
username:
|
||||
from_secret: DOCKER_REGISTRY_USER
|
||||
password:
|
||||
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||
repo: registry.odit.services/lfk/frontend
|
||||
tags:
|
||||
- dev
|
||||
registry: registry.odit.services
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
|
92
CHANGELOG.md
92
CHANGELOG.md
@@ -2,8 +2,99 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
||||
|
||||
#### [0.3.0](https://git.odit.services/lfk/frontend/compare/0.2.1...0.3.0)
|
||||
|
||||
- Merge pull request 'feature/16-org-management' (#32) from feature/16-org-management into dev [`#16`](https://git.odit.services/lfk/frontend/issues/16)
|
||||
- Merge commit 'fcd657c10ea14290455cfb0bf2de89375a664143' into dev [`#31`](https://git.odit.services/lfk/frontend/issues/31)
|
||||
- ✨ added Org base components [`bdc0de6`](https://git.odit.services/lfk/frontend/commit/bdc0de6adab2db95e6075a993bd50317e9e36eb5)
|
||||
- 🏬 OrgDetail ui [`7a09869`](https://git.odit.services/lfk/frontend/commit/7a09869b0ca9d5dd38cf0c0010b71ab9ce6c6f40)
|
||||
- 🏁 finish basic functionality of AddOrgModal + OrgDetail [`9324925`](https://git.odit.services/lfk/frontend/commit/93249258c6b0f34da22f0ed5d290b437d221a8fd)
|
||||
- ✨ basic functionality in OrgDetail [`0e2a10f`](https://git.odit.services/lfk/frontend/commit/0e2a10fe94075b3cda8ef3ebae6a6159a2e6bbf9)
|
||||
- 🐞 fix sidebar mobile-md scaling [`fcd657c`](https://git.odit.services/lfk/frontend/commit/fcd657c10ea14290455cfb0bf2de89375a664143)
|
||||
- 🔨 reorder CI build order for correct license exporting [`7d58657`](https://git.odit.services/lfk/frontend/commit/7d58657c800e9e494c1d1f098ad0dc34d1f0cd8d)
|
||||
- 💬 AddOrgModal bindings [`bc239ee`](https://git.odit.services/lfk/frontend/commit/bc239eead1d1a29c9662d94db797c6bf23e43166)
|
||||
- ✨ improvements in OrgOverview [`0b9f3de`](https://git.odit.services/lfk/frontend/commit/0b9f3de47c0c8b750c38da07e53927ba55ef3499)
|
||||
- 🔨 config compatibility for new Snowpack V3 bundler [`32ffa34`](https://git.odit.services/lfk/frontend/commit/32ffa345cde67b1affe2750add620522c0a24577)
|
||||
- 🧹 general component cleanup [`157c7c6`](https://git.odit.services/lfk/frontend/commit/157c7c66b57c3a5053c780682402d3615fbc046a)
|
||||
- ⏫ basic dependency bump [`6fc3c16`](https://git.odit.services/lfk/frontend/commit/6fc3c16073555fffd55773218c5c2eed361f076b)
|
||||
- 🌎 i18n [`01c01a4`](https://git.odit.services/lfk/frontend/commit/01c01a46faa9332a2e437861fdb42afe962da833)
|
||||
- ⏫ bump gridjs to 3.2.2 [`6ff9069`](https://git.odit.services/lfk/frontend/commit/6ff90694e288356e16f5226a6e0a054e6fec8b3f)
|
||||
- [tmp] - disable serviceworker [`0fa107a`](https://git.odit.services/lfk/frontend/commit/0fa107a75bc33046758bc42523262a566da9f60f)
|
||||
- new license file version [CI SKIP] [`ad34e45`](https://git.odit.services/lfk/frontend/commit/ad34e455ceedc0e0ccca5ccd86f7f011a7667873)
|
||||
- ⏫ Bump Dockerfile builder to 15.5.1-alpine3.12 [`01fdd0b`](https://git.odit.services/lfk/frontend/commit/01fdd0bee2199bb58373aecc9942591a2d45011a)
|
||||
- new license file version [CI SKIP] [`87926e6`](https://git.odit.services/lfk/frontend/commit/87926e69dbd5b93b2c98cd68fb31913259e3cc00)
|
||||
- 🐳 Dockerfile - drop js sourcemaps [`4b80f30`](https://git.odit.services/lfk/frontend/commit/4b80f30afbfb8c16b9395fb310f309c516c48a17)
|
||||
|
||||
#### [0.2.1](https://git.odit.services/lfk/frontend/compare/0.2.0...0.2.1)
|
||||
|
||||
> 13 January 2021
|
||||
|
||||
- 🔒 UserDetail - WIP on Permissions [`36a084e`](https://git.odit.services/lfk/frontend/commit/36a084eab6bd0c922da29ebb2d260ba803bf9675)
|
||||
- 👪 UserDetail - group edit support [`a9e319e`](https://git.odit.services/lfk/frontend/commit/a9e319e0c0f2bfaba42bc3af875462e394489dc2)
|
||||
- 🙋♂️ UserDetails - group updating [`041c24a`](https://git.odit.services/lfk/frontend/commit/041c24a837d58ff46362699b54e8088f22ba2daa)
|
||||
- ⚡ shared state reactivity - AddUserModal-Users-UsersOverview [`f7acbb1`](https://git.odit.services/lfk/frontend/commit/f7acbb1eaa14ddf41e29ff1db631520123218289)
|
||||
- ✨ AddUserModal + UserDetail - optional username field [`7df76f9`](https://git.odit.services/lfk/frontend/commit/7df76f9642b528586fd654f27148b5502400ffdf)
|
||||
- UserDetail - fixed group updating [`e6fbf7a`](https://git.odit.services/lfk/frontend/commit/e6fbf7aa5b230733ffd92fdfe851b9f86001c859)
|
||||
- 🚀RELEASE v0.2.1 [`2bbaa50`](https://git.odit.services/lfk/frontend/commit/2bbaa500f4ca56e41613cac12228f4e3327180ab)
|
||||
- 💬 UserDetail - info Toasts [`ea23b97`](https://git.odit.services/lfk/frontend/commit/ea23b972315db39e1f800366d52e3bacf9eaf58b)
|
||||
- 🔨 optimized release script [`23c3cd6`](https://git.odit.services/lfk/frontend/commit/23c3cd605db950a5620ea709748216f7ea034385)
|
||||
- 🐞 fix package release script: locales directory [`722a20e`](https://git.odit.services/lfk/frontend/commit/722a20e141079302da8876be1ccc55026c588048)
|
||||
- ⏫ bump @odit/lfk-client-js to 0.0.11 [`f6db117`](https://git.odit.services/lfk/frontend/commit/f6db117a5eca5c9692a4c5d83159917a712a0e63)
|
||||
- 🐞 UserDetail - fix permission reactivity by assignments [`39a3baa`](https://git.odit.services/lfk/frontend/commit/39a3baa00b0575ee3150c7ae26f32995e2e857d9)
|
||||
|
||||
#### [0.2.0](https://git.odit.services/lfk/frontend/compare/0.1.6...0.2.0)
|
||||
|
||||
> 11 January 2021
|
||||
|
||||
- 🔒 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)
|
||||
- 🚀RELEASE v0.2.0 [`7769070`](https://git.odit.services/lfk/frontend/commit/77690702c0461b71ff1b65a44bfdc331d5a42c3e)
|
||||
- [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)
|
||||
|
||||
> 10 January 2021
|
||||
|
||||
- 🌎 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)
|
||||
- 🌎 added i18n for UsersOverview [`3754f09`](https://git.odit.services/lfk/frontend/commit/3754f09b2f395a82ff8c3a9c655ab8a782e7eb71)
|
||||
@@ -11,6 +102,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)
|
||||
- ✨ 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)
|
||||
- 🚀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)
|
||||
|
||||
#### [0.1.2](https://git.odit.services/lfk/frontend/compare/0.1.2-1...0.1.2)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
FROM node:15.4.0-alpine3.12
|
||||
FROM node:15.5.1-alpine3.12
|
||||
WORKDIR /app
|
||||
RUN npm i -g pnpm
|
||||
COPY package.json ./
|
||||
@@ -11,6 +11,7 @@ RUN pnpm run build
|
||||
# final image
|
||||
FROM alpine
|
||||
COPY --from=0 /app/build /app
|
||||
RUN rm -rf build/sw.js.map build/workbox-*.js.map
|
||||
RUN rm -rf /app/build/_dist_/components
|
||||
RUN rm -rf /app/build/_dist_/locales
|
||||
RUN rm -rf /app/build-manifest.json
|
||||
|
@@ -9,7 +9,7 @@ http {
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
|
||||
location ~* \.(?:ico|css|gif|jpe?g|png)$ {
|
||||
expires 1y;
|
||||
add_header Pragma public;
|
||||
add_header Cache-Control "public";
|
||||
|
13
package.json
13
package.json
@@ -1,19 +1,18 @@
|
||||
{
|
||||
"name": "@odit/lfk-frontend",
|
||||
"version": "0.1.3",
|
||||
"version": "0.3.0",
|
||||
"scripts": {
|
||||
"i18n-order": "node order.js",
|
||||
"dev": "snowpack dev",
|
||||
"build": "snowpack build",
|
||||
"build:sw": "workbox generateSW workbox-config.js",
|
||||
"release": "release-it",
|
||||
"changelog": "npx auto-changelog --commit-limit false --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs",
|
||||
"licenses:export": "license-exporter --json -o public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@odit/lfk-client-js": "0.0.10",
|
||||
"@odit/lfk-client-js": "0.0.12",
|
||||
"filepond": "4.25.1",
|
||||
"gridjs": "3.2.1",
|
||||
"gridjs": "3.2.2",
|
||||
"localforage": "1.9.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"svelte-filepond": "0.0.1",
|
||||
@@ -26,13 +25,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@odit/license-exporter": "0.0.9",
|
||||
"@snowpack/plugin-svelte": "3.4.1",
|
||||
"@snowpack/plugin-svelte": "3.5.1",
|
||||
"auto-changelog": "^2.2.1",
|
||||
"autoprefixer": "10.2.1",
|
||||
"postcss": "8.2.4",
|
||||
"postcss-load-config": "3.0.0",
|
||||
"release-it": "^14.2.2",
|
||||
"snowpack": "3.0.0-rc.2",
|
||||
"snowpack": "3.0.10",
|
||||
"svelte": "3.31.2",
|
||||
"svelte-preprocess": "4.6.1",
|
||||
"workbox-cli": "6.0.2"
|
||||
@@ -51,7 +50,7 @@
|
||||
"publish": false
|
||||
},
|
||||
"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 && node order.js && git add src/locales"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.3.0-RELEASE_INFO</span>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<script src="/env.js"></script>
|
||||
<script defer type="module" src="/_dist_/index.js"></script>
|
||||
|
File diff suppressed because one or more lines are too long
@@ -5,10 +5,11 @@ module.exports = {
|
||||
src: '/_dist_'
|
||||
},
|
||||
plugins: [ '@snowpack/plugin-svelte' ],
|
||||
install: [
|
||||
/* ... */
|
||||
routes: [
|
||||
/* Enable an SPA Fallback in development: */
|
||||
{ match: 'routes', src: '.*', dest: '/index.html' }
|
||||
],
|
||||
installOptions: {
|
||||
packageOptions: {
|
||||
/* ... */
|
||||
sourceMap: false
|
||||
},
|
||||
@@ -18,13 +19,8 @@ module.exports = {
|
||||
buildOptions: {
|
||||
/* ... */
|
||||
},
|
||||
proxy: {
|
||||
/* ... */
|
||||
},
|
||||
alias: {
|
||||
/* ... */
|
||||
},
|
||||
experiments: {
|
||||
optimize: { bundle: true, minify: true }
|
||||
}
|
||||
optimize: { bundle: true, minify: true }
|
||||
};
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import "./TailwindStyles.svelte";
|
||||
import "toastify-js/src/toastify.css";
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
import { Route, router } from "tinro";
|
||||
router.subscribe((routeInfo) => {
|
||||
window.scrollTo(0, 0);
|
||||
|
@@ -50,14 +50,14 @@
|
||||
<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
|
||||
fill="currentColor"
|
||||
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"
|
||||
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>
|
||||
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 class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium">
|
||||
@@ -79,7 +79,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">
|
||||
Close
|
||||
{$_('close')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -112,13 +112,12 @@
|
||||
<h2 class="text-4xl font-display font-semibold md:text-5xl">
|
||||
{$_('credits')}
|
||||
</h2>
|
||||
<div
|
||||
class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
|
||||
<div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
|
||||
<p class="text-center">{$_('oss_credit_description')}</p>
|
||||
</div>
|
||||
<div class="w-screen leading-8 pl-5 mt-5">
|
||||
{#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}
|
||||
<table>
|
||||
<thead>
|
||||
@@ -164,9 +163,7 @@
|
||||
</div>
|
||||
{/await}
|
||||
</div>
|
||||
<h2 class="text-4xl font-display font-semibold md:text-5xl">
|
||||
Fragen
|
||||
</h2>
|
||||
<h2 class="text-4xl font-display font-semibold md:text-5xl">{$_('faq')}</h2>
|
||||
<div class="mt-6 border-t-2 border-gray-100 pt-10">
|
||||
<dl class="md:grid md:grid-cols-2 md:gap-8">
|
||||
<div>
|
||||
|
162
src/components/AddOrgModal.svelte
Normal file
162
src/components/AddOrgModal.svelte
Normal file
@@ -0,0 +1,162 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { RunnerOrganisationService } 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();
|
||||
RunnerOrganisationService.runnerOrganisationControllerPost({
|
||||
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}
|
@@ -2,20 +2,21 @@
|
||||
import { _ } from "svelte-i18n";
|
||||
import { clickOutside } from "./outsideclick";
|
||||
import { focusTrap } from "svelte-focus-trap";
|
||||
import { tracks as tracksstore } from "../store.js";
|
||||
import { UserService } from "@odit/lfk-client-js";
|
||||
import isEmail from "validator/es/lib/isEmail";
|
||||
import Toastify from "toastify-js";
|
||||
import "toastify-js/src/toastify.css";
|
||||
export let modal_open;
|
||||
export let current_users;
|
||||
let firstname_input;
|
||||
let lastname_input;
|
||||
let middlename_input;
|
||||
let username_input;
|
||||
let password_input;
|
||||
let email_input;
|
||||
function focus(el) {
|
||||
el.focus();
|
||||
}
|
||||
$: username_input_value = "";
|
||||
$: middlename_input_value = "";
|
||||
$: password_input_value = "";
|
||||
$: email_input_value = "";
|
||||
@@ -49,17 +50,25 @@
|
||||
text: "User is being added...",
|
||||
duration: -1,
|
||||
}).showToast();
|
||||
UserService.userControllerPost({
|
||||
let postdata={
|
||||
firstname: firstname_input_value,
|
||||
lastname: lastname_input_value,
|
||||
middlename: middlename_input_value,
|
||||
email: email_input_value,
|
||||
password: password_input_value,
|
||||
})
|
||||
password: password_input_value
|
||||
};
|
||||
if(email_input_value!==""){
|
||||
postdata.email=email_input_value;
|
||||
}
|
||||
if(username_input_value!==""){
|
||||
postdata.username=username_input_value;
|
||||
}
|
||||
UserService.userControllerPost(postdata)
|
||||
.then((result) => {
|
||||
firstname_input_value = "";
|
||||
lastname_input_value = "";
|
||||
middlename_input_value = "";
|
||||
email_input_value = "";
|
||||
username_input_value = "";
|
||||
modal_open = false;
|
||||
//
|
||||
Toastify({
|
||||
@@ -67,12 +76,8 @@
|
||||
duration: 500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
let storeval = [];
|
||||
tracksstore.subscribe((val) => {
|
||||
storeval = val;
|
||||
});
|
||||
storeval.push(result);
|
||||
tracksstore.set(storeval);
|
||||
current_users.push(result);
|
||||
current_users=current_users;
|
||||
})
|
||||
.catch((err) => {
|
||||
//
|
||||
@@ -213,6 +218,19 @@
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<label
|
||||
for="trackname"
|
||||
class="block text-sm font-medium text-gray-700">{$_('username')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('username')}
|
||||
bind:value={username_input_value}
|
||||
bind:this={username_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="email"
|
||||
|
@@ -24,19 +24,40 @@
|
||||
)
|
||||
check = true;
|
||||
})(navigator.userAgent || navigator.vendor || window.opera);
|
||||
const aspectratio=window.innerWidth/window.innerHeight;
|
||||
if(aspectratio<=0.765){
|
||||
check=true;
|
||||
}
|
||||
return check;
|
||||
}
|
||||
$: mobile = ismobile();
|
||||
window.addEventListener('resize', function(){
|
||||
const aspectratio=window.innerWidth/window.innerHeight;
|
||||
if(aspectratio<=0.765){
|
||||
navOpen=false;
|
||||
mobile=true;
|
||||
}else{
|
||||
navOpen=true;
|
||||
mobile=false;
|
||||
|
||||
}
|
||||
});
|
||||
// $: if (mobile===true) {
|
||||
// console.log("changed to mobile");
|
||||
// }
|
||||
// $: if (mobile===false) {
|
||||
// console.log("changed to md");
|
||||
// }
|
||||
function logout() {
|
||||
localForage.clear();
|
||||
location.replace("/");
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="min-h-screen bg-gray-50 dark:bg-black dark:text-gray-100">
|
||||
<section class="min-h-screen bg-gray-50">
|
||||
<nav
|
||||
class:hidden={!navOpen && mobile}
|
||||
class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 md:translate-x-0">
|
||||
class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 md:translate-x-0 bg-gray-50">
|
||||
<a href="/" class="flex items-center px-4 py-5">
|
||||
<img
|
||||
src="/lfk-logo.png"
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import { _, json } from "svelte-i18n";
|
||||
import { getlang } from "./datatable_i18n";
|
||||
import { Grid } from "gridjs";
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
//
|
||||
let table;
|
||||
const datatable = new Grid({
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<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
|
||||
@@ -11,12 +12,60 @@
|
||||
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}
|
||||
|
@@ -1,15 +1,35 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
$: releaseinfo = "";
|
||||
setTimeout(() => {
|
||||
releaseinfo = document
|
||||
.getElementById("buildinfo")
|
||||
.textContent.replace("RELEASE_INFO-", "")
|
||||
.replace("-RELEASE_INFO", "");
|
||||
}, 1500);
|
||||
const year = new Date().getFullYear();
|
||||
</script>
|
||||
|
||||
<footer class="container">
|
||||
<hr class="mt-2 mb-4 border-b-1 border-gray-300" />
|
||||
<footer class="p-5 w-full">
|
||||
<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
|
||||
class="underline"
|
||||
href="https://odit.services"
|
||||
rel="noopener,noreferrer"
|
||||
target="_blank">ODIT.Services</a>
|
||||
</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>
|
||||
|
@@ -4,6 +4,7 @@
|
||||
import { _ } from "svelte-i18n";
|
||||
store.init();
|
||||
import { OpenAPI, AuthService } from "@odit/lfk-client-js";
|
||||
import Footer from "./Footer.svelte";
|
||||
import Toastify from "toastify-js";
|
||||
// ------
|
||||
let username = "demo";
|
||||
@@ -140,3 +141,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
|
@@ -1,83 +1,205 @@
|
||||
<script>
|
||||
import { RunnerOrganisationService } from "@odit/lfk-client-js";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import store from "../store";
|
||||
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 = RunnerOrganisationService.runnerOrganisationControllerGetOne(
|
||||
params.orgid
|
||||
).then((value) => {
|
||||
data_loaded = true;
|
||||
orgdata = Object.assign(orgdata, value);
|
||||
original = Object.assign(original, value);
|
||||
});
|
||||
function deleteOrganisation() {
|
||||
RunnerOrganisationService.runnerOrganisationControllerRemove(
|
||||
original.id,
|
||||
true
|
||||
)
|
||||
.then((resp) => {
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
function submit() {
|
||||
if (data_loaded === true && save_enabled) {
|
||||
Toastify({
|
||||
text: "updating organization",
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
RunnerOrganisationService.runnerOrganisationControllerPut(
|
||||
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 {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="container p-5">
|
||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||
Orgs
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">
|
||||
configure the tracks & minimum lap times
|
||||
</p>
|
||||
<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>
|
||||
{#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('USER:DELETE')}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteOrganisation}
|
||||
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>
|
||||
</section>
|
||||
<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 dark:bg-gray-900 dark:text-gray-100 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 dark:bg-gray-900 dark:text-gray-100 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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" />
|
||||
</div>
|
||||
</section>
|
||||
{:else}
|
||||
{#await promise}
|
||||
organization detail is being loaded...
|
||||
{:catch error}
|
||||
<PromiseError />
|
||||
{/await}
|
||||
{/if}
|
||||
|
157
src/components/OrgOverview.svelte
Normal file
157
src/components/OrgOverview.svelte
Normal file
@@ -0,0 +1,157 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import { RunnerOrganisationService } from "@odit/lfk-client-js";
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
import store from "../store";
|
||||
import OrgsEmptyState from "./OrgsEmptyState.svelte";
|
||||
$: searchvalue = "";
|
||||
$: active_deletes = [];
|
||||
export let current_organizations = [];
|
||||
|
||||
const promise = RunnerOrganisationService.runnerOrganisationControllerGetAll().then(
|
||||
(val) => {
|
||||
current_organizations = val;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION: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">organizations are being loaded...</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
{#if current_organizations.length === 0}
|
||||
<OrgsEmptyState />
|
||||
{: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">
|
||||
Address
|
||||
</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 current_organizations as o}
|
||||
{#if Object.values(o)
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.includes(searchvalue)}
|
||||
<tr data-rowid="org_{o.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 dark:text-gray-100">
|
||||
{o.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 dark:text-gray-100">
|
||||
{#if o.address}
|
||||
{JSON.stringify(o.address)}
|
||||
{:else}no address specified{/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 dark:text-gray-100">
|
||||
{#if o.contact}
|
||||
{JSON.stringify(o.contact)}
|
||||
{:else}no contact specified{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
{#if active_deletes[o.id] === true}
|
||||
<td
|
||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<button
|
||||
on:click={() => {
|
||||
active_deletes[o.id] = false;
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">Cancel
|
||||
Delete</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
RunnerOrganisationService.runnerOrganisationControllerRemove(o.id, true)
|
||||
.then((resp) => {
|
||||
current_organizations = current_organizations.filter((obj) => obj.id !== o.id);
|
||||
})
|
||||
.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
|
||||
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>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION: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>
|
||||
{/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,13 +1,31 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import store from "../store";
|
||||
import AddOrgModal from "./AddOrgModal.svelte";
|
||||
export let modal_open = false;
|
||||
import OrgOverview from "./OrgOverview.svelte";
|
||||
console.log(store.state.jwtinfo.userdetails.permissions);
|
||||
let current_organizations = [];
|
||||
</script>
|
||||
|
||||
<section class="container p-5">
|
||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||
Orgs
|
||||
{$_('organizations')}
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION: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-organization')}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">
|
||||
add, delete, edit organizations
|
||||
</p>
|
||||
<nav><a class="underline" href="./1">Org 1</a></nav>
|
||||
<p class="mb-8 text-lg text-gray-500">manage runner organizations</p>
|
||||
<OrgOverview bind:current_organizations />
|
||||
</section>
|
||||
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('ORGANISATION:CREATE')}
|
||||
<AddOrgModal bind:current_organizations bind:modal_open />
|
||||
{/if}
|
||||
|
15
src/components/OrgsEmptyState.svelte
Normal file
15
src/components/OrgsEmptyState.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import AddOrgModal from "./AddOrgModal.svelte";
|
||||
let modal_open = false;
|
||||
let current_organizations = [];
|
||||
</script>
|
||||
|
||||
<div class="text-center items-center justify-center">
|
||||
<p class="mb-16 text-lg text-gray-500">
|
||||
<span class="font-bold">There are no organizations added yet.</span><br />
|
||||
<span>Add your first organization</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<AddOrgModal bind:modal_open bind:current_organizations />
|
@@ -6,7 +6,6 @@
|
||||
const tracks_promise = TrackService.trackControllerGetAll();
|
||||
import { getlang } from "./datatable_i18n";
|
||||
import { Grid, html } from "gridjs";
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
import { tracks as tracksstore } from "../store.js";
|
||||
$: trackscache = [];
|
||||
$: blocked = [];
|
||||
|
@@ -1,27 +1,91 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import lodashIsEqual from "lodash.isequal";
|
||||
import { UserService } from "@odit/lfk-client-js";
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
import store from "../store";
|
||||
import {
|
||||
UserService,
|
||||
UserGroupService,
|
||||
PermissionService,
|
||||
} from "@odit/lfk-client-js";
|
||||
import Toastify from "toastify-js";
|
||||
import PromiseError from "./PromiseError.svelte";
|
||||
export let params;
|
||||
const user_promise = UserService.userControllerGetOne(params.userid);
|
||||
let data_loaded = false;
|
||||
let original_data = undefined;
|
||||
$: editable_userdata = undefined;
|
||||
$: delete_triggered = false;
|
||||
$: original_data = {};
|
||||
$: editable_userdata = {};
|
||||
$: allpermissions = [];
|
||||
$: allgroups = [];
|
||||
$: allgroups_ids = [];
|
||||
$: usergroups_array_objects = [];
|
||||
$: usergroups_array = [];
|
||||
let usergroups_array_original = [];
|
||||
user_promise.then((data) => {
|
||||
data_loaded = true;
|
||||
original_data = data;
|
||||
original_data = Object.assign(original_data, data);
|
||||
editable_userdata = data;
|
||||
data.groups.forEach((g) => {
|
||||
usergroups_array=usergroups_array.concat([g.id]);
|
||||
});
|
||||
usergroups_array_original = usergroups_array;
|
||||
allgroups.forEach((g) => {
|
||||
allgroups_ids.push(g.id);
|
||||
});
|
||||
});
|
||||
// $: changes_performed = lodashIsEqual(original_data, editable_userdata);
|
||||
$: changes_performed = !lodashIsEqual({ test: 1 }, { test: 1 });
|
||||
UserGroupService.userGroupControllerGetAll().then((data) => {
|
||||
allgroups = data;
|
||||
});
|
||||
const permissions_promise = PermissionService.permissionControllerGetAll();
|
||||
permissions_promise.then((data) => {
|
||||
data.forEach((p) => {
|
||||
allpermissions=allpermissions.concat([p.target + ":" + p.action])
|
||||
});
|
||||
});
|
||||
$: changes_performed = !lodashIsEqual(original_data, editable_userdata);
|
||||
$: groups_changed = JSON.stringify(usergroups_array)===JSON.stringify(usergroups_array_original);
|
||||
$: save_enabled = changes_performed||!groups_changed;
|
||||
function submit() {
|
||||
if (data_loaded === true && changes_performed === true) {
|
||||
console.log("ok, submitting...");
|
||||
} else {
|
||||
console.log("no changes performed");
|
||||
if (
|
||||
!lodashIsEqual(original_data.permissions, editable_userdata.permissions)
|
||||
) {
|
||||
// TODO: add+delete permissions
|
||||
}
|
||||
if (data_loaded === true && save_enabled) {
|
||||
let tmp=[];
|
||||
usergroups_array.forEach(g => {
|
||||
const group=allgroups.find(obj=>obj.id===g);
|
||||
tmp.push(group);
|
||||
});
|
||||
editable_userdata.groups=tmp;
|
||||
Toastify({
|
||||
text: $_("updating-user"),
|
||||
duration: 2500,
|
||||
}).showToast();
|
||||
UserService.userControllerPut(original_data.id, editable_userdata)
|
||||
.then((resp) => {
|
||||
Object.assign(original_data, editable_userdata);
|
||||
original_data = editable_userdata;
|
||||
Object.assign(original_data, editable_userdata);
|
||||
//
|
||||
Toastify({
|
||||
text: $_("user-updated"),
|
||||
duration: 2500,
|
||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||
}).showToast();
|
||||
})
|
||||
.catch((err) => {
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
function deleteUser() {
|
||||
UserService.userControllerRemove(original_data.id, true)
|
||||
.then((resp) => {
|
||||
location.replace("./");
|
||||
})
|
||||
.catch((err) => {
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -63,51 +127,54 @@
|
||||
<polyline points="12 5 19 12 12 19" /></svg>
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<span class="mr-2">{user.firstname}
|
||||
{user.middlename || ''}
|
||||
{user.lastname}</span>
|
||||
<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">
|
||||
{user.firstname}
|
||||
{user.middlename || ''}
|
||||
{user.lastname}
|
||||
<span data-id="user_actions_${user.id}">
|
||||
<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"
|
||||
data-userid="${user.id}"
|
||||
onclick="user__delete_cancel()">{$_('cancel')}</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"
|
||||
data-userid="${user.id}"
|
||||
onclick="user__delete_confirm()">{$_('confirm-delete')}</button>
|
||||
<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>
|
||||
<button
|
||||
disabled={!changes_performed}
|
||||
class:opacity-50={!changes_performed}
|
||||
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>
|
||||
{original_data.firstname}
|
||||
{original_data.middlename || ''}
|
||||
{original_data.lastname}
|
||||
<span data-id="user_actions_${editable_userdata.id}">
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:DELETE')}
|
||||
{#if delete_triggered}
|
||||
<button
|
||||
on:click={deleteUser}
|
||||
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-user')}</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="mt-2 flex items-center">
|
||||
<img
|
||||
alt={$_('profile-picture')}
|
||||
class="inline-block h-20 w-20 rounded-full overflow-hidden bg-gray-100"
|
||||
src={user.profilePic} />
|
||||
<!-- <span
|
||||
class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100"><svg
|
||||
class="h-full w-full text-gray-300"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"><path
|
||||
d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg></span> -->
|
||||
src={editable_userdata.profilePic} />
|
||||
<button
|
||||
type="button"
|
||||
class="ml-5 bg-white py-2 px-3 border border-gray-300 rounded-md shadow-sm text-sm leading-4 font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">Change</button>
|
||||
@@ -165,6 +232,102 @@
|
||||
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" />
|
||||
</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">
|
||||
<label
|
||||
for="username"
|
||||
class="font-medium text-gray-700">{$_('username')}</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
placeholder={$_('username')}
|
||||
type="text"
|
||||
bind:value={editable_userdata.username}
|
||||
name="username"
|
||||
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>
|
||||
<!-- svelte-ignore a11y-no-onchange -->
|
||||
<select
|
||||
bind:value={usergroups_array}
|
||||
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>
|
||||
{#each allgroups as g}
|
||||
{#if usergroups_array.includes(g.id)}
|
||||
<option selected value={g.id}>{g.name}</option>
|
||||
{:else}
|
||||
<option value={g.id}>{g.name}</option>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="text-sm w-full">
|
||||
<span class="font-medium">Permissions</span>
|
||||
<div class="border-4 border-dashed rounded 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">
|
||||
verfügbare
|
||||
</div>
|
||||
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2">erteilte</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="flex flex-wrap -mx-1 overflow-hidden">
|
||||
{#if allpermissions.length > 0}
|
||||
<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">
|
||||
{#each allpermissions as p}
|
||||
{#if !editable_userdata.permissions.includes(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">
|
||||
{p}
|
||||
<button
|
||||
on:click={() => {
|
||||
editable_userdata.permissions.push(p);
|
||||
editable_userdata.permissions = editable_userdata.permissions;
|
||||
}}
|
||||
type="button"
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm">+</button>
|
||||
</p>
|
||||
{/if}
|
||||
{/each}
|
||||
</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">
|
||||
{#each allpermissions as p}
|
||||
{#if editable_userdata.permissions.includes(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">
|
||||
{p}
|
||||
<button
|
||||
on:click={() => {
|
||||
editable_userdata.permissions = editable_userdata.permissions.filter((obj) => obj !== p);
|
||||
}}
|
||||
type="button"
|
||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm">-</button>
|
||||
</p>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{:catch error}
|
||||
<PromiseError {error} />
|
||||
|
@@ -1,23 +1,31 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
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>
|
||||
|
||||
<section class="container p-5">
|
||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||
{$_('users')}
|
||||
<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-user')}
|
||||
</button>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER: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-user')}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
<p class="mb-8 text-lg text-gray-500">{$_('manage-admin-users')}</p>
|
||||
<UsersOverview />
|
||||
<UsersOverview bind:current_users />
|
||||
</section>
|
||||
<AddUserModal bind:modal_open />
|
||||
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:CREATE')}
|
||||
<AddUserModal bind:current_users bind:modal_open />
|
||||
{/if}
|
||||
|
@@ -1,147 +1,179 @@
|
||||
<script>
|
||||
import { _ } from "svelte-i18n";
|
||||
import Toastify from "toastify-js";
|
||||
import { UserService } from "@odit/lfk-client-js";
|
||||
const users_promise = UserService.userControllerGetAll();
|
||||
import "gridjs/dist/theme/mermaid.css";
|
||||
import { users as usersstore } from "../store.js";
|
||||
import store from "../store";
|
||||
import UsersEmptyState from "./UsersEmptyState.svelte";
|
||||
$: searchvalue = "";
|
||||
$: userscache = [];
|
||||
$: active_deletes = [];
|
||||
export let current_users=[];
|
||||
$: advanced_search = false;
|
||||
usersstore.subscribe((val) => {
|
||||
userscache = val;
|
||||
current_users=val;
|
||||
});
|
||||
users_promise.then((data) => {
|
||||
console.log(data);
|
||||
usersstore.set(data);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#await users_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">users are being loaded...</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then users}
|
||||
{#if userscache.length === 0}
|
||||
<UsersEmptyState />
|
||||
{:else}
|
||||
{#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" />
|
||||
{/if}
|
||||
<button
|
||||
on:click={() => {
|
||||
advanced_search = !advanced_search;
|
||||
}}
|
||||
type="button"
|
||||
class="w-full inline-flex 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">
|
||||
{#if advanced_search}
|
||||
toggle simple search
|
||||
{:else}toggle advanced search{/if}
|
||||
</button>
|
||||
{#if store.state.jwtinfo.userdetails.permissions.includes('USER:GET')}
|
||||
{#await users_promise}
|
||||
<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">
|
||||
Status
|
||||
</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="relative px-6 py-3">
|
||||
<span class="sr-only">Action</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
{#each users as u}
|
||||
{#if Object.values(u)
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.includes(searchvalue)}
|
||||
<tr>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
{#if u.profilePic}
|
||||
<div class="flex-shrink-0 h-10 w-10">
|
||||
<img
|
||||
class="h-10 w-10 rounded-full"
|
||||
src={u.profilePic}
|
||||
alt="" />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
||||
{u.firstname}
|
||||
{u.middlename || ''}
|
||||
{u.lastname}
|
||||
</div>
|
||||
<div class="text-sm text-gray-500">
|
||||
{u.email || u.username}
|
||||
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">users are being loaded...</p>
|
||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||
</div>
|
||||
{:then}
|
||||
{#if current_users.length === 0}
|
||||
<UsersEmptyState />
|
||||
{:else}
|
||||
{#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" />
|
||||
{/if}
|
||||
<button
|
||||
on:click={() => {
|
||||
advanced_search = !advanced_search;
|
||||
}}
|
||||
type="button"
|
||||
class="w-full inline-flex 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">
|
||||
{#if advanced_search}
|
||||
toggle simple search
|
||||
{:else}toggle advanced search{/if}
|
||||
</button>
|
||||
<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">
|
||||
Status
|
||||
</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="relative px-6 py-3">
|
||||
<span class="sr-only">Action</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
{#each current_users as u}
|
||||
{#if Object.values(u)
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.includes(searchvalue)}
|
||||
<tr data-rowid="user_{u.id}">
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<div class="flex items-center">
|
||||
{#if u.profilePic}
|
||||
<div class="flex-shrink-0 h-10 w-10">
|
||||
<img
|
||||
class="h-10 w-10 rounded-full"
|
||||
src={u.profilePic}
|
||||
alt="" />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="ml-4">
|
||||
<div
|
||||
class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
||||
{u.firstname}
|
||||
{u.middlename || ''}
|
||||
{u.lastname}
|
||||
</div>
|
||||
<div class="text-sm text-gray-500">
|
||||
{u.email || u.username}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<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>
|
||||
</td>
|
||||
<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>
|
||||
{:else}
|
||||
<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">
|
||||
{#each u.groups as g}
|
||||
<a
|
||||
href="../groups/{g.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
|
||||
{/each}
|
||||
</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) => {
|
||||
current_users=current_users.filter(obj=>obj.id!==u.id);
|
||||
})
|
||||
.catch((err) => {
|
||||
// error deleting user
|
||||
});
|
||||
}}
|
||||
tabindex="0"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Confirm
|
||||
Delete</button>
|
||||
</td>
|
||||
{:else}
|
||||
<span
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Inactive</span>
|
||||
<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>
|
||||
{#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>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
||||
{#each u.groups as g}
|
||||
<a
|
||||
href="../groups/{g.id}"
|
||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{g.name}</a>
|
||||
{/each}
|
||||
</td>
|
||||
<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>
|
||||
<span
|
||||
tabindex="0"
|
||||
href="#"
|
||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">Delete</span>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
{/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}
|
||||
{/await}
|
||||
{/if}
|
||||
|
@@ -4,17 +4,22 @@
|
||||
"about": "About",
|
||||
"action": "Action",
|
||||
"add-your-first-track": "Add your first track",
|
||||
"address": "Address",
|
||||
"application_name": "Lauf für Kaya! - Admin",
|
||||
"author": "Author",
|
||||
"browse": "Browse",
|
||||
"by": "by",
|
||||
"cancel": "Cancel",
|
||||
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
|
||||
"changelog": "Changelog",
|
||||
"close": "Close",
|
||||
"confirm-delete": "Confirm Delete",
|
||||
"contact": "Contact",
|
||||
"count_organizations": "# Organizations",
|
||||
"count_teams": "# Teams",
|
||||
"create": "Create",
|
||||
"create-a-new-track": "Create a new Track",
|
||||
"create-organization": "Create Organization",
|
||||
"create-user": "Create User",
|
||||
"credits": "Credits",
|
||||
"dashboard-greeting": "hello there",
|
||||
@@ -34,20 +39,43 @@
|
||||
"no_matching_records_found": "No matching records found",
|
||||
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
|
||||
},
|
||||
"delete-organization": "Delete Organization",
|
||||
"delete-user": "Delete User",
|
||||
"dependency_name": "Name",
|
||||
"dont-have-your-email-connected": "Don't have your email connected?",
|
||||
"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",
|
||||
"email_address_or_username": "Email / username",
|
||||
"error_on_login": "Error on login",
|
||||
"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-is-required": "First Name is required",
|
||||
"forgot_password?": "Forgot your password?",
|
||||
"general-stats": "General Stats",
|
||||
"general_promise_error": "😢 Error",
|
||||
"goback": "Go Home",
|
||||
"groups": "Groups",
|
||||
"hallo": "hello",
|
||||
"installed-version": "Installed version",
|
||||
"invalid-mail-reset": "the provided email is invalid",
|
||||
@@ -55,6 +83,7 @@
|
||||
"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.",
|
||||
"license": "License",
|
||||
"licenses-are-being-loaded": "Licenses are being loaded...",
|
||||
"log_in": "Log in",
|
||||
"log_in_to_your_account": "Log in to your account",
|
||||
"login_is_checked": "Login is being checked...",
|
||||
@@ -65,6 +94,7 @@
|
||||
"minimum-lap-time-in-s": "minimum lap time in s",
|
||||
"no-license-text-could-be-found": "No license text could be found 😢",
|
||||
"no-tracks-added-yet": "there are no tracks added yet.",
|
||||
"organizations": "Organizations",
|
||||
"orgs": "Orgs",
|
||||
"oss_credit_description": "We use a lot of open source software on these projects, and would like to thank the following projects and contributors who help make open source great!",
|
||||
"password": "Password",
|
||||
@@ -92,6 +122,9 @@
|
||||
"track-length-in-m": "Track Length in m",
|
||||
"track-name": "Track name",
|
||||
"tracks": "Tracks",
|
||||
"updating-user": "updating user...",
|
||||
"user-updated": "User updated",
|
||||
"username": "Username",
|
||||
"users": "Users",
|
||||
"valid-email-is-required": "valid email is required",
|
||||
"welcome_wavinghand": "Welcome 👋",
|
||||
|
@@ -27,6 +27,8 @@ const store = () => {
|
||||
AuthService.authControllerRefresh({ token: state.auth.refresh_token }).then((auth) => {
|
||||
console.log('got new auth');
|
||||
OpenAPI.TOKEN = auth.access_token;
|
||||
const jwtinfo = JSON.parse(atob(auth.access_token.split('.')[1]));
|
||||
state.jwtinfo = jwtinfo;
|
||||
localForage.setItem('logindata', auth);
|
||||
});
|
||||
},
|
||||
@@ -39,8 +41,8 @@ const store = () => {
|
||||
//
|
||||
state.refreshInterval = setInterval(() => {
|
||||
this.refreshAuth();
|
||||
// 4min
|
||||
}, 4 * 60000);
|
||||
// 2min
|
||||
}, 2 * 60000);
|
||||
//
|
||||
return state;
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@ module.exports = {
|
||||
purge: {
|
||||
content: [ './src/**/*.svelte' ]
|
||||
},
|
||||
darkMode: 'media',
|
||||
// darkMode: 'media',
|
||||
variants: {},
|
||||
plugins: [],
|
||||
theme: {
|
||||
|
5
versionbuilder.js
Normal file
5
versionbuilder.js
Normal 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);
|
Reference in New Issue
Block a user