WIP refactor container and queuing system (#206)

* refactor microservices to machine-learning

* Update tGithub issue template with correct task syntax

* Added microservices container

* Communicate between service based on queue system

* added dependency

* Fixed problem with having to import BullQueue into the individual service

* Added todo

* refactor server into monorepo with microservices

* refactor database and entity to library

* added simple migration

* Move migrations and database config to library

* Migration works in library

* Cosmetic change in logging message

* added user dto

* Fixed issue with testing not able to find the shared library

* Clean up library mapping path

* Added webp generator to microservices

* Update Github Action build latest

* Fixed issue NPM cannot install due to conflict witl Bull Queue

* format project with prettier

* Modified docker-compose file

* Add GH Action for Staging build:

* Fixed GH action job name

* Modified GH Action to only build & push latest when pushing to main

* Added Test 2e2 Github Action

* Added Test 2e2 Github Action

* Implemented microservice to extract exif

* Added cronjob to scan and generate webp thumbnail  at midnight

* Refactor to ireduce hit time to database when running microservices

* Added error handling to asset services that handle read file from disk

* Added video transcoding queue to process one video at a time

* Fixed loading spinner on web while loading covering the info panel

* Add mechanism to show new release announcement to web and mobile app (#209)

* Added changelog page

* Fixed issues based on PR comments

* Fixed issue with video transcoding run on the server

* Change entry point content for backward combatibility when starting up server

* Added announcement box

* Added error handling to failed silently when the app version checking is not able to make the request to GITHUB

* Added new version announcement overlay

* Update message

* Added messages

* Added logic to check and show announcement

* Add method to handle saving new version

* Added button to dimiss the acknowledge message

* Up version for deployment to the app store
This commit is contained in:
Alex
2022-06-11 16:12:06 -05:00
committed by GitHub
parent 397f8c70b4
commit a8220172f8
192 changed files with 1823 additions and 2117 deletions

131
web/package-lock.json generated
View File

@@ -13,6 +13,7 @@
"leaflet": "^1.8.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"markdown-it": "^13.0.1",
"moment": "^2.29.3",
"svelte-material-icons": "^2.0.2"
},
@@ -27,6 +28,7 @@
"@types/leaflet": "^1.7.10",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@types/markdown-it": "^12.2.3",
"@typescript-eslint/eslint-plugin": "^5.10.1",
"@typescript-eslint/parser": "^5.10.1",
"autoprefixer": "^10.4.7",
@@ -291,6 +293,12 @@
"@types/geojson": "*"
}
},
"node_modules/@types/linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==",
"dev": true
},
"node_modules/@types/lodash": {
"version": "4.14.182",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
@@ -306,6 +314,22 @@
"@types/lodash": "*"
}
},
"node_modules/@types/markdown-it": {
"version": "12.2.3",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
"dev": true,
"dependencies": {
"@types/linkify-it": "*",
"@types/mdurl": "*"
}
},
"node_modules/@types/mdurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
"integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
"dev": true
},
"node_modules/@types/node": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz",
@@ -626,8 +650,7 @@
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/array-union": {
"version": "2.1.0",
@@ -1020,6 +1043,17 @@
"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
"dev": true
},
"node_modules/entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/es6-promise": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
@@ -2078,6 +2112,14 @@
"node": ">=10"
}
},
"node_modules/linkify-it": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
"integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
"dependencies": {
"uc.micro": "^1.0.1"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@@ -2118,6 +2160,26 @@
"node": ">=12"
}
},
"node_modules/markdown-it": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
"integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
"dependencies": {
"argparse": "^2.0.1",
"entities": "~3.0.1",
"linkify-it": "^4.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -3125,6 +3187,11 @@
"node": ">=4.2.0"
}
},
"node_modules/uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -3458,6 +3525,12 @@
"@types/geojson": "*"
}
},
"@types/linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==",
"dev": true
},
"@types/lodash": {
"version": "4.14.182",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
@@ -3473,6 +3546,22 @@
"@types/lodash": "*"
}
},
"@types/markdown-it": {
"version": "12.2.3",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
"dev": true,
"requires": {
"@types/linkify-it": "*",
"@types/mdurl": "*"
}
},
"@types/mdurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
"integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
"dev": true
},
"@types/node": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz",
@@ -3673,8 +3762,7 @@
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"array-union": {
"version": "2.1.0",
@@ -3940,6 +4028,11 @@
"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
"dev": true
},
"entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="
},
"es6-promise": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
@@ -4636,6 +4729,14 @@
"integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==",
"dev": true
},
"linkify-it": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
"integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@@ -4670,6 +4771,23 @@
"sourcemap-codec": "^1.4.8"
}
},
"markdown-it": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
"integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
"requires": {
"argparse": "^2.0.1",
"entities": "~3.0.1",
"linkify-it": "^4.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
},
"merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -5318,6 +5436,11 @@
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
"dev": true
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",

View File

@@ -3,58 +3,54 @@ import * as cookie from 'cookie';
import { serverEndpoint } from '$lib/constants';
import { session } from '$app/stores';
export const handle: Handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
export const handle: Handle = async ({ event, resolve, }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
if (!cookies.session) {
return await resolve(event);
}
if (!cookies.session) {
return await resolve(event)
}
try {
const { email, isAdmin, firstName, lastName, id, accessToken } = JSON.parse(cookies.session);
try {
const { email, isAdmin, firstName, lastName, id, accessToken } = JSON.parse(cookies.session);
const res = await fetch(`${serverEndpoint}/auth/validateToken`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
const res = await fetch(`${serverEndpoint}/auth/validateToken`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`
}
})
if (res.status === 201) {
event.locals.user = {
id,
accessToken,
firstName,
lastName,
isAdmin,
email,
};
}
if (res.status === 201) {
event.locals.user = {
id,
accessToken,
firstName,
lastName,
isAdmin,
email
};
}
const response = await resolve(event);
return response;
} catch (error) {
console.log('Error parsing session', error);
return await resolve(event);
}
const response = await resolve(event);
return response;
} catch (error) {
console.log('Error parsing session', error);
return await resolve(event);
}
};
export const getSession: GetSession = async ({ locals }) => {
if (!locals.user) return {};
if (!locals.user) return {}
return {
user: {
id: locals.user.id,
accessToken: locals.user.accessToken,
firstName: locals.user.firstName,
lastName: locals.user.lastName,
isAdmin: locals.user.isAdmin,
email: locals.user.email
}
}
}
return {
user: {
id: locals.user.id,
accessToken: locals.user.accessToken,
firstName: locals.user.firstName,
lastName: locals.user.lastName,
isAdmin: locals.user.isAdmin,
email: locals.user.email,
},
};
};

View File

@@ -1,60 +1,59 @@
import { serverEndpoint } from './constants';
type ISend = {
method: string,
path: string,
data?: any,
token: string
customHeaders?: Record<string, string>,
}
method: string;
path: string;
data?: any;
token: string;
customHeaders?: Record<string, string>;
};
type IOption = {
method: string,
headers: Record<string, string>,
body: any
}
method: string;
headers: Record<string, string>;
body: any;
};
async function send({ method, path, data, token, customHeaders }: ISend) {
const opts: IOption = { method, headers: {} } as IOption;
const opts: IOption = { method, headers: {} } as IOption;
if (data) {
opts.headers['Content-Type'] = 'application/json';
opts.body = JSON.stringify(data);
}
if (data) {
opts.headers['Content-Type'] = 'application/json';
opts.body = JSON.stringify(data);
}
if (customHeaders) {
console.log(customHeaders);
// opts.headers[customHeader.$1]
}
if (customHeaders) {
console.log(customHeaders);
// opts.headers[customHeader.$1]
}
if (token) {
opts.headers['Authorization'] = `Bearer ${token}`;
}
if (token) {
opts.headers['Authorization'] = `Bearer ${token}`;
}
return fetch(`${serverEndpoint}/${path}`, opts)
.then((r) => r.text())
.then((json) => {
try {
return JSON.parse(json);
} catch (err) {
return json;
}
});
return fetch(`${serverEndpoint}/${path}`, opts)
.then((r) => r.text())
.then((json) => {
try {
return JSON.parse(json);
} catch (err) {
return json;
}
});
}
export function getRequest(path: string, token: string, customHeaders?: Record<string, string>) {
return send({ method: 'GET', path, token, customHeaders });
return send({ method: 'GET', path, token, customHeaders });
}
export function delRequest(path: string, token: string, customHeaders?: Record<string, string>) {
return send({ method: 'DELETE', path, token, customHeaders });
return send({ method: 'DELETE', path, token, customHeaders });
}
export function postRequest(path: string, data: any, token: string, customHeaders?: Record<string, string>) {
return send({ method: 'POST', path, data, token, customHeaders });
return send({ method: 'POST', path, data, token, customHeaders });
}
export function putRequest(path: string, data: any, token: string, customHeaders?: Record<string, string>) {
return send({ method: 'PUT', path, data, token, customHeaders });
}
return send({ method: 'PUT', path, data, token, customHeaders });
}

View File

@@ -67,7 +67,7 @@
</video>
{#if isVideoLoading}
<div class="absolute w-full h-full bg-black/50 flex place-items-center place-content-center">
<div class="absolute flex place-items-center place-content-center">
<LoadingSpinner />
</div>
{/if}

View File

@@ -0,0 +1,61 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { createEventDispatcher } from 'svelte';
import { page } from '$app/stores';
import FullScreenModal from './full-screen-modal.svelte';
export let localVersion: string;
export let remoteVersion: string;
const acknowledgeClickHandler = () => {
localStorage.setItem('appVersion', remoteVersion);
goto($page.url.pathname);
};
</script>
<div class="absolute top-0 left-0 w-screen h-screen">
<FullScreenModal on:clickOutside={() => console.log('Click outside')}>
<div class="max-w-[500px] z-[99999] border bg-immich-bg p-10 rounded-xl">
<p class="text-2xl ">🎉 NEW VERSION AVAILABLE 🎉</p>
<br />
<section class="max-h-[400px] overflow-y-auto">
<div class="font-thin">
Hi friend, there is a new release of <span class="font-immich-title text-immich-primary font-bold"
>IMMICH</span
>, please take your time to visit the
<span class="underline font-medium"
><a href="https://github.com/alextran1502/immich/releases/latest" target="_blank" rel="noopener noreferrer"
>release note</a
></span
>
and ensure your <code>docker-compose</code>, and <code>.env</code> setup is up-to-date to prevent any misconfigurations,
especially if you use WatchTower or any mechanism that handles updating your application automatically.
</div>
{#if remoteVersion == 'v1.11.0_17-dev'}
<div class="mt-2 font-thin">
This specific version <span class="font-medium">v1.11.0_17-dev</span> includes changes in the docker-compose
setup that added additional containters. Please make sure to update the docker-compose file, pull new images
and check your setup for the latest features and bug fixes.
</div>
{/if}
</section>
<div class="font-thin mt-4">Your friend, Alex</div>
<div class="text-xs mt-8">
<code>Local Version {localVersion}</code>
<br />
<code>Remote Version {remoteVersion}</code>
</div>
<div class="text-right mt-4">
<button
class="bg-immich-primary text-gray-50 hover:bg-immich-primary/90 py-2 px-4 rounded-lg font-medium shadow-lg transition-all"
on:click={acknowledgeClickHandler}>Acknowledge</button
>
</div>
</div>
</FullScreenModal>
</div>

View File

@@ -11,7 +11,7 @@
out:fade={{ duration: 100 }}
class="absolute w-full h-full bg-black/40 z-[100] flex place-items-center place-content-center "
>
<div class="bg-immich-bg z-[9999] rounded-md" use:clickOutside on:outclick={() => dispatch('clickOutside')}>
<div class="z-[9999]" use:clickOutside on:outclick={() => dispatch('clickOutside')}>
<slot />
</div>
</section>

View File

@@ -22,7 +22,6 @@
};
const navigateToAdmin = () => {
console.log('Navigating to admin page');
goto('/admin');
};
</script>

View File

@@ -5,6 +5,7 @@
import Cloud from 'svelte-material-icons/Cloud.svelte';
import Dns from 'svelte-material-icons/Dns.svelte';
import LoadingSpinner from './loading-spinner.svelte';
import { goto } from '$app/navigation';
type ServerInfoType = {
diskAvailable: string;
@@ -77,7 +78,11 @@
<div class="text-xs">
<p class="text-sm font-medium text-immich-primary">Server</p>
<input class="border p-2 rounded-md bg-gray-200 mt-2 text-immich-primary font-medium" value="{endpoint}" disabled="true">
<input
class="border p-2 rounded-md bg-gray-200 mt-2 text-immich-primary font-medium"
value={endpoint}
disabled={true}
/>
<div class="flex justify-items-center justify-between mt-2">
<p>Status</p>
@@ -94,4 +99,10 @@
</div>
</div>
</div>
<!-- <div>
<hr class="ml-5 my-4" />
</div>
<button class="text-xs ml-5 underline hover:cursor-pointer text-immich-primary" on:click={() => goto('/changelog')}
>Changelog</button
> -->
</div>

View File

@@ -0,0 +1,50 @@
type CheckAppVersionReponse = {
shouldShowAnnouncement: boolean;
localVersion?: string;
remoteVersion?: string;
};
type GithubRelease = {
tag_name: string;
};
export const checkAppVersion = async (): Promise<CheckAppVersionReponse> => {
const res = await fetch('https://api.github.com/repos/alextran1502/immich/releases/latest', {
headers: {
Accept: 'application/vnd.github.v3+json',
},
});
if (res.status == 200) {
const latestRelease = (await res.json()) as GithubRelease;
const appVersion = localStorage.getItem('appVersion');
if (!appVersion) {
return {
shouldShowAnnouncement: true,
remoteVersion: latestRelease.tag_name,
localVersion: 'empty',
};
}
if (appVersion != latestRelease.tag_name) {
return {
shouldShowAnnouncement: true,
remoteVersion: latestRelease.tag_name,
localVersion: appVersion,
};
}
return {
shouldShowAnnouncement: false,
remoteVersion: latestRelease.tag_name,
localVersion: appVersion,
};
} else {
return {
shouldShowAnnouncement: false,
remoteVersion: '0',
localVersion: '0',
};
}
};

View File

@@ -1,7 +1,19 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
import { checkAppVersion } from '$lib/utils/check-app-version';
import { browser } from '$app/env';
export const load: Load = async ({ url }) => ({ props: { url } });
export const load: Load = async ({ url }) => {
if (browser) {
const { shouldShowAnnouncement, localVersion, remoteVersion } = await checkAppVersion();
return { props: { url, shouldShowAnnouncement, localVersion, remoteVersion } };
} else {
return {
props: { url },
};
}
};
</script>
<script lang="ts">
@@ -10,8 +22,13 @@
import { blur } from 'svelte/transition';
import DownloadPanel from '$lib/components/asset-viewer/download-panel.svelte';
import FullScreenModal from '../lib/components/shared/full-screen-modal.svelte';
import AnnouncementBox from '../lib/components/shared/announcement-box.svelte';
export let url: string;
export let shouldShowAnnouncement: boolean;
export let localVersion: string;
export let remoteVersion: string;
</script>
<main>
@@ -19,6 +36,10 @@
<div transition:blur={{ duration: 250 }}>
<slot />
<DownloadPanel />
{#if shouldShowAnnouncement}
<AnnouncementBox {localVersion} {remoteVersion} />
{/if}
</div>
{/key}
</main>

View File

@@ -1,12 +1,11 @@
import type { RequestHandler } from '@sveltejs/kit';
import { getRequest } from '../../../../lib/api';
export const get: RequestHandler = async ({ request, locals }) => {
const allUsers = await getRequest('user?isAll=true', locals.user!.accessToken)
const allUsers = await getRequest('user?isAll=true', locals.user!.accessToken);
return {
status: 200,
body: { allUsers }
};
}
return {
status: 200,
body: { allUsers },
};
};

View File

@@ -1,63 +1,63 @@
import type { RequestHandler } from '@sveltejs/kit';
import { putRequest } from '../../../lib/api';
import * as cookie from 'cookie'
import * as cookie from 'cookie';
export const post: RequestHandler = async ({ request, locals }) => {
const form = await request.formData();
const form = await request.formData();
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const firstName = form.get('firstName')
const lastName = form.get('lastName')
if (locals.user) {
const updatedUser = await putRequest(
'user',
{
id: locals.user.id,
firstName,
lastName,
},
locals.user.accessToken,
);
if (locals.user) {
const updatedUser = await putRequest('user', {
id: locals.user.id,
firstName,
lastName
}, locals.user.accessToken)
return {
status: 200,
body: {
user: {
id: updatedUser.id,
accessToken: locals.user.accessToken,
firstName: updatedUser.firstName,
lastName: updatedUser.lastName,
isAdmin: updatedUser.isAdmin,
email: updatedUser.email,
},
success: 'Update user success',
},
headers: {
'Set-Cookie': cookie.serialize(
'session',
JSON.stringify({
id: updatedUser.id,
accessToken: locals.user.accessToken,
firstName: updatedUser.firstName,
lastName: updatedUser.lastName,
isAdmin: updatedUser.isAdmin,
email: updatedUser.email,
}),
{
path: '/',
httpOnly: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 30,
},
),
},
};
}
return {
status: 200,
body: {
user: {
id: updatedUser.id,
accessToken: locals.user.accessToken,
firstName: updatedUser.firstName,
lastName: updatedUser.lastName,
isAdmin: updatedUser.isAdmin,
email: updatedUser.email,
},
success: 'Update user success'
},
headers: {
'Set-Cookie': cookie.serialize('session', JSON.stringify(
{
id: updatedUser.id,
accessToken: locals.user.accessToken,
firstName: updatedUser.firstName,
lastName: updatedUser.lastName,
isAdmin: updatedUser.isAdmin,
email: updatedUser.email,
}), {
path: '/',
httpOnly: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 30,
})
}
}
}
return {
status: 400,
body: {
error: 'Cannot get access token from cookies'
}
}
}
return {
status: 400,
body: {
error: 'Cannot get access token from cookies',
},
};
};

View File

@@ -3,6 +3,7 @@
import type { Load } from '@sveltejs/kit';
import { getAssetsInfo } from '$lib/stores/assets';
import { checkAppVersion } from '$lib/utils/check-app-version';
export const load: Load = async ({ session }) => {
if (!session.user) {