diff --git a/admin/package.json b/admin/package.json
index d74fedc1..20ada956 100644
--- a/admin/package.json
+++ b/admin/package.json
@@ -14,6 +14,7 @@
"@radix-ui/react-toast": "^1.1.5",
"i18next": "^23.10.1",
"i18next-browser-languagedetector": "^7.2.0",
+ "lucide-react": "^0.356.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.1.0",
diff --git a/admin/pnpm-workspace.yaml b/admin/pnpm-workspace.yaml
deleted file mode 100644
index e69de29b..00000000
diff --git a/admin/public/Karla-Bold.ttf b/admin/public/Karla-Bold.ttf
new file mode 100644
index 00000000..2348e007
Binary files /dev/null and b/admin/public/Karla-Bold.ttf differ
diff --git a/admin/public/Karla-BoldItalic.ttf b/admin/public/Karla-BoldItalic.ttf
new file mode 100644
index 00000000..3c0e045e
Binary files /dev/null and b/admin/public/Karla-BoldItalic.ttf differ
diff --git a/admin/public/Karla-ExtraBold.ttf b/admin/public/Karla-ExtraBold.ttf
new file mode 100644
index 00000000..f1847119
Binary files /dev/null and b/admin/public/Karla-ExtraBold.ttf differ
diff --git a/admin/public/Karla-ExtraBoldItalic.ttf b/admin/public/Karla-ExtraBoldItalic.ttf
new file mode 100644
index 00000000..3799659c
Binary files /dev/null and b/admin/public/Karla-ExtraBoldItalic.ttf differ
diff --git a/admin/public/Karla-ExtraLight.ttf b/admin/public/Karla-ExtraLight.ttf
new file mode 100644
index 00000000..0f8642c0
Binary files /dev/null and b/admin/public/Karla-ExtraLight.ttf differ
diff --git a/admin/public/Karla-ExtraLightItalic.ttf b/admin/public/Karla-ExtraLightItalic.ttf
new file mode 100644
index 00000000..bb328e17
Binary files /dev/null and b/admin/public/Karla-ExtraLightItalic.ttf differ
diff --git a/admin/public/Karla-Italic.ttf b/admin/public/Karla-Italic.ttf
new file mode 100644
index 00000000..1853cbe4
Binary files /dev/null and b/admin/public/Karla-Italic.ttf differ
diff --git a/admin/public/Karla-Light.ttf b/admin/public/Karla-Light.ttf
new file mode 100644
index 00000000..46457ece
Binary files /dev/null and b/admin/public/Karla-Light.ttf differ
diff --git a/admin/public/Karla-LightItalic.ttf b/admin/public/Karla-LightItalic.ttf
new file mode 100644
index 00000000..3b0f01ff
Binary files /dev/null and b/admin/public/Karla-LightItalic.ttf differ
diff --git a/admin/public/Karla-Medium.ttf b/admin/public/Karla-Medium.ttf
new file mode 100644
index 00000000..9066b49c
Binary files /dev/null and b/admin/public/Karla-Medium.ttf differ
diff --git a/admin/public/Karla-MediumItalic.ttf b/admin/public/Karla-MediumItalic.ttf
new file mode 100644
index 00000000..ea953535
Binary files /dev/null and b/admin/public/Karla-MediumItalic.ttf differ
diff --git a/admin/public/Karla-Regular.ttf b/admin/public/Karla-Regular.ttf
new file mode 100644
index 00000000..c164d004
Binary files /dev/null and b/admin/public/Karla-Regular.ttf differ
diff --git a/admin/public/Karla-SemiBold.ttf b/admin/public/Karla-SemiBold.ttf
new file mode 100644
index 00000000..82e0c5ab
Binary files /dev/null and b/admin/public/Karla-SemiBold.ttf differ
diff --git a/admin/public/Karla-SemiBoldItalic.ttf b/admin/public/Karla-SemiBoldItalic.ttf
new file mode 100644
index 00000000..77c19ef6
Binary files /dev/null and b/admin/public/Karla-SemiBoldItalic.ttf differ
diff --git a/admin/src/App.tsx b/admin/src/App.tsx
index 3db45f0e..a1a1e437 100644
--- a/admin/src/App.tsx
+++ b/admin/src/App.tsx
@@ -6,6 +6,7 @@ import {NavLink, Outlet, useNavigate} from "react-router-dom";
import {useStore} from "./store/store.ts";
import {LoadingScreen} from "./utils/LoadingScreen.tsx";
import {Trans, useTranslation} from "react-i18next";
+import {Cable, Construction, Crown, NotepadText, Wrench} from "lucide-react";
const WS_URL = import.meta.env.DEV? 'http://localhost:9001' : ''
export const App = ()=> {
@@ -86,14 +87,19 @@ export const App = ()=> {
return
-
-
Etherpad
-
+
diff --git a/admin/src/components/IconButton.tsx b/admin/src/components/IconButton.tsx
new file mode 100644
index 00000000..e91f3e91
--- /dev/null
+++ b/admin/src/components/IconButton.tsx
@@ -0,0 +1,16 @@
+import {FC, ReactElement} from "react";
+
+export type IconButtonProps = {
+ icon: JSX.Element,
+ title: string|ReactElement,
+ onClick: ()=>void,
+ className?: string,
+ disabled?: boolean
+}
+
+export const IconButton:FC
= ({icon,className,onClick,title, disabled})=>{
+ return
+}
diff --git a/admin/src/components/SearchField.tsx b/admin/src/components/SearchField.tsx
new file mode 100644
index 00000000..62a965d4
--- /dev/null
+++ b/admin/src/components/SearchField.tsx
@@ -0,0 +1,14 @@
+import {ChangeEventHandler, FC} from "react";
+import {Search} from 'lucide-react'
+export type SearchFieldProps = {
+ value: string,
+ onChange: ChangeEventHandler,
+ placeholder?: string
+}
+
+export const SearchField:FC = ({onChange,value, placeholder})=>{
+ return
+
+
+
+}
diff --git a/admin/src/index.css b/admin/src/index.css
index e9683bef..087de1b1 100644
--- a/admin/src/index.css
+++ b/admin/src/index.css
@@ -1,17 +1,23 @@
:root {
--etherpad-color: #0f775b;
+ --etherpad-comp: #9C8840;
+ --etherpad-light: #99FF99;
}
-
+@font-face {
+ font-family: Karla;
+ src: url(/Karla-Regular.ttf);
+}
html, body, #root {
box-sizing: border-box;
height: 100%;
-
+ font-family: "Karla", sans-serif;
}
*, *:before, *:after {
box-sizing: inherit;
+ font-size: 16px;
}
body {
@@ -22,44 +28,111 @@ body {
}
div.menu {
- height: 100%;
- padding: 15px;
- width: 220px;
- border-right: 1px solid #ccc;
- position: fixed;
+ height: 100vh;
+ font-size: 16px;
+ font-weight: bolder;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ max-width: 20%;
+ min-width: 20%;
+}
+
+.icon-button{
+ display: flex;
+ gap: 10px;
+ background-color: var(--etherpad-color);
+ color: white;
+ border: none;
+ padding: 10px 20px;
+ border-radius: 5px;
+ cursor: pointer;
+}
+
+.icon-button svg {
+ align-self: center;
+}
+
+.icon-button span {
+ align-self: center;
+}
+
+
+div.menu span:first-child {
+ display: flex;
+ justify-content: center;
+}
+
+div.menu span:first-child svg {
+ margin-right: 10px;
+ align-self: center;
+}
+
+
+div.menu h1 {
+ font-size: 50px;
+ text-align: center;
+}
+
+.inner-menu {
+ border-radius: 0 20px 20px 0;
+ padding: 10px;
+ flex-grow: 100;
+ background-color: var(--etherpad-comp);
+ color: white;
+ height: 100vh;
}
div.menu ul {
+ color: white;
padding: 0;
}
+div.menu li a {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 20px;
+}
+
+div.menu svg {
+ align-self: center;
+}
+
div.menu li {
+ padding: 10px;
+ color: white;
list-style: none;
margin-left: 3px;
line-height: 3;
- border-top: 1px solid #ccc;
}
-div.menu li:last-child {
- border-bottom: 1px solid #ccc;
+
+div.menu li:has(.active) {
+ background-color: #9C885C ;
}
+div.menu li a {
+ color: lightgray;
+}
+
+
+
div.innerwrapper {
- padding: 15px;
- padding-left: 265px;
+ background-color: #F0F0F0;
+ overflow: auto;
+ height: 100vh;
+ flex-grow: 100;
+ padding: 20px;
}
div.innerwrapper-err {
- padding: 15px;
- padding-left: 265px;
display: none;
}
#wrapper {
+ display: flex;
background: none repeat scroll 0px 0px #FFFFFF;
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.2);
- margin: auto;
- max-width: 1150px;
min-height: 100%;/*always display a scrollbar*/
}
@@ -110,17 +183,25 @@ input {
content:'▼'
}
+
+#installed-plugins thead tr th:nth-child(3) {
+ width: 15%;
+}
+
table {
border: 1px solid #ddd;
border-radius: 3px;
border-spacing: 0;
width: 100%;
margin: 20px 0;
- position:relative; /* Allows us to position the loading indicator relative to the table */
}
-table thead tr {
- background: #eee;
+
+
+
+
+#available-plugins th:first-child, #available-plugins th:nth-child(2){
+ text-align: center;
}
td, th {
@@ -223,6 +304,7 @@ pre {
height: auto;
border-right: none;
width: auto;
+ float: left;
}
table {
@@ -484,6 +566,76 @@ pre {
}
.search-field {
- width: 50%;
- padding: 5px;
+ position: relative;
+}
+
+.search-field input {
+ border-color: transparent;
+ border-radius: 20px;
+ height: 2.5rem;
+ width: 100vh;
+ padding: 5px 5px 5px 30px;
+}
+
+.search-field input:focus {
+ outline: none;
+}
+
+.search-field svg {
+ position: absolute;
+ left: 3px;
+ bottom: -3px;
+}
+
+
+.search-field svg {
+ color: gray
+}
+
+table {
+ margin: 25px 0;
+ font-size: 0.9em;
+ font-family: sans-serif;
+ min-width: 400px;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
+}
+
+th:first-child {
+ border-top-left-radius: 10px;
+}
+
+th:last-child {
+ border-top-right-radius: 10px;
+}
+
+table thead tr {
+ font-size: 25px;
+ background-color: var(--etherpad-color);
+ color: #ffffff;
+ text-align: left;
+}
+
+table tbody tr {
+ border-bottom: 1px solid #dddddd;
+}
+
+table tr:nth-child(even) td{
+ background-color: lightgray;
+}
+
+table tr td {
+ padding: 12px 15px;
+}
+
+table tbody tr:nth-of-type(even) {
+ background-color: #f3f3f3;
+}
+
+table tbody tr:last-of-type {
+ border-bottom: 2px solid #009879;
+}
+
+table tbody tr.active-row {
+ font-weight: bold;
+ color: #009879;
}
diff --git a/admin/src/pages/HomePage.tsx b/admin/src/pages/HomePage.tsx
index c43585d0..0ea1a26d 100644
--- a/admin/src/pages/HomePage.tsx
+++ b/admin/src/pages/HomePage.tsx
@@ -3,6 +3,9 @@ import {useEffect, useMemo, useState} from "react";
import {InstalledPlugin, PluginDef, SearchParams} from "./Plugin.ts";
import {useDebounce} from "../utils/useDebounce.ts";
import {Trans, useTranslation} from "react-i18next";
+import {SearchField} from "../components/SearchField.tsx";
+import {Download, Trash} from "lucide-react";
+import {IconButton} from "../components/IconButton.tsx";
export const HomePage = () => {
@@ -128,12 +131,12 @@ export const HomePage = () => {
-
+
|
|
- |
+ |
@@ -145,10 +148,7 @@ export const HomePage = () => {
{
plugin.updatable ?
- :
-
+ : } title={} onClick={() => uninstallPlugin(plugin.name)}/>
}
@@ -158,19 +158,16 @@ export const HomePage = () => {
+ {setSearchTerm(v.target.value)}} placeholder={t('admin_plugins.available_search.placeholder')} value={searchTerm}/>
- {
- setSearchTerm(v.target.value)
- }}/>
-
-
+
|
|
|
|
- |
+ |
@@ -181,7 +178,7 @@ export const HomePage = () => {
{plugin.version} |
{plugin.time} |
-
+ } onClick={() => installPlugin(plugin.name)} title={}/>
|
})}
diff --git a/admin/src/pages/PadPage.tsx b/admin/src/pages/PadPage.tsx
index 5c11755d..abb934df 100644
--- a/admin/src/pages/PadPage.tsx
+++ b/admin/src/pages/PadPage.tsx
@@ -5,6 +5,9 @@ import {PadSearchQuery, PadSearchResult} from "../utils/PadSearch.ts";
import {useDebounce} from "../utils/useDebounce.ts";
import {determineSorting} from "../utils/sorting.ts";
import * as Dialog from "@radix-ui/react-dialog";
+import {IconButton} from "../components/IconButton.tsx";
+import {Trash2} from "lucide-react";
+import {SearchField} from "../components/SearchField.tsx";
export const PadPage = ()=>{
const settingsSocket = useStore(state=>state.settingsSocket)
@@ -98,8 +101,7 @@ export const PadPage = ()=>{
- setSearchTerm(v.target.value)}
- placeholder={t('ep_admin_pads:ep_adminpads2_search-heading')}/>
+ setSearchTerm(v.target.value)} placeholder={t('ep_admin_pads:ep_adminpads2_search-heading')}/>
@@ -144,13 +146,11 @@ export const PadPage = ()=>{
{pad.revisionNumber} |
-
-
+ }}/>
+ } title="view" onClick={()=>window.open(`/p/${pad.padName}`, '_blank')}/>
|
diff --git a/admin/src/pages/SettingsPage.tsx b/admin/src/pages/SettingsPage.tsx
index b72507c3..2706ffa3 100644
--- a/admin/src/pages/SettingsPage.tsx
+++ b/admin/src/pages/SettingsPage.tsx
@@ -1,10 +1,11 @@
import {useStore} from "../store/store.ts";
import {isJSONClean} from "../utils/utils.ts";
import {Trans} from "react-i18next";
+import {IconButton} from "../components/IconButton.tsx";
+import {RotateCw, Save} from "lucide-react";
export const SettingsPage = ()=>{
const settingsSocket = useStore(state=>state.settingsSocket)
-
const settings = useStore(state=>state.settings)
return
@@ -13,7 +14,8 @@ export const SettingsPage = ()=>{
useStore.getState().setSettings(v.target.value)
}}/>
-
-
+ }}/>
diff --git a/package.json b/package.json
index 99cb89c8..d9bdf8cd 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,9 @@
"dependencies": {
"ep_etherpad-lite": "workspace:./src"
},
+ "devDependencies": {
+ "admin": "workspace:./admin"
+ },
"engines": {
"node": ">=18.18.2",
"npm": ">=6.14.0",
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 4d8f70bb..3d3e285e 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,2 +1,3 @@
packages:
- src
+ - admin
diff --git a/src/tests/frontend-new/admin-spec/adminsettings.spec.ts b/src/tests/frontend-new/admin-spec/adminsettings.spec.ts
index ad3a0c44..adeb10f4 100644
--- a/src/tests/frontend-new/admin-spec/adminsettings.spec.ts
+++ b/src/tests/frontend-new/admin-spec/adminsettings.spec.ts
@@ -1,5 +1,6 @@
import {expect, test} from "@playwright/test";
import {loginToAdmin, restartEtherpad, saveSettings} from "../helper/adminhelper";
+import exp from "node:constants";
test.beforeEach(async ({ page })=>{
await loginToAdmin(page, 'admin', 'changeme1');