Compare commits

106 Commits

Author SHA1 Message Date
Aine
4404840b16 Merge pull request #365 from etkecc/add-etke-server-commands
Add etke server commands panel inside server status page
2025-03-05 13:04:41 +00:00
Borislav Pantaleev
ad8aa21dc2 cleanup 2025-03-05 14:53:47 +02:00
Aine
2eb0f804ee update docs 2025-03-05 14:16:18 +02:00
Aine
73028da430 add docs 2025-03-05 14:14:41 +02:00
Borislav Pantaleev
9fd7290757 Set server command manually for commands with_lock 2025-03-04 23:43:18 +02:00
Aine
f7f2b5f447 Merge branch 'main' into add-etke-server-commands 2025-03-04 22:54:00 +02:00
Aine
71d281a59f fix translations 2025-03-03 20:27:05 +02:00
Aine
9111863889 Merge pull request #368 from etkecc/dependabot/npm_and_yarn/vite-6.2.0
Bump vite from 6.1.1 to 6.2.0
2025-03-03 18:22:41 +00:00
Aine
ddfb092c65 Merge pull request #383 from etkecc/dependabot/npm_and_yarn/tanstack/react-query-5.67.1
Bump @tanstack/react-query from 5.66.9 to 5.67.1
2025-03-03 18:22:21 +00:00
dependabot[bot]
d6a7db9540 Bump @tanstack/react-query from 5.66.9 to 5.67.1
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.66.9 to 5.67.1.
- [Release notes](https://github.com/TanStack/query/releases)
- [Commits](https://github.com/TanStack/query/commits/v5.67.1/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 18:22:11 +00:00
Aine
0158250a15 Merge pull request #373 from etkecc/dependabot/npm_and_yarn/ra-language-french-5.6.2
Bump ra-language-french from 5.6.1 to 5.6.2
2025-03-03 18:22:07 +00:00
Aine
b041141816 Merge pull request #380 from etkecc/dependabot/npm_and_yarn/react-admin-5.6.2
Bump react-admin from 5.6.1 to 5.6.2
2025-03-03 18:19:57 +00:00
dependabot[bot]
02864a5625 Bump vite from 6.1.1 to 6.2.0
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.2.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 18:17:17 +00:00
Aine
7656aa88ff Merge pull request #378 from etkecc/dependabot/npm_and_yarn/eslint-config-prettier-10.0.2
Bump eslint-config-prettier from 10.0.1 to 10.0.2
2025-03-03 18:15:42 +00:00
Aine
ddf584fec5 Merge pull request #382 from etkecc/dependabot/npm_and_yarn/typescript-eslint-8.26.0
Bump typescript-eslint from 8.24.1 to 8.26.0
2025-03-03 18:15:09 +00:00
Aine
260345ce79 Merge pull request #376 from etkecc/dependabot/npm_and_yarn/types/lodash-4.17.16
Bump @types/lodash from 4.17.15 to 4.17.16
2025-03-03 18:14:45 +00:00
dependabot[bot]
1d7bb4bde9 Bump @types/lodash from 4.17.15 to 4.17.16
Bumps [@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash) from 4.17.15 to 4.17.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash)

---
updated-dependencies:
- dependency-name: "@types/lodash"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 18:14:08 +00:00
dependabot[bot]
fc320e3290 Bump typescript-eslint from 8.24.1 to 8.26.0
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.24.1 to 8.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.26.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 18:13:58 +00:00
Aine
3df050af5c Merge pull request #371 from etkecc/dependabot/npm_and_yarn/mui/material-6.4.6
Bump @mui/material from 6.4.5 to 6.4.6
2025-03-03 18:12:06 +00:00
Aine
8088e06351 Merge pull request #370 from etkecc/dependabot/npm_and_yarn/prettier-3.5.3
Bump prettier from 3.5.2 to 3.5.3
2025-03-03 18:11:44 +00:00
Aine
4683eacf1c Merge pull request #367 from etkecc/dependabot/npm_and_yarn/types/node-22.13.8
Bump @types/node from 22.13.5 to 22.13.8
2025-03-03 18:11:26 +00:00
dependabot[bot]
46db0e5b3d Bump react-admin from 5.6.1 to 5.6.2
Bumps [react-admin](https://github.com/marmelab/react-admin) from 5.6.1 to 5.6.2.
- [Release notes](https://github.com/marmelab/react-admin/releases)
- [Changelog](https://github.com/marmelab/react-admin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/marmelab/react-admin/compare/v5.6.1...v5.6.2)

---
updated-dependencies:
- dependency-name: react-admin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:46:40 +00:00
dependabot[bot]
d495fa6052 Bump eslint-config-prettier from 10.0.1 to 10.0.2
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 10.0.1 to 10.0.2.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v10.0.1...v10.0.2)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:46:21 +00:00
dependabot[bot]
04ea1c4192 Bump ra-language-french from 5.6.1 to 5.6.2
Bumps [ra-language-french](https://github.com/marmelab/react-admin) from 5.6.1 to 5.6.2.
- [Release notes](https://github.com/marmelab/react-admin/releases)
- [Changelog](https://github.com/marmelab/react-admin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/marmelab/react-admin/compare/v5.6.1...v5.6.2)

---
updated-dependencies:
- dependency-name: ra-language-french
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:45:45 +00:00
dependabot[bot]
c7e3c26819 Bump @mui/material from 6.4.5 to 6.4.6
Bumps [@mui/material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material) from 6.4.5 to 6.4.6.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v6.4.6/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.4.6/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:45:18 +00:00
dependabot[bot]
d910c7000a Bump prettier from 3.5.2 to 3.5.3
Bumps [prettier](https://github.com/prettier/prettier) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.2...3.5.3)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:45:07 +00:00
dependabot[bot]
fcff225cbd Bump @types/node from 22.13.5 to 22.13.8
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.5 to 22.13.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 07:44:16 +00:00
Borislav Pantaleev
092d8109b0 Add args param to run command 2025-02-27 21:31:58 +02:00
Borislav Pantaleev
a8f5f917dd reverse order of notifications so it's ASC 2025-02-27 20:16:30 +02:00
Borislav Pantaleev
ee7aa12fd0 burst cache for status, lock, notifications if command is running 2025-02-27 00:06:01 +02:00
Borislav Pantaleev
201da84967 Fix handling of date string that are ISO formatted 2025-02-27 00:03:01 +02:00
Borislav Pantaleev
341c9950f7 Fix notifications ASC order and proper display of time since 2025-02-26 23:25:05 +02:00
Borislav Pantaleev
233c50571b Move Server Status on top of Sidebar and fix icon background 2025-02-26 22:51:18 +02:00
Borislav Pantaleev
c080f72062 Fix tooltip for ServerStatusBadge 2025-02-25 23:08:11 +02:00
Borislav Pantaleev
79c46c2f46 Add ServerCommandsPanel to ServerStatusPage 2025-02-25 23:03:49 +02:00
Aine
0f4def5c46 Merge pull request #348 from etkecc/dependabot/npm_and_yarn/react-router-dom-7.2.0
Bump react-router-dom from 7.1.5 to 7.2.0
2025-02-24 08:24:30 +00:00
dependabot[bot]
21e90f65e6 Bump react-router-dom from 7.1.5 to 7.2.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 7.1.5 to 7.2.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.2.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 08:22:57 +00:00
Aine
a412cebe72 Merge pull request #349 from etkecc/dependabot/npm_and_yarn/react-router-7.2.0
Bump react-router from 7.1.5 to 7.2.0
2025-02-24 08:20:47 +00:00
Aine
ab179e3aa4 Merge pull request #351 from etkecc/dependabot/npm_and_yarn/ra-language-french-5.6.1
Bump ra-language-french from 5.5.3 to 5.6.1
2025-02-24 08:18:28 +00:00
Aine
75af43bb11 Merge pull request #364 from etkecc/dependabot/npm_and_yarn/mui/icons-material-6.4.5
Bump @mui/icons-material from 6.4.3 to 6.4.5
2025-02-24 08:16:56 +00:00
dependabot[bot]
a0607aa80d Bump @mui/icons-material from 6.4.3 to 6.4.5
Bumps [@mui/icons-material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material) from 6.4.3 to 6.4.5.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v6.4.5/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.4.5/packages/mui-icons-material)

---
updated-dependencies:
- dependency-name: "@mui/icons-material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 08:16:12 +00:00
dependabot[bot]
03711516da Bump react-router from 7.1.5 to 7.2.0
Bumps [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) from 7.1.5 to 7.2.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.2.0/packages/react-router)

---
updated-dependencies:
- dependency-name: react-router
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 08:15:19 +00:00
Aine
ce23c82de4 Merge pull request #357 from etkecc/dependabot/npm_and_yarn/mui/material-6.4.5
Bump @mui/material from 6.4.4 to 6.4.5
2025-02-24 08:13:46 +00:00
dependabot[bot]
9dda3b7836 Bump @mui/material from 6.4.4 to 6.4.5
Bumps [@mui/material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material) from 6.4.4 to 6.4.5.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v6.4.5/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.4.5/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 08:12:51 +00:00
Aine
45c861a530 Merge pull request #355 from etkecc/dependabot/npm_and_yarn/react-admin-5.6.1
Bump react-admin from 5.5.3 to 5.6.1
2025-02-24 08:11:05 +00:00
Aine
a1dc9379c7 Merge pull request #361 from etkecc/dependabot/npm_and_yarn/tanstack/react-query-5.66.9
Bump @tanstack/react-query from 5.66.5 to 5.66.9
2025-02-24 08:08:38 +00:00
Aine
373ba87de5 fix tests 2025-02-24 10:08:24 +02:00
Aine
21fac8576f Merge pull request #358 from etkecc/dependabot/npm_and_yarn/ts-jest-29.2.6
Bump ts-jest from 29.2.5 to 29.2.6
2025-02-24 08:01:49 +00:00
Aine
b5b39df212 Merge pull request #354 from etkecc/dependabot/npm_and_yarn/vite-6.1.1
Bump vite from 6.1.0 to 6.1.1
2025-02-24 08:01:26 +00:00
dependabot[bot]
a658856724 Bump vite from 6.1.0 to 6.1.1
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.1.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:54:09 +00:00
dependabot[bot]
dd8ade8843 Bump ts-jest from 29.2.5 to 29.2.6
Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 29.2.5 to 29.2.6.
- [Release notes](https://github.com/kulshekhar/ts-jest/releases)
- [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.2.5...v29.2.6)

---
updated-dependencies:
- dependency-name: ts-jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:53:56 +00:00
Aine
ae8f4a9722 Merge pull request #359 from etkecc/dependabot/npm_and_yarn/eslint-9.21.0
Bump eslint from 9.20.1 to 9.21.0
2025-02-24 07:52:07 +00:00
Aine
d5100b57c7 Merge pull request #360 from etkecc/dependabot/npm_and_yarn/prettier-3.5.2
Bump prettier from 3.5.1 to 3.5.2
2025-02-24 07:51:52 +00:00
Aine
dc9da147a9 Merge pull request #362 from etkecc/dependabot/npm_and_yarn/types/node-22.13.5
Bump @types/node from 22.13.4 to 22.13.5
2025-02-24 07:51:31 +00:00
dependabot[bot]
dd0668daee Bump @types/node from 22.13.4 to 22.13.5
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.4 to 22.13.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:48:35 +00:00
dependabot[bot]
3fda89462d Bump @tanstack/react-query from 5.66.5 to 5.66.9
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.66.5 to 5.66.9.
- [Release notes](https://github.com/TanStack/query/releases)
- [Commits](https://github.com/TanStack/query/commits/v5.66.9/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:48:26 +00:00
dependabot[bot]
4fa0ce111b Bump prettier from 3.5.1 to 3.5.2
Bumps [prettier](https://github.com/prettier/prettier) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.1...3.5.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:48:13 +00:00
dependabot[bot]
37c208a965 Bump eslint from 9.20.1 to 9.21.0
Bumps [eslint](https://github.com/eslint/eslint) from 9.20.1 to 9.21.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.20.1...v9.21.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:48:05 +00:00
dependabot[bot]
cbebe2d8de Bump react-admin from 5.5.3 to 5.6.1
Bumps [react-admin](https://github.com/marmelab/react-admin) from 5.5.3 to 5.6.1.
- [Release notes](https://github.com/marmelab/react-admin/releases)
- [Changelog](https://github.com/marmelab/react-admin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/marmelab/react-admin/compare/v5.5.3...v5.6.1)

---
updated-dependencies:
- dependency-name: react-admin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:47:07 +00:00
dependabot[bot]
9d43a45c5c Bump ra-language-french from 5.5.3 to 5.6.1
Bumps [ra-language-french](https://github.com/marmelab/react-admin) from 5.5.3 to 5.6.1.
- [Release notes](https://github.com/marmelab/react-admin/releases)
- [Changelog](https://github.com/marmelab/react-admin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/marmelab/react-admin/compare/v5.5.3...v5.6.1)

---
updated-dependencies:
- dependency-name: ra-language-french
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 07:46:24 +00:00
Aine
fbb578392d better UI signal when deleting server notifications from the appbar icon 2025-02-18 11:28:38 +02:00
Aine
84c14f6de2 Merge pull request #343 from etkecc/dependabot/npm_and_yarn/tanstack/react-query-5.66.5
Bump @tanstack/react-query from 5.66.0 to 5.66.5
2025-02-18 09:18:44 +00:00
Aine
b6b58e0f02 Merge pull request #345 from etkecc/dependabot/npm_and_yarn/types/react-19.0.10
Bump @types/react from 19.0.8 to 19.0.10
2025-02-18 09:14:53 +00:00
dependabot[bot]
9f764006af Bump @types/react from 19.0.8 to 19.0.10
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 19.0.8 to 19.0.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-18 08:40:23 +00:00
Aine
57ab59514c Merge pull request #347 from etkecc/dependabot/npm_and_yarn/typescript-eslint-8.24.1
Bump typescript-eslint from 8.23.0 to 8.24.1
2025-02-18 08:38:07 +00:00
dependabot[bot]
97103cdac3 Bump typescript-eslint from 8.23.0 to 8.24.1
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.23.0 to 8.24.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.24.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-18 08:33:51 +00:00
dependabot[bot]
711cf243a7 Bump @tanstack/react-query from 5.66.0 to 5.66.5
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.66.0 to 5.66.5.
- [Release notes](https://github.com/TanStack/query/releases)
- [Commits](https://github.com/TanStack/query/commits/v5.66.5/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-18 08:33:20 +00:00
Aine
565877a173 Merge pull request #334 from etkecc/dependabot/npm_and_yarn/types/react-19.0.9
Bump @types/react from 19.0.8 to 19.0.9
2025-02-18 08:32:47 +00:00
Aine
b3681ee007 Merge pull request #337 from etkecc/dependabot/npm_and_yarn/typescript-eslint/parser-8.24.0
Bump @typescript-eslint/parser from 8.23.0 to 8.24.0
2025-02-18 08:32:12 +00:00
Aine
07ec25cb5f Merge pull request #339 from etkecc/dependabot/npm_and_yarn/types/node-22.13.4
Bump @types/node from 22.13.1 to 22.13.4
2025-02-18 08:31:48 +00:00
Aine
0f80366f6c Merge pull request #340 from etkecc/dependabot/npm_and_yarn/prettier-3.5.1
Bump prettier from 3.5.0 to 3.5.1
2025-02-18 08:31:33 +00:00
Aine
32f53a6d72 Merge pull request #341 from etkecc/dependabot/npm_and_yarn/eslint-9.20.1
Bump eslint from 9.20.0 to 9.20.1
2025-02-18 08:31:17 +00:00
Aine
c22e6f0cb7 Merge pull request #342 from etkecc/dependabot/npm_and_yarn/mui/material-6.4.4
Bump @mui/material from 6.4.3 to 6.4.4
2025-02-18 08:31:02 +00:00
dependabot[bot]
672355c21c Bump @mui/material from 6.4.3 to 6.4.4
Bumps [@mui/material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-material) from 6.4.3 to 6.4.4.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v6.4.4/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.4.4/packages/mui-material)

---
updated-dependencies:
- dependency-name: "@mui/material"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:51:06 +00:00
dependabot[bot]
187052e603 Bump eslint from 9.20.0 to 9.20.1
Bumps [eslint](https://github.com/eslint/eslint) from 9.20.0 to 9.20.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.20.0...v9.20.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:50:35 +00:00
dependabot[bot]
6a1c4949d7 Bump prettier from 3.5.0 to 3.5.1
Bumps [prettier](https://github.com/prettier/prettier) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.5.0...3.5.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:50:27 +00:00
dependabot[bot]
9dc1af3dd1 Bump @types/node from 22.13.1 to 22.13.4
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.13.1 to 22.13.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:50:20 +00:00
dependabot[bot]
7c30d76f42 Bump @typescript-eslint/parser from 8.23.0 to 8.24.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.23.0 to 8.24.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.24.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:49:58 +00:00
dependabot[bot]
5842ae5d6c Bump @types/react from 19.0.8 to 19.0.9
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 19.0.8 to 19.0.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 07:49:15 +00:00
Aine
7d97ed90c9 add room ID column to the rooms table 2025-02-13 22:48:34 +02:00
Aine
e05ca5ba0b Merge pull request #329 from etkecc/dependabot/npm_and_yarn/types/react-19.0.8
Bump @types/react from 18.3.18 to 19.0.8
2025-02-10 11:38:40 +00:00
Aine
8360243e2b Merge pull request #331 from etkecc/dependabot/npm_and_yarn/eslint-9.20.0
Bump eslint from 9.19.0 to 9.20.0
2025-02-10 11:20:46 +00:00
Aine
65c1bff4b3 Merge pull request #332 from etkecc/dependabot/npm_and_yarn/prettier-3.5.0
Bump prettier from 3.4.2 to 3.5.0
2025-02-10 11:20:34 +00:00
Aine
3ef6dfdbdd Merge pull request #333 from etkecc/dependabot/npm_and_yarn/vite-6.1.0
Bump vite from 6.0.11 to 6.1.0
2025-02-10 11:19:50 +00:00
dependabot[bot]
72ba4cded3 Bump vite from 6.0.11 to 6.1.0
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.11 to 6.1.0.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/create-vite@6.1.0/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 07:17:00 +00:00
dependabot[bot]
817572c841 Bump prettier from 3.4.2 to 3.5.0
Bumps [prettier](https://github.com/prettier/prettier) from 3.4.2 to 3.5.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.4.2...3.5.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 07:16:41 +00:00
dependabot[bot]
5437fcb7ae Bump eslint from 9.19.0 to 9.20.0
Bumps [eslint](https://github.com/eslint/eslint) from 9.19.0 to 9.20.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.19.0...v9.20.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 07:16:26 +00:00
dependabot[bot]
2d785d1fd9 Bump @types/react from 18.3.18 to 19.0.8
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.18 to 19.0.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 07:16:05 +00:00
Aine
80a8d09b77 Merge pull request #328 from etkecc/161-speed-up-large-profiles
Add manual pagination to Rooms tab in User's profile
2025-02-07 21:11:22 +00:00
Borislav Pantaleev
6fe9be463c remove conosle.log 2025-02-07 22:01:31 +02:00
Aine
04e8862128 change perPage of user's rooms to 10, to keep it in sync with media 2025-02-05 12:03:33 +02:00
Borislav Pantaleev
e394193abb Fix cache key again 2025-02-04 23:24:35 +02:00
Borislav Pantaleev
0024bf78d5 remove console.log 2025-02-04 23:20:14 +02:00
Borislav Pantaleev
fd67f7d7d7 Fix caching key 2025-02-04 23:19:12 +02:00
Borislav Pantaleev
3325b0407f revert status interval 2025-02-04 23:14:24 +02:00
Borislav Pantaleev
3e9bfb605c Add manual pagination to Rooms tab in User's profile 2025-02-04 23:13:43 +02:00
Aine
95ab9587c9 Merge pull request #327 from etkecc/update-deps
Update react, react-dom, react-is, ts-jest-mock-import-meta
2025-02-04 20:30:25 +00:00
Borislav Pantaleev
b7e308fe85 Update react, react-dom, react-is, ts-jest-mock-import-meta 2025-02-04 22:06:48 +02:00
Aine
e272d0eb17 Merge pull request #323 from etkecc/dependabot/npm_and_yarn/tanstack/react-query-5.66.0
Bump @tanstack/react-query from 5.65.1 to 5.66.0
2025-02-04 08:49:00 +00:00
dependabot[bot]
1a6c6ffd10 Bump @tanstack/react-query from 5.65.1 to 5.66.0
Bumps [@tanstack/react-query](https://github.com/TanStack/query/tree/HEAD/packages/react-query) from 5.65.1 to 5.66.0.
- [Release notes](https://github.com/TanStack/query/releases)
- [Commits](https://github.com/TanStack/query/commits/v5.66.0/packages/react-query)

---
updated-dependencies:
- dependency-name: "@tanstack/react-query"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-04 08:47:01 +00:00
Aine
7f03f5423d Merge pull request #322 from etkecc/dependabot/npm_and_yarn/types/node-22.13.0
Bump @types/node from 22.12.0 to 22.13.0
2025-02-04 08:44:51 +00:00
Aine
bcc73c59f8 Merge pull request #325 from etkecc/dependabot/npm_and_yarn/mui/utils-6.4.2
Bump @mui/utils from 5.16.14 to 6.4.2
2025-02-04 08:44:21 +00:00
Aine
fcacd0f09f Merge pull request #326 from etkecc/dependabot/npm_and_yarn/ra-language-russian-5.4.3
Bump ra-language-russian from 4.14.2 to 5.4.3
2025-02-04 08:44:06 +00:00
dependabot[bot]
586dd5cdfc Bump ra-language-russian from 4.14.2 to 5.4.3
Bumps [ra-language-russian](https://github.com/Klucherev/ra-language-russian) from 4.14.2 to 5.4.3.
- [Commits](https://github.com/Klucherev/ra-language-russian/commits)

---
updated-dependencies:
- dependency-name: ra-language-russian
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-03 07:36:04 +00:00
dependabot[bot]
bbbaed259d Bump @mui/utils from 5.16.14 to 6.4.2
Bumps [@mui/utils](https://github.com/mui/material-ui/tree/HEAD/packages/mui-utils) from 5.16.14 to 6.4.2.
- [Release notes](https://github.com/mui/material-ui/releases)
- [Changelog](https://github.com/mui/material-ui/blob/v6.4.2/CHANGELOG.md)
- [Commits](https://github.com/mui/material-ui/commits/v6.4.2/packages/mui-utils)

---
updated-dependencies:
- dependency-name: "@mui/utils"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-03 07:35:58 +00:00
dependabot[bot]
db77c22f9c Bump @types/node from 22.12.0 to 22.13.0
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.12.0 to 22.13.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-03 07:34:58 +00:00
21 changed files with 1028 additions and 628 deletions

View File

@@ -118,6 +118,7 @@ The following list contains such features - they are only available for [etke.cc
* 📊 [Server Status indicator and page](https://github.com/etkecc/synapse-admin/pull/182) * 📊 [Server Status indicator and page](https://github.com/etkecc/synapse-admin/pull/182)
* 📬 [Server Notifications indicator and page](https://github.com/etkecc/synapse-admin/pull/240) * 📬 [Server Notifications indicator and page](https://github.com/etkecc/synapse-admin/pull/240)
* 🛠️ [Server Commands panel](https://github.com/etkecc/synapse-admin/pull/365)
### Development ### Development

View File

@@ -17,15 +17,15 @@
"@testing-library/react": "^16.2.0", "@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1", "@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14", "@types/jest": "^29.5.14",
"@types/lodash": "^4.17.14", "@types/lodash": "^4.17.16",
"@types/node": "^22.10.10", "@types/node": "^22.13.8",
"@types/papaparse": "^5.3.15", "@types/papaparse": "^5.3.15",
"@types/react": "^18.3.12", "@types/react": "^19.0.10",
"@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^8.19.0", "@typescript-eslint/parser": "^8.24.0",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.19.0", "eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.1", "eslint-config-prettier": "^10.0.2",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.3", "eslint-plugin-prettier": "^5.2.3",
@@ -34,13 +34,13 @@
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0", "jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3", "jest-fetch-mock": "^3.0.3",
"prettier": "^3.4.2", "prettier": "^3.5.3",
"react-test-renderer": "^18.3.1", "react-test-renderer": "^19.0.0",
"ts-jest": "^29.2.5", "ts-jest": "^29.2.6",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.7.3", "typescript": "^5.7.3",
"typescript-eslint": "^8.21.0", "typescript-eslint": "^8.26.0",
"vite": "^6.0.11", "vite": "^6.2.0",
"vite-plugin-version-mark": "^0.1.4" "vite-plugin-version-mark": "^0.1.4"
}, },
"dependencies": { "dependencies": {
@@ -48,10 +48,10 @@
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@haleos/ra-language-german": "^1.0.0", "@haleos/ra-language-german": "^1.0.0",
"@haxqer/ra-language-chinese": "^4.16.2", "@haxqer/ra-language-chinese": "^4.16.2",
"@mui/icons-material": "^6.3.1", "@mui/icons-material": "^6.4.5",
"@mui/material": "^6.4.0", "@mui/material": "^6.4.6",
"@mui/utils": "^5.16.14", "@mui/utils": "^6.4.2",
"@tanstack/react-query": "^5.64.2", "@tanstack/react-query": "^5.67.1",
"history": "^5.3.0", "history": "^5.3.0",
"jest-fixed-jsdom": "^0.0.9", "jest-fixed-jsdom": "^0.0.9",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@@ -60,15 +60,17 @@
"ra-i18n-polyglot": "^5.4.4", "ra-i18n-polyglot": "^5.4.4",
"ra-language-english": "^5.4.4", "ra-language-english": "^5.4.4",
"ra-language-farsi": "^5.1.0", "ra-language-farsi": "^5.1.0",
"ra-language-french": "^5.5.2", "ra-language-french": "^5.6.2",
"ra-language-italian": "^3.13.1", "ra-language-italian": "^3.13.1",
"ra-language-russian": "^4.14.2", "ra-language-russian": "^5.4.3",
"react": "^18.3.1", "react": "^19.0.0",
"react-admin": "^5.5.2", "react-admin": "^5.6.2",
"react-dom": "^18.3.1", "react-dom": "^19.0.0",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-is": "^18.3.1", "react-is": "^19.0.0",
"ts-jest-mock-import-meta": "^1.2.1" "ts-jest-mock-import-meta": "^1.2.1",
"react-router": "^7.2.0",
"react-router-dom": "^7.2.0"
}, },
"scripts": { "scripts": {
"start": "vite serve", "start": "vite serve",

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,4 +1,4 @@
import { CheckForApplicationUpdate, AppBar, TitlePortal, InspectorButton, Confirm, Layout, Logout, Menu, useLogout, UserMenu } from "react-admin"; import { CheckForApplicationUpdate, AppBar, TitlePortal, InspectorButton, Confirm, Layout, Logout, Menu, useLogout, UserMenu, useStore } from "react-admin";
import { LoginMethod } from "../pages/LoginPage"; import { LoginMethod } from "../pages/LoginPage";
import { useEffect, useState, Suspense } from "react"; import { useEffect, useState, Suspense } from "react";
import { Icons, DefaultIcon } from "../utils/icons"; import { Icons, DefaultIcon } from "../utils/icons";
@@ -6,6 +6,8 @@ import { MenuItem, GetConfig, ClearConfig } from "../utils/config";
import Footer from "./Footer"; import Footer from "./Footer";
import ServerStatusBadge from "./etke.cc/ServerStatusBadge"; import ServerStatusBadge from "./etke.cc/ServerStatusBadge";
import { ServerNotificationsBadge } from "./etke.cc/ServerNotificationsBadge"; import { ServerNotificationsBadge } from "./etke.cc/ServerNotificationsBadge";
import { ServerProcessResponse, ServerStatusResponse } from "../synapse/dataProvider";
import { ServerStatusStyledBadge } from "./etke.cc/ServerStatusBadge";
const AdminUserMenu = () => { const AdminUserMenu = () => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -59,9 +61,20 @@ const AdminAppBar = () => {
const AdminMenu = (props) => { const AdminMenu = (props) => {
const [menu, setMenu] = useState([] as MenuItem[]); const [menu, setMenu] = useState([] as MenuItem[]);
useEffect(() => setMenu(GetConfig().menu), []); useEffect(() => setMenu(GetConfig().menu), []);
const [serverProcess, setServerProcess] = useStore<ServerProcessResponse>("serverProcess", { command: "", locked_at: "" });
const [serverStatus, setServerStatus] = useStore<ServerStatusResponse>("serverStatus", { success: false, ok: false, host: "", results: [] });
return ( return (
<Menu {...props}> <Menu {...props}>
{menu && menu.length > 0 && <Menu.Item to="/server_status" leftIcon={
<ServerStatusStyledBadge
inSidebar={true}
command={serverProcess.command}
locked_at={serverProcess.locked_at}
isOkay={serverStatus.ok} />
}
primaryText="Server Status" />
}
<Menu.ResourceItems /> <Menu.ResourceItems />
{menu && menu.map((item, index) => { {menu && menu.map((item, index) => {
const { url, icon, label } = item; const { url, icon, label } = item;

View File

@@ -558,7 +558,7 @@ const FilePicker = () => {
</CardActions> </CardActions>
); );
const allCards: JSX.Element[] = []; const allCards: React.JSX.Element[] = [];
if (uploadCard) allCards.push(uploadCard); if (uploadCard) allCards.push(uploadCard);
if (errorCards) allCards.push(errorCards); if (errorCards) allCards.push(errorCards);
if (conflictCards) allCards.push(conflictCards); if (conflictCards) allCards.push(conflictCards);

View File

@@ -18,6 +18,10 @@ In the application bar the new monitoring icon is displayed that shows the curre
* 🟡 (yellow) - the server is up and running, but there is a command in progress (likely [maintenance](https://etke.cc/help/extras/scheduler/#maintenance)), so some temporary issues may occur - that's totally fine * 🟡 (yellow) - the server is up and running, but there is a command in progress (likely [maintenance](https://etke.cc/help/extras/scheduler/#maintenance)), so some temporary issues may occur - that's totally fine
* 🔴 (red) - there is at least 1 issue with one of the server's components * 🔴 (red) - there is at least 1 issue with one of the server's components
![Server Status icon in sidebar](../../../screenshots/etke.cc/server-status/indicator-sidebar.webp)
The same icon (and link to the [Server Status page](#server-status-page)) is displayed in the sidebar.
### Server Status page ### Server Status page
![Server Status Page](../../../screenshots/etke.cc/server-status/page.webp) ![Server Status Page](../../../screenshots/etke.cc/server-status/page.webp)
@@ -29,6 +33,8 @@ Server Status page. This page contains the following information:
* Details about the currently running command (if any) * Details about the currently running command (if any)
* Details about the server's components statuses (up/down with error details and suggested actions) by categories * Details about the server's components statuses (up/down with error details and suggested actions) by categories
This is [a Monitoring report](https://etke.cc/services/monitoring/)
### Server Notifications icon ### Server Notifications icon
![Server Notifications icon](../../../screenshots/etke.cc/server-notifications/badge.webp) ![Server Notifications icon](../../../screenshots/etke.cc/server-notifications/badge.webp)
@@ -40,3 +46,11 @@ In the application bar the new notifications icon is displayed that shows the nu
![Server Notifications Page](../../../screenshots/etke.cc/server-notifications/page.webp) ![Server Notifications Page](../../../screenshots/etke.cc/server-notifications/page.webp)
When you click on a notification from the [Server Notifications icon](#server-notifications-icon)'s list in the application bar, you will be redirected to the Server Notifications page. This page contains the full text of all the notifications you have about your server. When you click on a notification from the [Server Notifications icon](#server-notifications-icon)'s list in the application bar, you will be redirected to the Server Notifications page. This page contains the full text of all the notifications you have about your server.
### Server Commands Panel
![Server Commands Panel](../../../screenshots/etke.cc/server-commands/panel.webp)
When you open [Server Status page](#server-status-page), you will see the Server Commands panel. This panel contains all
[the commands](https://etke.cc/help/extras/scheduler/#commands) you can run on your server in 1 click. Once command is finished, you will get a notification about the
result.

View File

@@ -0,0 +1,182 @@
import { useEffect, useState } from "react";
import { Button, Loading, useDataProvider, useCreatePath, useStore } from "react-admin";
import { useAppContext } from "../../Context";
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Alert, TextField, Box } from "@mui/material";
import { PlayArrow, CheckCircle } from "@mui/icons-material";
import { Icons } from "../../utils/icons";
import { ServerCommand, ServerProcessResponse } from "../../synapse/dataProvider";
import { Link } from 'react-router-dom';
const renderIcon = (icon: string) => {
const IconComponent = Icons[icon] as React.ComponentType<any> | undefined;
return IconComponent ? <IconComponent sx={{ verticalAlign: "middle", mr: 1 }} /> : null;
}
const ServerCommandsPanel = () => {
const { etkeccAdmin } = useAppContext();
const createPath = useCreatePath();
const [ isLoading, setLoading ] = useState(true);
const [serverCommands, setServerCommands] = useState<{ [key: string]: ServerCommand }>({});
const [serverProcess, setServerProcess] = useStore<ServerProcessResponse>("serverProcess", { command: "", locked_at: "" });
const [commandIsRunning, setCommandIsRunning] = useState<boolean>(serverProcess.command !== "");
const [commandResult, setCommandResult] = useState<any[]>([]);
const dataProvider = useDataProvider();
useEffect(() => {
const fetchIsAdmin = async () => {
const serverCommandsResponse = await dataProvider.getServerCommands(etkeccAdmin);
if (serverCommandsResponse) {
const serverCommands = serverCommandsResponse;
Object.keys(serverCommandsResponse).forEach((command: string) => {
serverCommands[command].additionalArgs = "";
});
setServerCommands(serverCommands);
}
setLoading(false);
}
fetchIsAdmin();
}, []);
useEffect(() => {
if (serverProcess.command === "") {
setCommandIsRunning(false);
}
}, [serverProcess]);
const setCommandAdditionalArgs = (command: string, additionalArgs: string) => {
const updatedServerCommands = {...serverCommands};
updatedServerCommands[command].additionalArgs = additionalArgs;
setServerCommands(updatedServerCommands);
}
const runCommand = async (command: string) => {
setCommandResult([]);
setCommandIsRunning(true);
try {
const additionalArgs = serverCommands[command].additionalArgs || "";
const requestParams = additionalArgs ? { args: additionalArgs } : {};
const response = await dataProvider.runServerCommand(etkeccAdmin, command, requestParams);
if (!response.success) {
setCommandIsRunning(false);
return;
}
// Update UI with success message
const commandResults = buildCommandResultMessages(command, additionalArgs);
setCommandResult(commandResults);
// Reset the additional args field
resetCommandArgs(command);
// Update server process status
await updateServerProcessStatus(serverCommands[command]);
} catch (error) {
setCommandIsRunning(false);
}
};
const buildCommandResultMessages = (command: string, additionalArgs: string): React.ReactNode[] => {
const results: React.ReactNode[] = [];
let commandScheduledText = `Command scheduled: ${command}`;
if (additionalArgs) {
commandScheduledText += `, with additional args: ${additionalArgs}`;
}
results.push(<Box>{commandScheduledText}</Box>);
results.push(
<Box>
Expect your result in the <Link to={createPath({ resource: "server_notifications", type: "list" })}>Notifications</Link> page soon.
</Box>
);
return results;
};
const resetCommandArgs = (command: string) => {
const updatedServerCommands = {...serverCommands};
updatedServerCommands[command].additionalArgs = "";
setServerCommands(updatedServerCommands);
};
const updateServerProcessStatus = async (command: ServerCommand) => {
const commandIsLocking = command.with_lock;
const serverProcess = await dataProvider.getServerRunningProcess(etkeccAdmin, true);
if (!commandIsLocking && serverProcess.command === "") {
// if command is not locking, we simulate the "lock" mechanism so notifications will be refetched
serverProcess["command"] = command.name;
serverProcess["locked_at"] = new Date().toISOString();
}
setServerProcess({...serverProcess});
};
if (isLoading) {
return <Loading />
}
return (<>
<h2>Server Commands</h2>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 450 }} size="small" aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Command</TableCell>
<TableCell>Description</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{Object.entries(serverCommands).map(([command, { icon, args, description, additionalArgs }]) => (
<TableRow
key={command}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell scope="row">
<Box>
{renderIcon(icon)}
{command}
</Box>
</TableCell>
<TableCell>{description}</TableCell>
<TableCell>
{args && <TextField
size="small"
variant="standard"
onChange={(e) => {
setCommandAdditionalArgs(command, e.target.value);
}}
value={additionalArgs}
/>}
<Button
size="small"
variant="contained"
color="primary"
label="Run"
startIcon={<PlayArrow />}
onClick={() => { runCommand(command); }}
disabled={commandIsRunning || (args && typeof additionalArgs === 'string' && additionalArgs.length === 0)}
></Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{commandResult.length > 0 && <Alert icon={<CheckCircle fontSize="inherit" />} severity="success">
{commandResult.map((result, index) => (
<div key={index}>{result}</div>
))}
</Alert>}
</>
)
};
export default ServerCommandsPanel;

View File

@@ -5,21 +5,28 @@ import { useDataProvider, useStore } from "react-admin";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { Fragment, useEffect, useState } from "react"; import { Fragment, useEffect, useState } from "react";
import { useAppContext } from "../../Context"; import { useAppContext } from "../../Context";
import { ServerNotificationsResponse } from "../../synapse/dataProvider"; import { ServerNotificationsResponse, ServerProcessResponse } from "../../synapse/dataProvider";
import { getTimeSince } from "../../utils/date";
// 5 minutes
const SERVER_NOTIFICATIONS_INTERVAL_TIME = 300000; const SERVER_NOTIFICATIONS_INTERVAL_TIME = 300000;
const useServerNotifications = () => { const useServerNotifications = () => {
const [serverNotifications, setServerNotifications] = useStore<ServerNotificationsResponse>("serverNotifications", { notifications: [], success: false }); const [serverNotifications, setServerNotifications] = useStore<ServerNotificationsResponse>("serverNotifications", { notifications: [], success: false });
const [ serverProcess, setServerProcess ] = useStore<ServerProcessResponse>("serverProcess", { command: "", locked_at: "" });
const { command, locked_at } = serverProcess;
const { etkeccAdmin } = useAppContext(); const { etkeccAdmin } = useAppContext();
const dataProvider = useDataProvider(); const dataProvider = useDataProvider();
const { notifications, success } = serverNotifications; const { notifications, success } = serverNotifications;
const fetchNotifications = async () => { const fetchNotifications = async () => {
const notificationsResponse: ServerNotificationsResponse = await dataProvider.getServerNotifications(etkeccAdmin); const notificationsResponse: ServerNotificationsResponse = await dataProvider.getServerNotifications(etkeccAdmin, command !== "");
const serverNotifications = [...notificationsResponse.notifications];
serverNotifications.reverse();
setServerNotifications({ setServerNotifications({
...notificationsResponse, ...notificationsResponse,
notifications: notificationsResponse.notifications, notifications: serverNotifications,
success: notificationsResponse.success success: notificationsResponse.success
}); });
}; };
@@ -27,26 +34,34 @@ const useServerNotifications = () => {
const deleteServerNotifications = async () => { const deleteServerNotifications = async () => {
const deleteResponse = await dataProvider.deleteServerNotifications(etkeccAdmin); const deleteResponse = await dataProvider.deleteServerNotifications(etkeccAdmin);
if (deleteResponse.success) { if (deleteResponse.success) {
await fetchNotifications(); setServerNotifications({
notifications: [],
success: true,
});
} }
}; };
useEffect(() => { useEffect(() => {
let serverNotificationsInterval: NodeJS.Timeout; let serverNotificationsInterval: NodeJS.Timeout | null = null;
let timeoutId: NodeJS.Timeout | null = null;
if (etkeccAdmin) { if (etkeccAdmin) {
fetchNotifications(); fetchNotifications();
setTimeout(() => { timeoutId = setTimeout(() => {
// start the interval after the SERVER_NOTIFICATIONS_INTERVAL_TIME to avoid too many requests // start the interval after the SERVER_NOTIFICATIONS_INTERVAL_TIME to avoid too many requests
serverNotificationsInterval = setInterval(fetchNotifications, SERVER_NOTIFICATIONS_INTERVAL_TIME); serverNotificationsInterval = setInterval(fetchNotifications, SERVER_NOTIFICATIONS_INTERVAL_TIME);
}, SERVER_NOTIFICATIONS_INTERVAL_TIME); }, SERVER_NOTIFICATIONS_INTERVAL_TIME);
} }
return () => { return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (serverNotificationsInterval) { if (serverNotificationsInterval) {
clearInterval(serverNotificationsInterval); clearInterval(serverNotificationsInterval);
} }
} }
}, [etkeccAdmin]); }, [etkeccAdmin, command, locked_at]);
return { success, notifications, deleteServerNotifications }; return { success, notifications, deleteServerNotifications };
}; };
@@ -105,6 +120,7 @@ export const ServerNotificationsBadge = () => {
sx={{ sx={{
p: 1, p: 1,
maxHeight: "350px", maxHeight: "350px",
paddingTop: 0,
overflowY: "auto", overflowY: "auto",
minWidth: "300px", minWidth: "300px",
maxWidth: { maxWidth: {
@@ -123,7 +139,6 @@ export const ServerNotificationsBadge = () => {
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
fontWeight: "bold", fontWeight: "bold",
backgroundColor: "inherit",
}} }}
> >
<Typography variant="h6">Notifications</Typography> <Typography variant="h6">Notifications</Typography>
@@ -131,10 +146,14 @@ export const ServerNotificationsBadge = () => {
</ListSubheader> </ListSubheader>
<Divider /> <Divider />
{notifications.map((notification, index) => { {notifications.map((notification, index) => {
return (<Fragment key={notification.event_id ? notification.event_id : index }> return (<Fragment key={notification.event_id ? notification.event_id + index : index }>
<ListItem <ListItem
onClick={() => handleSeeAllNotifications()} onClick={() => handleSeeAllNotifications()}
sx={{ sx={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
overflow: "hidden",
"&:hover": { "&:hover": {
backgroundColor: "action.hover", backgroundColor: "action.hover",
cursor: "pointer" cursor: "pointer"
@@ -148,12 +167,16 @@ export const ServerNotificationsBadge = () => {
sx={{ sx={{
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap"
}} }}
dangerouslySetInnerHTML={{ __html: notification.output.split("\n")[0] }} dangerouslySetInnerHTML={{ __html: notification.output.split("\n")[0] }}
/> />
} }
/> />
<ListItemText
primary={
<Typography variant="body2" sx={{ color: theme.palette.text.secondary }}>{getTimeSince(notification.sent_at) + " ago"}</Typography>
}
/>
</ListItem> </ListItem>
<Divider /> <Divider />
</Fragment> </Fragment>

View File

@@ -4,9 +4,12 @@ import { useStore } from "react-admin"
import dataProvider, { ServerNotificationsResponse } from "../../synapse/dataProvider" import dataProvider, { ServerNotificationsResponse } from "../../synapse/dataProvider"
import { useAppContext } from "../../Context"; import { useAppContext } from "../../Context";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import { getTimeSince } from "../../utils/date";
import { Tooltip } from "@mui/material";
const DisplayTime = ({ date }: { date: string }) => { const DisplayTime = ({ date }: { date: string }) => {
const dateFromDateString = new Date(date); const dateFromDateString = new Date(date.replace(" ", "T") + "Z");
return <>{dateFromDateString.toLocaleString()}</>; return <Tooltip title={dateFromDateString.toLocaleString()}>{<span>{getTimeSince(date) + " ago"}</span>}</Tooltip>;
}; };
const ServerNotificationsPage = () => { const ServerNotificationsPage = () => {

View File

@@ -1,4 +1,4 @@
import { Avatar, Badge, Theme, Tooltip } from "@mui/material"; import { Avatar, Badge, Box, Theme, Tooltip } from "@mui/material";
import { useEffect } from "react"; import { useEffect } from "react";
import { useAppContext } from "../../Context"; import { useAppContext } from "../../Context";
import { Button, useDataProvider, useStore } from "react-admin"; import { Button, useDataProvider, useStore } from "react-admin";
@@ -52,13 +52,15 @@ const SERVER_CURRENT_PROCCESS_INTERVAL_TIME = 5 * 1000;
const useServerStatus = () => { const useServerStatus = () => {
const [serverStatus, setServerStatus] = useStore<ServerStatusResponse>("serverStatus", { ok: false, success: false, host: "", results: [] }); const [serverStatus, setServerStatus] = useStore<ServerStatusResponse>("serverStatus", { ok: false, success: false, host: "", results: [] });
const [serverProcess, setServerProcess] = useStore<ServerProcessResponse>("serverProcess", { command: "", locked_at: "" });
const { command, locked_at } = serverProcess;
const { etkeccAdmin } = useAppContext(); const { etkeccAdmin } = useAppContext();
const dataProvider = useDataProvider(); const dataProvider = useDataProvider();
const isOkay = serverStatus.ok; const isOkay = serverStatus.ok;
const successCheck = serverStatus.success; const successCheck = serverStatus.success;
const checkServerStatus = async () => { const checkServerStatus = async () => {
const serverStatus: ServerStatusResponse = await dataProvider.getServerStatus(etkeccAdmin); const serverStatus: ServerStatusResponse = await dataProvider.getServerStatus(etkeccAdmin, command !== "");
setServerStatus({ setServerStatus({
ok: serverStatus.ok, ok: serverStatus.ok,
success: serverStatus.success, success: serverStatus.success,
@@ -68,10 +70,12 @@ const useServerStatus = () => {
}; };
useEffect(() => { useEffect(() => {
let serverStatusInterval: NodeJS.Timeout; let serverStatusInterval: NodeJS.Timeout | null = null;
let timeoutId: NodeJS.Timeout | null = null;
if (etkeccAdmin) { if (etkeccAdmin) {
checkServerStatus(); checkServerStatus();
setTimeout(() => { timeoutId = setTimeout(() => {
// start the interval after 10 seconds to avoid too many requests // start the interval after 10 seconds to avoid too many requests
serverStatusInterval = setInterval(checkServerStatus, SERVER_STATUS_INTERVAL_TIME); serverStatusInterval = setInterval(checkServerStatus, SERVER_STATUS_INTERVAL_TIME);
}, 10000); }, 10000);
@@ -80,11 +84,14 @@ const useServerStatus = () => {
} }
return () => { return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (serverStatusInterval) { if (serverStatusInterval) {
clearInterval(serverStatusInterval); clearInterval(serverStatusInterval);
} }
} }
}, [etkeccAdmin]); }, [etkeccAdmin, command]);
return { isOkay, successCheck }; return { isOkay, successCheck };
}; };
@@ -96,7 +103,7 @@ const useCurrentServerProcess = () => {
const { command, locked_at } = serverProcess; const { command, locked_at } = serverProcess;
const checkServerRunningProcess = async () => { const checkServerRunningProcess = async () => {
const serverProcess: ServerProcessResponse = await dataProvider.getServerRunningProcess(etkeccAdmin); const serverProcess: ServerProcessResponse = await dataProvider.getServerRunningProcess(etkeccAdmin, command !== "");
setServerProcess({ setServerProcess({
...serverProcess, ...serverProcess,
command: serverProcess.command, command: serverProcess.command,
@@ -105,10 +112,12 @@ const useCurrentServerProcess = () => {
} }
useEffect(() => { useEffect(() => {
let serverCheckInterval: NodeJS.Timeout; let serverCheckInterval: NodeJS.Timeout | null = null;
let timeoutId: NodeJS.Timeout | null = null;
if (etkeccAdmin) { if (etkeccAdmin) {
checkServerRunningProcess(); checkServerRunningProcess();
setTimeout(() => { timeoutId = setTimeout(() => {
serverCheckInterval = setInterval(checkServerRunningProcess, SERVER_CURRENT_PROCCESS_INTERVAL_TIME); serverCheckInterval = setInterval(checkServerRunningProcess, SERVER_CURRENT_PROCCESS_INTERVAL_TIME);
}, 5000); }, 5000);
} else { } else {
@@ -116,19 +125,48 @@ const useCurrentServerProcess = () => {
} }
return () => { return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (serverCheckInterval) { if (serverCheckInterval) {
clearInterval(serverCheckInterval); clearInterval(serverCheckInterval);
} }
} }
}, [etkeccAdmin]); }, [etkeccAdmin, command]);
return { command, locked_at }; return { command, locked_at };
}; };
export const ServerStatusStyledBadge = ({ command, locked_at, isOkay, inSidebar = false }: { command: string, locked_at: string, isOkay: boolean, inSidebar: boolean }) => {
const theme = useTheme();
let badgeBackgroundColor = isOkay ? theme.palette.success.light : theme.palette.error.main;
let badgeColor = isOkay ? theme.palette.success.light : theme.palette.error.main;
if (command && locked_at) {
badgeBackgroundColor = theme.palette.warning.main;
badgeColor = theme.palette.warning.main;
}
let avatarBackgroundColor = theme.palette.mode === "dark" ? theme.palette.background.default : "#2196f3";
if (inSidebar) {
avatarBackgroundColor = theme.palette.grey[600];
}
return <StyledBadge
overlap="circular"
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
variant="dot"
backgroundColor={badgeBackgroundColor}
badgeColor={badgeColor}
>
<Avatar sx={{ height: 24, width: 24, background: avatarBackgroundColor }}>
<MonitorHeartIcon sx={{ height: 22, width: 22, color: theme.palette.common.white }} />
</Avatar>
</StyledBadge>
};
const ServerStatusBadge = () => { const ServerStatusBadge = () => {
const { isOkay, successCheck } = useServerStatus(); const { isOkay, successCheck } = useServerStatus();
const { command, locked_at } = useCurrentServerProcess(); const { command, locked_at } = useCurrentServerProcess();
const theme = useTheme();
const navigate = useNavigate(); const navigate = useNavigate();
if (!successCheck) { if (!successCheck) {
@@ -140,28 +178,16 @@ const ServerStatusBadge = () => {
}; };
let tooltipText = "Click to view Server Status"; let tooltipText = "Click to view Server Status";
let badgeBackgroundColor = isOkay ? theme.palette.success.light : theme.palette.error.main;
let badgeColor = isOkay ? theme.palette.success.light : theme.palette.error.main;
if (command && locked_at) { if (command && locked_at) {
badgeBackgroundColor = theme.palette.warning.main;
badgeColor = theme.palette.warning.main;
tooltipText = `Running: ${command}; ${tooltipText}`; tooltipText = `Running: ${command}; ${tooltipText}`;
} }
return <Button onClick={handleServerStatusClick} size="medium" sx={{ minWidth: "auto", ".MuiButton-startIcon": { m: 0 }}}> return <Button onClick={handleServerStatusClick} size="medium" sx={{ minWidth: "auto", ".MuiButton-startIcon": { m: 0 }}}>
<Tooltip title={tooltipText} sx={{ cursor: "pointer" }}> <Tooltip title={tooltipText} sx={{ cursor: "pointer" }}>
<StyledBadge <Box>
overlap="circular" <ServerStatusStyledBadge inSidebar={false} command={command || ""} locked_at={locked_at || ""} isOkay={isOkay} />
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} </Box>
variant="dot"
backgroundColor={badgeBackgroundColor}
badgeColor={badgeColor}
>
<Avatar sx={{ height: 24, width: 24, background: theme.palette.mode === "dark" ? theme.palette.background.default : "#2196f3" }}>
<MonitorHeartIcon sx={{ height: 22, width: 22, color: theme.palette.common.white }} />
</Avatar>
</StyledBadge>
</Tooltip> </Tooltip>
</Button> </Button>
}; };

View File

@@ -4,16 +4,8 @@ import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
import EngineeringIcon from '@mui/icons-material/Engineering'; import EngineeringIcon from '@mui/icons-material/Engineering';
import { ServerProcessResponse, ServerStatusComponent, ServerStatusResponse } from "../../synapse/dataProvider"; import { ServerProcessResponse, ServerStatusComponent, ServerStatusResponse } from "../../synapse/dataProvider";
import ServerCommandsPanel from "./ServerCommandsPanel";
const getTimeSince = (date: string) => { import { getTimeSince } from "../../utils/date";
const now = new Date();
const past = new Date(date);
const diffInMinutes = Math.floor((now.getTime() - past.getTime()) / (1000 * 60));
if (diffInMinutes < 1) return "a couple of seconds";
if (diffInMinutes === 1) return "1 minute";
return `${diffInMinutes} minutes`;
};
const StatusChip = ({ isOkay, size = "medium", command }: { isOkay: boolean, size?: "small" | "medium", command?: string }) => { const StatusChip = ({ isOkay, size = "medium", command }: { isOkay: boolean, size?: "small" | "medium", command?: string }) => {
let label = "OK"; let label = "OK";
@@ -102,6 +94,8 @@ const ServerStatusPage = () => {
</Stack> </Stack>
)} )}
<ServerCommandsPanel />
<Stack spacing={2} direction="row"> <Stack spacing={2} direction="row">
{Object.keys(groupedResults).map((category, idx) => ( {Object.keys(groupedResults).map((category, idx) => (
<Box key={`category_${category}`} sx={{ flex: 1 }}> <Box key={`category_${category}`} sx={{ flex: 1 }}>

View File

@@ -12,6 +12,10 @@ const fixedGermanMessages = {
clear_filters: "Alle Filter entfernen", clear_filters: "Alle Filter entfernen",
add_filter: "Filter hinzufügen", add_filter: "Filter hinzufügen",
}, },
auth: {
...formalGermanMessages.ra.auth,
email: "E-Mail",
},
action: { action: {
...formalGermanMessages.ra.action, ...formalGermanMessages.ra.action,
update_application: "Anwendung aktualisieren", update_application: "Anwendung aktualisieren",

View File

@@ -11,6 +11,10 @@ const fixedChineseMessages = {
no_filtered_results: "没有结果", no_filtered_results: "没有结果",
clear_filters: "清除所有过滤器", clear_filters: "清除所有过滤器",
}, },
auth: {
...chineseMessages.ra.auth,
email: "邮箱",
},
action: { action: {
...chineseMessages.ra.action, ...chineseMessages.ra.action,
update_application: "更新应用", update_application: "更新应用",

View File

@@ -376,6 +376,7 @@ export const RoomList = (props: ListProps) => {
<ReferenceField reference="rooms" source="id" label="resources.users.fields.avatar" link={false} sortable={false}> <ReferenceField reference="rooms" source="id" label="resources.users.fields.avatar" link={false} sortable={false}>
<AvatarField source="avatar" sx={{ height: "40px", width: "40px" }} /> <AvatarField source="avatar" sx={{ height: "40px", width: "40px" }} />
</ReferenceField> </ReferenceField>
<RaTextField source="id" label="resources.rooms.fields.room_id" sortable={false} />
<WrapperField source="encryption" sortBy="is_encrypted" label="resources.rooms.fields.encryption"> <WrapperField source="encryption" sortBy="is_encrypted" label="resources.rooms.fields.encryption">
<BooleanField <BooleanField
source="is_encrypted" source="is_encrypted"

View File

@@ -497,7 +497,7 @@ export const UserEdit = (props: EditProps) => {
target="user_id" target="user_id"
label={false} label={false}
pagination={<UserPagination />} pagination={<UserPagination />}
perPage={50} perPage={10}
sort={{ field: "created_ts", order: "DESC" }} sort={{ field: "created_ts", order: "DESC" }}
> >
<Datagrid sx={{ width: "100%" }} bulkActionButtons={<BulkDeleteButton/>}> <Datagrid sx={{ width: "100%" }} bulkActionButtons={<BulkDeleteButton/>}>
@@ -516,7 +516,7 @@ export const UserEdit = (props: EditProps) => {
</FormTab> </FormTab>
<FormTab label={translate("resources.rooms.name", { smart_count: 2 })} icon={<ViewListIcon />} path="rooms"> <FormTab label={translate("resources.rooms.name", { smart_count: 2 })} icon={<ViewListIcon />} path="rooms">
<ReferenceManyField reference="joined_rooms" target="user_id" label={false}> <ReferenceManyField reference="joined_rooms" target="user_id" label={false} perPage={10} pagination={<Pagination />}>
<Datagrid sx={{ width: "100%" }} rowClick={id => "/rooms/" + id + "/show"} bulkActionButtons={false}> <Datagrid sx={{ width: "100%" }} rowClick={id => "/rooms/" + id + "/show"} bulkActionButtons={false}>
<ReferenceField reference="rooms" source="id" label={false} link={false} sortable={false}> <ReferenceField reference="rooms" source="id" label={false} link={false} sortable={false}>
<AvatarField source="avatar" sx={{ height: "40px", width: "40px" }} /> <AvatarField source="avatar" sx={{ height: "40px", width: "40px" }} />

View File

@@ -2,7 +2,7 @@ import { AuthProvider, HttpError, Options, fetchUtils } from "react-admin";
import { MatrixError, displayError } from "../utils/error"; import { MatrixError, displayError } from "../utils/error";
import { fetchAuthenticatedMedia } from "../utils/fetchMedia"; import { fetchAuthenticatedMedia } from "../utils/fetchMedia";
import { FetchConfig, ClearConfig } from "../utils/config"; import { FetchConfig, ClearConfig, GetConfig } from "../utils/config";
import decodeURLComponent from "../utils/decodeURLComponent"; import decodeURLComponent from "../utils/decodeURLComponent";
const authProvider: AuthProvider = { const authProvider: AuthProvider = {
@@ -81,9 +81,16 @@ const authProvider: AuthProvider = {
localStorage.setItem("access_token", accessToken ? accessToken : json.access_token); localStorage.setItem("access_token", accessToken ? accessToken : json.access_token);
localStorage.setItem("device_id", json.device_id); localStorage.setItem("device_id", json.device_id);
localStorage.setItem("login_type", accessToken ? "accessToken" : "credentials"); localStorage.setItem("login_type", accessToken ? "accessToken" : "credentials");
await FetchConfig();
return Promise.resolve({redirectTo: "/"}); await FetchConfig();
const config = GetConfig();
let pageToRedirectTo = "/";
if (config && config.etkeccAdmin) {
pageToRedirectTo = "/server_status";
}
return Promise.resolve({redirectTo: pageToRedirectTo});
} catch(err) { } catch(err) {
const error = err as HttpError; const error = err as HttpError;
const errorStatus = error.status; const errorStatus = error.status;

View File

@@ -16,6 +16,8 @@ import {
import { returnMXID } from "../utils/mxid"; import { returnMXID } from "../utils/mxid";
import { MatrixError, displayError } from "../utils/error"; import { MatrixError, displayError } from "../utils/error";
const CACHED_MANY_REF: Record<string, any> = {};
// Adds the access token to all requests // Adds the access token to all requests
const jsonClient = async (url: string, options: Options = {}) => { const jsonClient = async (url: string, options: Options = {}) => {
const token = localStorage.getItem("access_token"); const token = localStorage.getItem("access_token");
@@ -298,8 +300,8 @@ export interface ServerStatusResponse {
} }
export interface ServerProcessResponse { export interface ServerProcessResponse {
locked_at?: string; locked_at: string;
command?: string; command: string;
} }
export interface ServerNotification { export interface ServerNotification {
@@ -313,6 +315,19 @@ export interface ServerNotificationsResponse {
notifications: ServerNotification[]; notifications: ServerNotification[];
} }
export interface ServerCommand {
icon: string;
name: string;
description: string;
args: boolean;
with_lock: boolean;
additionalArgs?: string;
}
export interface ServerCommandsResponse {
[command: string]: ServerCommand;
}
export interface SynapseDataProvider extends DataProvider { export interface SynapseDataProvider extends DataProvider {
deleteMedia: (params: DeleteMediaParams) => Promise<DeleteMediaResult>; deleteMedia: (params: DeleteMediaParams) => Promise<DeleteMediaResult>;
purgeRemoteMedia: (params: DeleteMediaParams) => Promise<DeleteMediaResult>; purgeRemoteMedia: (params: DeleteMediaParams) => Promise<DeleteMediaResult>;
@@ -327,6 +342,7 @@ export interface SynapseDataProvider extends DataProvider {
getServerStatus: (etkeAdminUrl: string) => Promise<ServerStatusResponse>; getServerStatus: (etkeAdminUrl: string) => Promise<ServerStatusResponse>;
getServerNotifications: (etkeAdminUrl: string) => Promise<ServerNotificationsResponse>; getServerNotifications: (etkeAdminUrl: string) => Promise<ServerNotificationsResponse>;
deleteServerNotifications: (etkeAdminUrl: string) => Promise<{ success: boolean }>; deleteServerNotifications: (etkeAdminUrl: string) => Promise<{ success: boolean }>;
getServerCommands: (etkeAdminUrl: string) => Promise<ServerCommandsResponse>;
} }
const resourceMap = { const resourceMap = {
@@ -706,18 +722,37 @@ const baseDataProvider: SynapseDataProvider = {
dir: getSearchOrder(order), dir: getSearchOrder(order),
}; };
const homeserver = localStorage.getItem("base_url"); const homeserver = localStorage.getItem("base_url");
if (!homeserver || !(resource in resourceMap)) throw Error("Homeserver not set"); if (!homeserver || !(resource in resourceMap)) throw Error("Homeserver not set");
const res = resourceMap[resource]; const res = resourceMap[resource];
const ref = res.reference(params.id); const ref = res.reference(params.id);
const endpoint_url = `${homeserver}${ref.endpoint}?${new URLSearchParams(filterUndefined(query)).toString()}`;
const endpoint_url = `${homeserver}${ref.endpoint}?${new URLSearchParams(filterUndefined(query)).toString()}`;
let CACHE_KEY = ref.endpoint;
let jsonData = [];
let total = 0;
if (CACHED_MANY_REF[CACHE_KEY]) {
jsonData = CACHED_MANY_REF[CACHE_KEY]["data"].slice(from, from + perPage);
total = CACHED_MANY_REF[CACHE_KEY]["total"];
} else {
const { json } = await jsonClient(endpoint_url); const { json } = await jsonClient(endpoint_url);
jsonData = json[res.data]
total = res.total(json, from, perPage);
if (resource === "joined_rooms") {
// cache will be applied only for joined_rooms
CACHED_MANY_REF[CACHE_KEY] = { data: jsonData, total: total };
jsonData = jsonData.slice(from, from + perPage);
}
}
return { return {
data: json[res.data].map(res.map), data: jsonData.map(res.map),
total: res.total(json, from, perPage), total: total,
}; };
}, },
@@ -973,12 +1008,17 @@ const baseDataProvider: SynapseDataProvider = {
throw error; throw error;
} }
}, },
getServerRunningProcess: async (runningProcessUrl: string): Promise<ServerProcessResponse> => { getServerRunningProcess: async (etkeAdminUrl: string, burstCache: boolean = false): Promise<ServerProcessResponse> => {
const locked_at = ""; const locked_at = "";
const command = ""; const command = "";
let serverURL = `${etkeAdminUrl}/lock`;
if (burstCache) {
serverURL += `?time=${new Date().getTime()}`;
}
try { try {
const response = await fetch(`${runningProcessUrl}/lock`, { const response = await fetch(serverURL, {
headers: { headers: {
"Authorization": `Bearer ${localStorage.getItem("access_token")}` "Authorization": `Bearer ${localStorage.getItem("access_token")}`
} }
@@ -1003,9 +1043,14 @@ const baseDataProvider: SynapseDataProvider = {
return { locked_at, command }; return { locked_at, command };
}, },
getServerStatus: async (serverStatusUrl: string): Promise<ServerStatusResponse> => { getServerStatus: async (etkeAdminUrl: string, burstCache: boolean = false): Promise<ServerStatusResponse> => {
let serverURL = `${etkeAdminUrl}/status`;
if (burstCache) {
serverURL += `?time=${new Date().getTime()}`;
}
try { try {
const response = await fetch(`${serverStatusUrl}/status`, { const response = await fetch(serverURL, {
headers: { headers: {
"Authorization": `Bearer ${localStorage.getItem("access_token")}` "Authorization": `Bearer ${localStorage.getItem("access_token")}`
} }
@@ -1027,9 +1072,14 @@ const baseDataProvider: SynapseDataProvider = {
return { success: false, ok: false, host: "", results: [] }; return { success: false, ok: false, host: "", results: [] };
}, },
getServerNotifications: async (serverNotificationsUrl: string): Promise<ServerNotificationsResponse> => { getServerNotifications: async (serverNotificationsUrl: string, burstCache: boolean = false): Promise<ServerNotificationsResponse> => {
let serverURL = `${serverNotificationsUrl}/notifications`;
if (burstCache) {
serverURL += `?time=${new Date().getTime()}`;
}
try { try {
const response = await fetch(`${serverNotificationsUrl}/notifications`, { const response = await fetch(serverURL, {
headers: { headers: {
"Authorization": `Bearer ${localStorage.getItem("access_token")}` "Authorization": `Bearer ${localStorage.getItem("access_token")}`
} }
@@ -1080,6 +1130,66 @@ const baseDataProvider: SynapseDataProvider = {
} }
return { success: false }; return { success: false };
},
getServerCommands: async (serverCommandsUrl: string) => {
try {
const response = await fetch(`${serverCommandsUrl}/commands`, {
headers: {
"Authorization": `Bearer ${localStorage.getItem("access_token")}`
}
});
if (!response.ok) {
console.error(`Error fetching server commands: ${response.status} ${response.statusText}`);
return {};
}
const status = response.status;
if (status === 200) {
const json = await response.json();
return json as ServerCommandsResponse;
}
return {};
} catch (error) {
console.error("Error fetching server commands, error");
}
return {};
},
runServerCommand: async (serverCommandsUrl: string, command: string, additionalArgs: Record<string, any> = {}) => {
const endpoint_url = `${serverCommandsUrl}/commands`;
const body = {
command: command,
...additionalArgs
}
const response = await fetch(endpoint_url, {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${localStorage.getItem("access_token")}`
}
});
if (!response.ok) {
console.error(`Error running server command: ${response.status} ${response.statusText}`);
return {
success: false,
};
}
const status = response.status;
if (status === 204) {
return {
success: true,
}
}
return {
success: false,
}
} }
}; };

View File

@@ -26,3 +26,29 @@ export const dateFormatter = (v: string | number | Date | undefined | null): str
// target format yyyy-MM-ddThh:mm // target format yyyy-MM-ddThh:mm
return `${year}-${month}-${day}T${hour}:${minute}`; return `${year}-${month}-${day}T${hour}:${minute}`;
}; };
// assuming date is in format "2025-02-26 20:52:00" where no timezone is specified
export const getTimeSince = (dateToCompare: string) => {
const nowUTC = new Date().getTime();
if (!dateToCompare.includes("Z")) {
dateToCompare = dateToCompare + "Z";
}
const past = new Date(dateToCompare);
const pastUTC = past.getTime();
const diffInMs = nowUTC - pastUTC;
const diffInMinutes = Math.floor(diffInMs / (1000 * 60));
if (diffInMinutes < 1) return "a couple of seconds";
if (diffInMinutes === 1) return "1 minute";
if (diffInMinutes < 60) return `${diffInMinutes} minutes`;
if (diffInMinutes < 120) return "1 hour";
if (diffInMinutes < 24 * 60) return `${Math.floor(diffInMinutes / 60)} hours`;
if (diffInMinutes < 48 * 60) return "1 day";
if (diffInMinutes < 7 * 24 * 60) return `${Math.floor(diffInMinutes / (24 * 60))} days`;
if (diffInMinutes < 14 * 24 * 60) return "1 week";
if (diffInMinutes < 30 * 24 * 60) return `${Math.floor(diffInMinutes / (7 * 24 * 60))} weeks`;
if (diffInMinutes < 60 * 24 * 60) return "1 month";
return `${Math.floor(diffInMinutes / (30 * 24 * 60))} months`;
};

View File

@@ -3,6 +3,11 @@ import EngineeringIcon from '@mui/icons-material/Engineering';
import HelpCenterIcon from '@mui/icons-material/HelpCenter'; import HelpCenterIcon from '@mui/icons-material/HelpCenter';
import SupportAgentIcon from '@mui/icons-material/SupportAgent'; import SupportAgentIcon from '@mui/icons-material/SupportAgent';
import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import PieChartIcon from '@mui/icons-material/PieChart';
import UpgradeIcon from '@mui/icons-material/Upgrade';
import RouterIcon from '@mui/icons-material/Router';
import PriceCheckIcon from '@mui/icons-material/PriceCheck';
import RestartAltIcon from '@mui/icons-material/RestartAlt';
export const Icons = { export const Icons = {
Announcement: AnnouncementIcon, Announcement: AnnouncementIcon,
@@ -10,6 +15,11 @@ export const Icons = {
HelpCenter: HelpCenterIcon, HelpCenter: HelpCenterIcon,
SupportAgent: SupportAgentIcon, SupportAgent: SupportAgentIcon,
Default: OpenInNewIcon, Default: OpenInNewIcon,
PieChart: PieChartIcon,
Upgrade: UpgradeIcon,
Router: RouterIcon,
PriceCheck: PriceCheckIcon,
RestartAlt: RestartAltIcon,
// Add more icons as needed // Add more icons as needed
}; };

1060
yarn.lock

File diff suppressed because it is too large Load Diff