mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 11:42:30 +03:00
UBERF-5870: Fix cache control and some minor enhancements (#4869)
UBERF-5870: Fix cache control and some minor enhancements Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
a3e3767108
commit
1847ae6aaa
@ -963,8 +963,8 @@ dependencies:
|
||||
specifier: ^1.5.1
|
||||
version: 1.5.1
|
||||
body-parser:
|
||||
specifier: ~1.19.1
|
||||
version: 1.19.2
|
||||
specifier: ^1.20.2
|
||||
version: 1.20.2
|
||||
browserslist:
|
||||
specifier: 4.21.5
|
||||
version: 4.21.5
|
||||
@ -1065,10 +1065,10 @@ dependencies:
|
||||
specifier: ^2.34.0
|
||||
version: 2.35.1(eslint@8.56.0)(svelte@4.2.11)(ts-node@10.9.2)
|
||||
express:
|
||||
specifier: ^4.17.1
|
||||
version: 4.18.2
|
||||
specifier: ^4.18.3
|
||||
version: 4.18.3
|
||||
express-fileupload:
|
||||
specifier: ^1.2.1
|
||||
specifier: ^1.4.3
|
||||
version: 1.4.3
|
||||
faker:
|
||||
specifier: ~5.5.3
|
||||
@ -4797,7 +4797,7 @@ packages:
|
||||
ejs: 3.1.9
|
||||
esbuild: 0.18.20
|
||||
esbuild-plugin-alias: 0.2.1
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
find-cache-dir: 3.3.2
|
||||
fs-extra: 11.2.0
|
||||
process: 0.11.10
|
||||
@ -4834,7 +4834,7 @@ packages:
|
||||
constants-browserify: 1.0.0
|
||||
css-loader: 6.10.0(webpack@5.90.3)
|
||||
es-module-lexer: 1.4.1
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.3.3)(webpack@5.90.3)
|
||||
fs-extra: 11.2.0
|
||||
html-webpack-plugin: 5.6.0(webpack@5.90.3)
|
||||
@ -4908,7 +4908,7 @@ packages:
|
||||
detect-indent: 6.1.0
|
||||
envinfo: 7.11.1
|
||||
execa: 5.1.1
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
find-up: 5.0.0
|
||||
fs-extra: 11.2.0
|
||||
get-npm-tarball-url: 2.1.0
|
||||
@ -5086,7 +5086,7 @@ packages:
|
||||
cli-table3: 0.6.3
|
||||
compression: 1.7.4
|
||||
detect-port: 1.5.1
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
fs-extra: 11.2.0
|
||||
globby: 11.1.0
|
||||
ip: 2.0.1
|
||||
@ -7581,24 +7581,8 @@ packages:
|
||||
readable-stream: 3.6.2
|
||||
dev: false
|
||||
|
||||
/body-parser@1.19.2:
|
||||
resolution: {integrity: sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
content-type: 1.0.5
|
||||
debug: 2.6.9
|
||||
depd: 1.1.2
|
||||
http-errors: 1.8.1
|
||||
iconv-lite: 0.4.24
|
||||
on-finished: 2.3.0
|
||||
qs: 6.9.7
|
||||
raw-body: 2.4.3
|
||||
type-is: 1.6.18
|
||||
dev: false
|
||||
|
||||
/body-parser@1.20.1:
|
||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||
/body-parser@1.20.2:
|
||||
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
@ -7610,7 +7594,7 @@ packages:
|
||||
iconv-lite: 0.4.24
|
||||
on-finished: 2.4.1
|
||||
qs: 6.11.0
|
||||
raw-body: 2.5.1
|
||||
raw-body: 2.5.2
|
||||
type-is: 1.6.18
|
||||
unpipe: 1.0.0
|
||||
dev: false
|
||||
@ -9756,13 +9740,13 @@ packages:
|
||||
busboy: 1.6.0
|
||||
dev: false
|
||||
|
||||
/express@4.18.2:
|
||||
resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
|
||||
/express@4.18.3:
|
||||
resolution: {integrity: sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
dependencies:
|
||||
accepts: 1.3.8
|
||||
array-flatten: 1.1.1
|
||||
body-parser: 1.20.1
|
||||
body-parser: 1.20.2
|
||||
content-disposition: 0.5.4
|
||||
content-type: 1.0.5
|
||||
cookie: 0.5.0
|
||||
@ -13965,11 +13949,6 @@ packages:
|
||||
side-channel: 1.0.5
|
||||
dev: false
|
||||
|
||||
/qs@6.9.7:
|
||||
resolution: {integrity: sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/query-string@7.1.3:
|
||||
resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==}
|
||||
engines: {node: '>=6'}
|
||||
@ -14017,26 +13996,6 @@ packages:
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/raw-body@2.4.3:
|
||||
resolution: {integrity: sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
http-errors: 1.8.1
|
||||
iconv-lite: 0.4.24
|
||||
unpipe: 1.0.0
|
||||
dev: false
|
||||
|
||||
/raw-body@2.5.1:
|
||||
resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
bytes: 3.1.2
|
||||
http-errors: 2.0.0
|
||||
iconv-lite: 0.4.24
|
||||
unpipe: 1.0.0
|
||||
dev: false
|
||||
|
||||
/raw-body@2.5.2:
|
||||
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -16320,7 +16279,7 @@ packages:
|
||||
compression: 1.7.4
|
||||
connect-history-api-fallback: 2.0.0
|
||||
default-gateway: 6.0.3
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
graceful-fs: 4.2.11
|
||||
html-entities: 2.4.0
|
||||
http-proxy-middleware: 2.0.6(@types/express@4.17.21)
|
||||
@ -17749,7 +17708,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/collaborator.tgz(@tiptap/pm@2.2.3)(bufferutil@4.0.8)(prosemirror-model@1.19.4)(svelte@4.2.11):
|
||||
resolution: {integrity: sha512-HvLgY+NwEKic10k5ZvdykepwdECRL2FQHFp3XfjK3Li7pvHMPzKUcTYfnBsJFSHD+jjEZ31C2wP9oRD5s5lSag==, tarball: file:projects/collaborator.tgz}
|
||||
resolution: {integrity: sha512-C2X7Yyjr7DoJenvaHw4y2eOCKejrUUI4IUXBNMWpSLvZx0L6O+6DwY2KP+N7UrKaifKX3vICt35Tyb0UA3K/dQ==, tarball: file:projects/collaborator.tgz}
|
||||
id: file:projects/collaborator.tgz
|
||||
name: '@rush-temp/collaborator'
|
||||
version: 0.0.0
|
||||
@ -17767,7 +17726,7 @@ packages:
|
||||
'@types/ws': 8.5.10
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
body-parser: 1.19.2
|
||||
body-parser: 1.20.2
|
||||
compression: 1.7.4
|
||||
cors: 2.8.5
|
||||
cross-env: 7.0.3
|
||||
@ -17777,7 +17736,7 @@ packages:
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
mongodb: 6.3.0
|
||||
prettier: 3.2.5
|
||||
@ -18317,7 +18276,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/front.tgz(esbuild@0.20.1)(svelte@4.2.11):
|
||||
resolution: {integrity: sha512-Q1CZmbbm59dl6s4oEnEHBJPIxWzMEfaNIzWRPFJnV9wc4wckFya5G525eP1BwzwtWeQic7GY9nQrUQ96qhXtuQ==, tarball: file:projects/front.tgz}
|
||||
resolution: {integrity: sha512-Oh/0YDbHbRu5+GmJeWOf9gVUaX0q31L9pdRbKq1zMt34GrzJGfSpRZO0bOxhu1Bsda3RSErk8q1rlY9EO2TCIA==, tarball: file:projects/front.tgz}
|
||||
id: file:projects/front.tgz
|
||||
name: '@rush-temp/front'
|
||||
version: 0.0.0
|
||||
@ -18334,7 +18293,7 @@ packages:
|
||||
'@types/uuid': 8.3.4
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
body-parser: 1.19.2
|
||||
body-parser: 1.20.2
|
||||
compression: 1.7.4
|
||||
cors: 2.8.5
|
||||
cross-env: 7.0.3
|
||||
@ -18343,7 +18302,7 @@ packages:
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
express-fileupload: 1.4.3
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
morgan: 1.10.0
|
||||
@ -20937,7 +20896,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/pod-front.tgz(svelte@4.2.11):
|
||||
resolution: {integrity: sha512-IbqAyQ8rYXPdITQ9dFovtQ6q89wIiUTzkhafA+K5cX65SUfeSM6iMx94gce9/LbLIWIs/v87/3ftO9Lf88gswA==, tarball: file:projects/pod-front.tgz}
|
||||
resolution: {integrity: sha512-GL3Lo44ZK+ONrZYYP192Ixh6X9/Vq3wkWvgosdYesIrmQEvvZaxPmtLZUwJRpZ5HiYAequ5u015rUIz+gjhVcQ==, tarball: file:projects/pod-front.tgz}
|
||||
id: file:projects/pod-front.tgz
|
||||
name: '@rush-temp/pod-front'
|
||||
version: 0.0.0
|
||||
@ -20953,7 +20912,7 @@ packages:
|
||||
'@types/uuid': 8.3.4
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
body-parser: 1.19.2
|
||||
body-parser: 1.20.2
|
||||
compression: 1.7.4
|
||||
cors: 2.8.5
|
||||
cross-env: 7.0.3
|
||||
@ -20963,7 +20922,7 @@ packages:
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
express-fileupload: 1.4.3
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
@ -20986,7 +20945,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/pod-server.tgz(svelte@4.2.11):
|
||||
resolution: {integrity: sha512-rRrgSjbgcgoFqfaUlCyx/b0kG4FG+ULExDOMrCX9xF8i3rWRE4H96NhEYCLRfW7Tc/lRgb9z3CEJKRGwRyVkjQ==, tarball: file:projects/pod-server.tgz}
|
||||
resolution: {integrity: sha512-RfcF42iv64hXOnQ1OMrGVXV0wUXqKOtAx0nEXbsGETtY059o/Rt+rIVimT+R8GQVaYfqyY5AR9kC91eBbWls+w==, tarball: file:projects/pod-server.tgz}
|
||||
id: file:projects/pod-server.tgz
|
||||
name: '@rush-temp/pod-server'
|
||||
version: 0.0.0
|
||||
@ -22503,7 +22462,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/server-request-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(svelte@4.2.11)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-Hh38VO8SURroi8TtBT0UfnxIqUwZjPhHf9nv3GfIpcbwkKgMr0qAWo9P6k9eEeKSRjriPcNhIM9VNOFwMsG1SQ==, tarball: file:projects/server-request-resources.tgz}
|
||||
resolution: {integrity: sha512-bVFnGUZCaRd2aKmIc8CtCuY7Jgoyt2D/ocKsObNwd+iKsIhVCaZrcYoqSn8jhqKUdWMyc2784n9mmHeNqKSTQw==, tarball: file:projects/server-request-resources.tgz}
|
||||
id: file:projects/server-request-resources.tgz
|
||||
name: '@rush-temp/server-request-resources'
|
||||
version: 0.0.0
|
||||
@ -23124,7 +23083,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/server-ws.tgz(esbuild@0.20.1)(svelte@4.2.11)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-IdOX7544NnlwLGuaLfDhiWdJkESqXP24M4fIa6Twlg0nK9d0sj6//TTD3JDrvrkkHwjFHDQjYywQjwGLYwONoQ==, tarball: file:projects/server-ws.tgz}
|
||||
resolution: {integrity: sha512-owCA424nSv/RxJNLRWaOswSHP2ztwXKL/YhULEOFPo3sqPBustc/49QDoGjMFk/1aV3XEH4y4cPsl4xNsxqssg==, tarball: file:projects/server-ws.tgz}
|
||||
id: file:projects/server-ws.tgz
|
||||
name: '@rush-temp/server-ws'
|
||||
version: 0.0.0
|
||||
@ -23145,7 +23104,7 @@ packages:
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
express: 4.18.2
|
||||
express: 4.18.3
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
prettier-plugin-svelte: 3.2.1(prettier@3.2.5)(svelte@4.2.11)
|
||||
|
@ -539,7 +539,12 @@ export function isCollectionAttr (hierarchy: Hierarchy, key: KeyedAttribute): bo
|
||||
* @public
|
||||
*/
|
||||
export function decodeTokenPayload (token: string): any {
|
||||
return JSON.parse(atob(token.split('.')[1]))
|
||||
try {
|
||||
return JSON.parse(atob(token.split('.')[1]))
|
||||
} catch (err: any) {
|
||||
console.error(err)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function isAdminUser (): boolean {
|
||||
|
@ -16,8 +16,15 @@
|
||||
<script lang="ts">
|
||||
import { LoginInfo, Workspace } from '@hcengineering/login'
|
||||
import { OK, Severity, Status } from '@hcengineering/platform'
|
||||
import presentation, { NavLink } from '@hcengineering/presentation'
|
||||
import { Button, Label, Scroller, deviceOptionsStore as deviceInfo, setMetadataLocalStorage } from '@hcengineering/ui'
|
||||
import presentation, { NavLink, isAdminUser } from '@hcengineering/presentation'
|
||||
import {
|
||||
Button,
|
||||
Label,
|
||||
Scroller,
|
||||
SearchEdit,
|
||||
deviceOptionsStore as deviceInfo,
|
||||
setMetadataLocalStorage
|
||||
} from '@hcengineering/ui'
|
||||
import { onMount } from 'svelte'
|
||||
import login from '../plugin'
|
||||
import { getAccount, getHref, getWorkspaces, goTo, navigateToWorkspace, selectWorkspace } from '../utils'
|
||||
@ -84,6 +91,9 @@
|
||||
throw err
|
||||
}
|
||||
}
|
||||
$: isAdmin = isAdminUser()
|
||||
|
||||
let search: string = ''
|
||||
</script>
|
||||
|
||||
<form class="container" style:padding={$deviceInfo.docWidth <= 480 ? '1.25rem' : '5rem'}>
|
||||
@ -95,16 +105,32 @@
|
||||
<div class="status">
|
||||
<StatusControl {status} />
|
||||
</div>
|
||||
{#if isAdmin}
|
||||
<div class="ml-2 mr-2 mb-2 flex-grow">
|
||||
<SearchEdit bind:value={search} width={'100%'} />
|
||||
</div>
|
||||
{/if}
|
||||
{#await _getWorkspaces() then}
|
||||
<Scroller padding={'.125rem 0'}>
|
||||
<div class="form">
|
||||
{#each workspaces as workspace}
|
||||
{#each workspaces.filter((it) => search === '' || (it.workspaceName?.includes(search) ?? false) || it.workspace.includes(search)) as workspace}
|
||||
{@const wsName = workspace.workspaceName ?? workspace.workspace}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="workspace flex-center fs-title cursor-pointer focused-button bordered form-row"
|
||||
on:click={() => select(workspace.workspace)}
|
||||
>
|
||||
{workspace.workspaceName ?? workspace.workspace}
|
||||
<div class="flex flex-col flex-grow">
|
||||
<span class="label overflow-label flex-center">
|
||||
{wsName}
|
||||
</span>
|
||||
{#if isAdmin && wsName !== workspace.workspace}
|
||||
<span class="text-xs flex-center">
|
||||
{workspace.workspace}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{#if workspaces.length === 0 && account?.confirmed === true}
|
||||
|
@ -203,7 +203,8 @@ export async function getWorkspaces (): Promise<Workspace[]> {
|
||||
if (endpoint !== undefined) {
|
||||
return [
|
||||
{
|
||||
workspace: DEV_WORKSPACE
|
||||
workspace: DEV_WORKSPACE,
|
||||
workspaceId: DEV_WORKSPACE
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ export const loginId = 'login' as Plugin
|
||||
* @public
|
||||
*/
|
||||
export interface Workspace {
|
||||
workspace: string //
|
||||
workspace: string // workspace Url
|
||||
workspaceName?: string // A company name
|
||||
workspaceId: string // A unique identifier for the workspace
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,23 +14,27 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import login, { Workspace } from '@hcengineering/login'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { getMetadata, getResource } from '@hcengineering/platform'
|
||||
import contact from '@hcengineering/contact'
|
||||
import {
|
||||
Icon,
|
||||
IconCheck,
|
||||
Loading,
|
||||
Location,
|
||||
SearchEdit,
|
||||
closePopup,
|
||||
fetchMetadataLocalStorage,
|
||||
getCurrentLocation,
|
||||
Loading,
|
||||
Location,
|
||||
locationStorageKeyId,
|
||||
locationToUrl,
|
||||
navigate,
|
||||
resolvedLocationStore,
|
||||
setMetadataLocalStorage,
|
||||
IconCheck,
|
||||
locationStorageKeyId
|
||||
ticker
|
||||
} from '@hcengineering/ui'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
import { onMount } from 'svelte'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { workspacesStore } from '../utils'
|
||||
import presentation, { isAdminUser } from '@hcengineering/presentation'
|
||||
// import Drag from './icons/Drag.svelte'
|
||||
|
||||
onMount(() => {
|
||||
@ -89,15 +93,56 @@
|
||||
ev.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
$: isAdmin = isAdminUser()
|
||||
|
||||
let search: string = ''
|
||||
|
||||
const _endpoint: string = fetchMetadataLocalStorage(login.metadata.LoginEndpoint) ?? ''
|
||||
const token: string = getMetadata(presentation.metadata.Token) ?? ''
|
||||
|
||||
let endpoint = _endpoint.replace(/^ws/g, 'http')
|
||||
if (endpoint.endsWith('/')) {
|
||||
endpoint = endpoint.substring(0, endpoint.length - 1)
|
||||
}
|
||||
|
||||
let data: any
|
||||
onDestroy(
|
||||
ticker.subscribe(() => {
|
||||
void fetch(endpoint + `/api/v1/statistics?token=${token}`, {})
|
||||
.then(async (json) => {
|
||||
data = await json.json()
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
$: activeSessions =
|
||||
(data?.statistics?.activeSessions as Record<
|
||||
string,
|
||||
Array<{
|
||||
userId: string
|
||||
data?: Record<string, any>
|
||||
}>
|
||||
>) ?? {}
|
||||
</script>
|
||||
|
||||
{#if $workspacesStore.length}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="antiPopup" on:keydown={keyDown}>
|
||||
<div class="ap-space x2" />
|
||||
{#if isAdmin}
|
||||
<div class="ml-2 mr-2 mb-2 flex-grow">
|
||||
<SearchEdit bind:value={search} width={'100%'} />
|
||||
</div>
|
||||
{/if}
|
||||
<div class="ap-scroll">
|
||||
<div class="ap-box">
|
||||
{#each $workspacesStore as ws, i}
|
||||
{#each $workspacesStore.filter((it) => search === '' || (it.workspaceName?.includes(search) ?? false) || it.workspace.includes(search)) as ws, i}
|
||||
{@const wsName = ws.workspaceName ?? ws.workspace}
|
||||
{@const _activeSession = activeSessions[ws.workspaceId]}
|
||||
<a
|
||||
class="stealth"
|
||||
href={getWorkspaceLink(ws)}
|
||||
@ -108,6 +153,7 @@
|
||||
<button
|
||||
bind:this={btns[i]}
|
||||
class="ap-menuItem flex-row-center flex-grow"
|
||||
class:active={isAdmin && (_activeSession?.length ?? 0) > 0}
|
||||
class:hover={btns[i] === activeElement}
|
||||
on:mousemove={() => {
|
||||
focusTarget(btns[i])
|
||||
@ -116,7 +162,24 @@
|
||||
<!-- <div class="drag"><Drag size={'small'} /></div> -->
|
||||
<!-- <div class="logo empty" /> -->
|
||||
<!-- <div class="flex-col flex-grow"> -->
|
||||
<span class="label overflow-label flex-grow">{ws.workspaceName ?? ws.workspace}</span>
|
||||
<div class="flex-col flex-grow">
|
||||
<span class="label overflow-label flex-grow">
|
||||
{wsName}
|
||||
</span>
|
||||
{#if isAdmin && wsName !== ws.workspace}
|
||||
<span class="text-xs">
|
||||
({ws.workspace})
|
||||
</span>
|
||||
{/if}
|
||||
{#if isAdmin && (_activeSession?.length ?? 0) > 0}
|
||||
<span class="text-xs flex-row-center">
|
||||
<div class="mr-1">
|
||||
<Icon icon={contact.icon.Person} size={'x-small'} />
|
||||
</div>
|
||||
{_activeSession?.length ?? 0}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- <span class="description overflow-label">Description</span> -->
|
||||
<!-- </div> -->
|
||||
<div class="ap-check">
|
||||
@ -134,3 +197,9 @@
|
||||
{:else}
|
||||
<div class="antiPopup"><Loading /></div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.active {
|
||||
background-color: var(--theme-inbox-people-counter-bgcolor);
|
||||
}
|
||||
</style>
|
||||
|
@ -19,6 +19,7 @@
|
||||
import { ObjectPresenter } from '@hcengineering/view-resources'
|
||||
import { onDestroy } from 'svelte'
|
||||
import MetricsInfo from './statistics/MetricsInfo.svelte'
|
||||
import { workspacesStore } from '../utils'
|
||||
|
||||
const _endpoint: string = fetchMetadataLocalStorage(login.metadata.LoginEndpoint) ?? ''
|
||||
const token: string = getMetadata(presentation.metadata.Token) ?? ''
|
||||
@ -166,6 +167,7 @@
|
||||
{:else if selectedTab === 'users'}
|
||||
<div class="flex-column p-3 h-full" style:overflow="auto">
|
||||
{#each Object.entries(activeSessions) as act}
|
||||
{@const wsInstance = $workspacesStore.find((it) => it.workspaceId === act[0])}
|
||||
{@const totalFind = act[1].reduce((it, itm) => itm.current.find + it, 0)}
|
||||
{@const totalTx = act[1].reduce((it, itm) => itm.current.tx + it, 0)}
|
||||
{@const employeeGroups = Array.from(new Set(act[1].map((it) => it.userId)))}
|
||||
@ -173,7 +175,7 @@
|
||||
<Expandable contentColor expanded={false} expandable={true} bordered>
|
||||
<svelte:fragment slot="title">
|
||||
<div class="fs-title">
|
||||
Workspace: {act[0]}: {act[1].length} current 5 mins => {totalFind}/{totalTx}
|
||||
Workspace: {wsInstance?.workspaceName ?? act[0]}: {act[1].length} current 5 mins => {totalFind}/{totalTx}
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<div class="flex-col">
|
||||
|
@ -60,15 +60,15 @@
|
||||
"@hcengineering/front": "^0.6.0",
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"express": "^4.18.3",
|
||||
"express-fileupload": "^1.4.3",
|
||||
"uuid": "^8.3.2",
|
||||
"cors": "^2.8.5",
|
||||
"@hcengineering/elastic": "^0.6.0",
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/server-token": "^0.6.7",
|
||||
"@hcengineering/attachment": "^0.6.9",
|
||||
"body-parser": "~1.19.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"compression": "~1.7.4",
|
||||
"sharp": "~0.32.0"
|
||||
}
|
||||
|
@ -896,7 +896,7 @@ export async function getInviteLink (
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ClientWorkspaceInfo = Omit<Workspace, '_id' | 'accounts' | 'workspaceUrl'>
|
||||
export type ClientWorkspaceInfo = Omit<Workspace, '_id' | 'accounts' | 'workspaceUrl'> & { workspaceId: string }
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -905,7 +905,7 @@ export type WorkspaceInfo = Omit<Workspace, '_id' | 'accounts'>
|
||||
|
||||
function mapToClientWorkspace (ws: Workspace): ClientWorkspaceInfo {
|
||||
const { _id, accounts, ...data } = ws
|
||||
return { ...data, workspace: ws.workspaceUrl ?? ws.workspace }
|
||||
return { ...data, workspace: ws.workspaceUrl ?? ws.workspace, workspaceId: ws.workspace }
|
||||
}
|
||||
|
||||
function trimWorkspaceInfo (ws: Workspace): WorkspaceInfo {
|
||||
|
@ -69,8 +69,8 @@
|
||||
"mongodb": "^6.3.0",
|
||||
"yjs": "^13.5.52",
|
||||
"y-prosemirror": "^1.2.1",
|
||||
"express": "^4.17.1",
|
||||
"body-parser": "~1.19.1",
|
||||
"express": "^4.18.3",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"compression": "~1.7.4",
|
||||
"ws": "^8.10.0"
|
||||
|
@ -46,15 +46,15 @@
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"express": "^4.18.3",
|
||||
"express-fileupload": "^1.4.3",
|
||||
"uuid": "^8.3.2",
|
||||
"cors": "^2.8.5",
|
||||
"@hcengineering/elastic": "^0.6.0",
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/server-token": "^0.6.7",
|
||||
"@hcengineering/attachment": "^0.6.9",
|
||||
"body-parser": "~1.19.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"compression": "~1.7.4",
|
||||
"sharp": "~0.32.0",
|
||||
"@hcengineering/minio": "^0.6.0",
|
||||
|
@ -23,10 +23,15 @@ import cors from 'cors'
|
||||
import express, { Response } from 'express'
|
||||
import fileUpload, { UploadedFile } from 'express-fileupload'
|
||||
import https from 'https'
|
||||
import morgan from 'morgan'
|
||||
import { join, resolve } from 'path'
|
||||
import { cwd } from 'process'
|
||||
import sharp from 'sharp'
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import morgan from 'morgan'
|
||||
import { preConditions } from './utils'
|
||||
|
||||
const cacheControlValue = 'public, max-age=365d'
|
||||
const cacheControlMaxAge = '365d'
|
||||
|
||||
async function minioUpload (minio: MinioService, workspace: WorkspaceId, file: UploadedFile): Promise<string> {
|
||||
const id = uuid()
|
||||
@ -103,15 +108,41 @@ async function getFileRange (
|
||||
}
|
||||
}
|
||||
|
||||
async function getFile (client: MinioService, workspace: WorkspaceId, uuid: string, res: Response): Promise<void> {
|
||||
async function getFile (
|
||||
client: MinioService,
|
||||
workspace: WorkspaceId,
|
||||
uuid: string,
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
const stat = await client.stat(workspace, uuid)
|
||||
|
||||
const etag = stat.etag
|
||||
|
||||
if (
|
||||
preConditions.IfNoneMatch(req.headers, { etag }) === 'notModified' ||
|
||||
preConditions.IfMatch(req.headers, { etag }) === 'notModified' ||
|
||||
preConditions.IfModifiedSince(req.headers, { lastModified: stat.lastModified }) === 'notModified'
|
||||
) {
|
||||
// Matched, return not modified
|
||||
res.statusCode = 304
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
if (preConditions.IfUnmodifiedSince(req.headers, { lastModified: stat.lastModified }) === 'failed') {
|
||||
// Send 412 (Precondition Failed)
|
||||
res.statusCode = 412
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const dataStream = await client.get(workspace, uuid)
|
||||
res.writeHead(200, {
|
||||
'Content-Type': stat.metaData['content-type'],
|
||||
Etag: stat.etag,
|
||||
'Last-Modified': stat.lastModified.toISOString()
|
||||
'Last-Modified': stat.lastModified.toISOString(),
|
||||
'Cache-Control': cacheControlValue
|
||||
})
|
||||
|
||||
dataStream.on('data', function (chunk) {
|
||||
@ -182,9 +213,7 @@ export function start (
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
app.get('/config.json', async (req, res) => {
|
||||
res.status(200)
|
||||
res.set('Cache-Control', 'no-cache')
|
||||
res.json({
|
||||
const data = {
|
||||
ACCOUNTS_URL: config.accountsUrl,
|
||||
UPLOAD_URL: config.uploadUrl,
|
||||
MODEL_VERSION: config.modelVersion,
|
||||
@ -199,19 +228,19 @@ export function start (
|
||||
DEFAULT_LANGUAGE: config.defaultLanguage,
|
||||
LAST_NAME_FIRST: config.lastNameFirst,
|
||||
...(extraConfig ?? {})
|
||||
})
|
||||
}
|
||||
res.set('Cache-Control', cacheControlValue)
|
||||
res.status(200)
|
||||
res.json(data)
|
||||
})
|
||||
|
||||
const dist = resolve(process.env.PUBLIC_DIR ?? __dirname, 'dist')
|
||||
const dist = resolve(process.env.PUBLIC_DIR ?? cwd(), 'dist')
|
||||
console.log('serving static files from', dist)
|
||||
app.use(
|
||||
express.static(dist, {
|
||||
maxAge: '7d',
|
||||
setHeaders (res, path) {
|
||||
if (path.includes('index.html')) {
|
||||
res.setHeader('Cache-Control', 'public, max-age=0')
|
||||
}
|
||||
}
|
||||
maxAge: '365d',
|
||||
etag: true,
|
||||
lastModified: true
|
||||
})
|
||||
)
|
||||
|
||||
@ -275,7 +304,7 @@ export function start (
|
||||
if (range !== undefined) {
|
||||
await getFileRange(range, config.minio, payload.workspace, uuid, res)
|
||||
} else {
|
||||
await getFile(config.minio, payload.workspace, uuid, res)
|
||||
await getFile(config.minio, payload.workspace, uuid, req, res)
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error?.code === 'NoSuchKey' || error?.code === 'NotFound') {
|
||||
@ -527,8 +556,11 @@ export function start (
|
||||
})
|
||||
|
||||
app.get('*', function (request, response) {
|
||||
response.setHeader('Cache-Control', 'max-age=0')
|
||||
response.sendFile(join(dist, 'index.html'))
|
||||
response.sendFile(join(dist, 'index.html'), {
|
||||
maxAge: cacheControlMaxAge,
|
||||
etag: true,
|
||||
lastModified: true
|
||||
})
|
||||
})
|
||||
|
||||
const server = app.listen(port)
|
||||
|
83
server/front/src/utils.ts
Normal file
83
server/front/src/utils.ts
Normal file
@ -0,0 +1,83 @@
|
||||
export const ETagSupport = {
|
||||
isWeak (etag: string): boolean {
|
||||
return etag.startsWith('W/"')
|
||||
},
|
||||
|
||||
isStrong (etag: string): boolean {
|
||||
return etag.startsWith('"')
|
||||
},
|
||||
|
||||
opaqueTag (etag: string): string {
|
||||
if (this.isWeak(etag)) {
|
||||
return etag.substring(2)
|
||||
}
|
||||
|
||||
return etag
|
||||
},
|
||||
weakMatch (a: string, b: string): boolean {
|
||||
return this.opaqueTag(a) === this.opaqueTag(b)
|
||||
},
|
||||
|
||||
strongMatch (a: string, b: string): boolean {
|
||||
return this.isStrong(a) && this.isStrong(b) && a === b
|
||||
}
|
||||
}
|
||||
|
||||
function toList (value: string): string[] {
|
||||
return value.split(',').map((s) => s.trim())
|
||||
}
|
||||
|
||||
export const preConditions = {
|
||||
IfMatch: (headers: Request['headers'], state: { etag: string }): 'fetch' | 'notModified' => {
|
||||
const header = (headers as any)['if-match']
|
||||
if (header == null) {
|
||||
return 'fetch'
|
||||
}
|
||||
if (header === '*') {
|
||||
return 'fetch'
|
||||
}
|
||||
return toList(header).some((etag) => ETagSupport.strongMatch(etag, state.etag)) ? 'notModified' : 'fetch'
|
||||
},
|
||||
IfNoneMatch: (headers: Request['headers'], state: { etag: string }): 'fetch' | 'notModified' => {
|
||||
const header = (headers as any)['if-none-match']
|
||||
if (header == null) {
|
||||
return 'fetch'
|
||||
}
|
||||
|
||||
if (header === '*') {
|
||||
return 'fetch'
|
||||
} else {
|
||||
return toList(header).some((etag) => ETagSupport.weakMatch(etag, state.etag)) ? 'notModified' : 'fetch'
|
||||
}
|
||||
},
|
||||
IfModifiedSince: (headers: Request['headers'], state: { lastModified: Date }): 'fetch' | 'notModified' => {
|
||||
if ((headers as any)['if-none-match'] != null) {
|
||||
return 'fetch'
|
||||
}
|
||||
const header = (headers as any)['if-modified-since']
|
||||
if (header == null) {
|
||||
return 'fetch'
|
||||
}
|
||||
|
||||
const date = Date.parse(header)
|
||||
if (isNaN(date)) {
|
||||
return 'fetch'
|
||||
}
|
||||
return state.lastModified.getTime() <= date ? 'notModified' : 'fetch'
|
||||
},
|
||||
IfUnmodifiedSince: (headers: Request['headers'], state: { lastModified: Date }): 'fetch' | 'failed' => {
|
||||
if ((headers as any)['if-match'] != null) {
|
||||
return 'fetch'
|
||||
}
|
||||
const header = (headers as any)['if-unmodified-since']
|
||||
if (header == null) {
|
||||
return 'fetch'
|
||||
}
|
||||
|
||||
const date = Date.parse(header)
|
||||
if (isNaN(date)) {
|
||||
return 'fetch'
|
||||
}
|
||||
return state.lastModified.getTime() > date ? 'failed' : 'fetch'
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@
|
||||
"@hcengineering/server-token": "^0.6.7",
|
||||
"@hcengineering/rpc": "^0.6.1",
|
||||
"bufferutil": "^4.0.7",
|
||||
"express": "^4.17.1",
|
||||
"express": "^4.18.3",
|
||||
"compression": "~1.7.4",
|
||||
"cors": "^2.8.5"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user