fix(admin): Fixed updating plugins (#6705)

This commit is contained in:
SamTV12345 2024-10-10 18:15:48 +02:00 committed by GitHub
parent f61a3b6c5a
commit 0b26405201
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 32 deletions

View file

@ -95,7 +95,9 @@ export const App = () => {
<h1>Etherpad</h1> <h1>Etherpad</h1>
</span> </span>
<ul onClick={()=>{ <ul onClick={()=>{
setSidebarOpen(false) if (window.innerWidth < 768) {
setSidebarOpen(false)
}
}}> }}>
<li><NavLink to="/plugins"><Cable/><Trans i18nKey="admin_plugins"/></NavLink></li> <li><NavLink to="/plugins"><Cable/><Trans i18nKey="admin_plugins"/></NavLink></li>
<li><NavLink to={"/settings"}><Wrench/><Trans i18nKey="admin_settings"/></NavLink></li> <li><NavLink to={"/settings"}><Wrench/><Trans i18nKey="admin_settings"/></NavLink></li>

View file

@ -4,7 +4,7 @@ import {InstalledPlugin, PluginDef, SearchParams} from "./Plugin.ts";
import {useDebounce} from "../utils/useDebounce.ts"; import {useDebounce} from "../utils/useDebounce.ts";
import {Trans, useTranslation} from "react-i18next"; import {Trans, useTranslation} from "react-i18next";
import {SearchField} from "../components/SearchField.tsx"; import {SearchField} from "../components/SearchField.tsx";
import {Download, Trash} from "lucide-react"; import {ArrowUpFromDot, Download, Trash} from "lucide-react";
import {IconButton} from "../components/IconButton.tsx"; import {IconButton} from "../components/IconButton.tsx";
import {determineSorting} from "../utils/sorting.ts"; import {determineSorting} from "../utils/sorting.ts";
@ -12,7 +12,8 @@ import {determineSorting} from "../utils/sorting.ts";
export const HomePage = () => { export const HomePage = () => {
const pluginsSocket = useStore(state=>state.pluginsSocket) const pluginsSocket = useStore(state=>state.pluginsSocket)
const [plugins,setPlugins] = useState<PluginDef[]>([]) const [plugins,setPlugins] = useState<PluginDef[]>([])
const [installedPlugins, setInstalledPlugins] = useState<InstalledPlugin[]>([]) const installedPlugins = useStore(state=>state.installedPlugins)
const setInstalledPlugins = useStore(state=>state.setInstalledPlugins)
const [searchParams, setSearchParams] = useState<SearchParams>({ const [searchParams, setSearchParams] = useState<SearchParams>({
offset: 0, offset: 0,
limit: 99999, limit: 99999,
@ -49,7 +50,7 @@ export const HomePage = () => {
}, [plugins, searchParams]) }, [plugins, searchParams])
const sortedInstalledPlugins = useMemo(()=>{ const sortedInstalledPlugins = useMemo(()=>{
return installedPlugins.sort((a, b)=>{ return useStore.getState().installedPlugins.sort((a, b)=>{
if(a.name < b.name){ if(a.name < b.name){
return -1 return -1
@ -78,17 +79,16 @@ export const HomePage = () => {
}) })
pluginsSocket.on('results:updatable', (data) => { pluginsSocket.on('results:updatable', (data) => {
data.updatable.forEach((pluginName: string) => { const newInstalledPlugins = useStore.getState().installedPlugins.map(plugin => {
setInstalledPlugins(installedPlugins.map(plugin => { if (data.updatable.includes(plugin.name)) {
if (plugin.name === pluginName) { return {
return { ...plugin,
...plugin, updatable: true
updatable: true }
} }
} return plugin
return plugin })
})) setInstalledPlugins(newInstalledPlugins)
})
}) })
pluginsSocket.on('finished:install', () => { pluginsSocket.on('finished:install', () => {
@ -159,6 +159,7 @@ export const HomePage = () => {
}) })
}, 500, [searchTerm]) }, 500, [searchTerm])
return <div> return <div>
<h1><Trans i18nKey="admin_plugins"/></h1> <h1><Trans i18nKey="admin_plugins"/></h1>
@ -180,7 +181,7 @@ export const HomePage = () => {
<td> <td>
{ {
plugin.updatable ? plugin.updatable ?
<button onClick={() => installPlugin(plugin.name)}>Update</button> <IconButton onClick={() => installPlugin(plugin.name)} icon={<ArrowUpFromDot/>} title="Update"></IconButton>
: <IconButton disabled={plugin.name == "ep_etherpad-lite"} icon={<Trash/>} title={<Trans i18nKey="admin_plugins.installed_uninstall.value"/>} onClick={() => uninstallPlugin(plugin.name)}/> : <IconButton disabled={plugin.name == "ep_etherpad-lite"} icon={<Trash/>} title={<Trans i18nKey="admin_plugins.installed_uninstall.value"/>} onClick={() => uninstallPlugin(plugin.name)}/>
} }
</td> </td>

View file

@ -1,6 +1,7 @@
import {create} from "zustand"; import {create} from "zustand";
import {Socket} from "socket.io-client"; import {Socket} from "socket.io-client";
import {PadSearchResult} from "../utils/PadSearch.ts"; import {PadSearchResult} from "../utils/PadSearch.ts";
import {InstalledPlugin} from "../pages/Plugin.ts";
type ToastState = { type ToastState = {
description?:string, description?:string,
@ -22,7 +23,9 @@ type StoreState = {
toastState: ToastState, toastState: ToastState,
setToastState: (val: ToastState)=>void, setToastState: (val: ToastState)=>void,
pads: PadSearchResult|undefined, pads: PadSearchResult|undefined,
setPads: (pads: PadSearchResult)=>void setPads: (pads: PadSearchResult)=>void,
installedPlugins: InstalledPlugin[],
setInstalledPlugins: (plugins: InstalledPlugin[])=>void
} }
@ -43,5 +46,7 @@ export const useStore = create<StoreState>()((set) => ({
success: false success: false
}, },
pads: undefined, pads: undefined,
setPads: (pads)=>set({pads}) setPads: (pads)=>set({pads}),
installedPlugins: [],
setInstalledPlugins: (plugins)=>set({installedPlugins: plugins})
})); }));

View file

@ -6,10 +6,10 @@ import {QueryType} from "../../types/QueryType";
import {getAvailablePlugins, install, search, uninstall} from "../../../static/js/pluginfw/installer"; import {getAvailablePlugins, install, search, uninstall} from "../../../static/js/pluginfw/installer";
import {PackageData} from "../../types/PackageInfo"; import {PackageData} from "../../types/PackageInfo";
const pluginDefs = require('../../../static/js/pluginfw/plugin_defs');
import semver from 'semver'; import semver from 'semver';
import log4js from 'log4js'; import log4js from 'log4js';
const pluginDefs = require('../../../static/js/pluginfw/plugin_defs');
const logger = log4js.getLogger('adminPlugins'); const logger = log4js.getLogger('adminPlugins');
@ -20,10 +20,28 @@ exports.socketio = (hookName:string, args:ArgsExpressType, cb:Function) => {
const {session: {user: {is_admin: isAdmin} = {}} = {}} = socket.conn.request; const {session: {user: {is_admin: isAdmin} = {}} = {}} = socket.conn.request;
if (!isAdmin) return; if (!isAdmin) return;
socket.on('getInstalled', (query:string) => { const checkPluginForUpdates = async () => {
const results = await getAvailablePlugins(/* maxCacheAge:*/ 60 * 10);
return Object.keys(pluginDefs.plugins).filter((plugin) => {
if (!results[plugin]) return false;
const latestVersion = results[plugin].version;
const currentVersion = pluginDefs.plugins[plugin].package.version;
return semver.gt(latestVersion, currentVersion);
})
}
socket.on('getInstalled', async (query: string) => {
// send currently installed plugins // send currently installed plugins
const installed = const installed =
Object.keys(pluginDefs.plugins).map((plugin) => pluginDefs.plugins[plugin].package); Object.keys(pluginDefs.plugins).map((plugin) => pluginDefs.plugins[plugin].package);
const updatable = await checkPluginForUpdates();
installed.forEach((plugin) => {
plugin.updatable = updatable.includes(plugin.name);
})
socket.emit('results:installed', {installed}); socket.emit('results:installed', {installed});
}); });
@ -31,16 +49,7 @@ exports.socketio = (hookName:string, args:ArgsExpressType, cb:Function) => {
socket.on('checkUpdates', async () => { socket.on('checkUpdates', async () => {
// Check plugins for updates // Check plugins for updates
try { try {
const results = await getAvailablePlugins(/* maxCacheAge:*/ 60 * 10); const updatable = checkPluginForUpdates();
const updatable = Object.keys(pluginDefs.plugins).filter((plugin) => {
if (!results[plugin]) return false;
const latestVersion = results[plugin].version;
const currentVersion = pluginDefs.plugins[plugin].package.version;
return semver.gt(latestVersion, currentVersion);
});
socket.emit('results:updatable', {updatable}); socket.emit('results:updatable', {updatable});
} catch (err) { } catch (err) {