mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 14:13:34 +01:00
Added sorting for plugins (#6580)
This commit is contained in:
parent
3fdb3f7838
commit
221f6f2002
4 changed files with 75 additions and 16 deletions
|
@ -802,3 +802,12 @@ input, button, select, optgroup, textarea {
|
||||||
background-color: var(--etherpad-color);
|
background-color: var(--etherpad-color);
|
||||||
color: white
|
color: white
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-pads{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-pads-body tr td:last-child {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
|
@ -6,14 +6,51 @@ 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 {Download, Trash} from "lucide-react";
|
||||||
import {IconButton} from "../components/IconButton.tsx";
|
import {IconButton} from "../components/IconButton.tsx";
|
||||||
|
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, setInstalledPlugins] = useState<InstalledPlugin[]>([])
|
||||||
|
const [searchParams, setSearchParams] = useState<SearchParams>({
|
||||||
|
offset: 0,
|
||||||
|
limit: 99999,
|
||||||
|
sortBy: 'name',
|
||||||
|
sortDir: 'asc',
|
||||||
|
searchTerm: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const filteredInstallablePlugins = useMemo(()=>{
|
||||||
|
return plugins.sort((a, b)=>{
|
||||||
|
if(searchParams.sortBy === "version"){
|
||||||
|
if(searchParams.sortDir === "asc"){
|
||||||
|
return a.version.localeCompare(b.version)
|
||||||
|
}
|
||||||
|
return b.version.localeCompare(a.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(searchParams.sortBy === "last-updated"){
|
||||||
|
if(searchParams.sortDir === "asc"){
|
||||||
|
return a.time.localeCompare(b.time)
|
||||||
|
}
|
||||||
|
return b.time.localeCompare(a.time)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (searchParams.sortBy === "name") {
|
||||||
|
if(searchParams.sortDir === "asc"){
|
||||||
|
return a.name.localeCompare(b.name)
|
||||||
|
}
|
||||||
|
return b.name.localeCompare(a.name)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
}, [plugins, searchParams])
|
||||||
|
|
||||||
const sortedInstalledPlugins = useMemo(()=>{
|
const sortedInstalledPlugins = useMemo(()=>{
|
||||||
return installedPlugins.sort((a, b)=>{
|
return installedPlugins.sort((a, b)=>{
|
||||||
|
|
||||||
if(a.name < b.name){
|
if(a.name < b.name){
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
@ -23,14 +60,8 @@ export const HomePage = () => {
|
||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
} ,[installedPlugins])
|
} ,[installedPlugins, searchParams])
|
||||||
const [searchParams, setSearchParams] = useState<SearchParams>({
|
|
||||||
offset: 0,
|
|
||||||
limit: 99999,
|
|
||||||
sortBy: 'name',
|
|
||||||
sortDir: 'asc',
|
|
||||||
searchTerm: ''
|
|
||||||
})
|
|
||||||
const [searchTerm, setSearchTerm] = useState<string>('')
|
const [searchTerm, setSearchTerm] = useState<string>('')
|
||||||
const {t} = useTranslation()
|
const {t} = useTranslation()
|
||||||
|
|
||||||
|
@ -165,16 +196,35 @@ export const HomePage = () => {
|
||||||
<table id="available-plugins">
|
<table id="available-plugins">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><Trans i18nKey="admin_plugins.name"/></th>
|
<th className={determineSorting(searchParams.sortBy, searchParams.sortDir == "asc", 'name')} onClick={()=>{
|
||||||
|
setSearchParams({
|
||||||
|
...searchParams,
|
||||||
|
sortBy: 'name',
|
||||||
|
sortDir: searchParams.sortDir === "asc"? "desc": "asc"
|
||||||
|
})
|
||||||
|
}}>
|
||||||
|
<Trans i18nKey="admin_plugins.name" /></th>
|
||||||
<th style={{width: '30%'}}><Trans i18nKey="admin_plugins.description"/></th>
|
<th style={{width: '30%'}}><Trans i18nKey="admin_plugins.description"/></th>
|
||||||
<th><Trans i18nKey="admin_plugins.version"/></th>
|
<th className={determineSorting(searchParams.sortBy, searchParams.sortDir == "asc", 'version')} onClick={()=>{
|
||||||
<th><Trans i18nKey="admin_plugins.last-update"/></th>
|
setSearchParams({
|
||||||
|
...searchParams,
|
||||||
|
sortBy: 'version',
|
||||||
|
sortDir: searchParams.sortDir === "asc"? "desc": "asc"
|
||||||
|
})
|
||||||
|
}}><Trans i18nKey="admin_plugins.version"/></th>
|
||||||
|
<th className={determineSorting(searchParams.sortBy, searchParams.sortDir == "asc", 'last-updated')} onClick={()=>{
|
||||||
|
setSearchParams({
|
||||||
|
...searchParams,
|
||||||
|
sortBy: 'last-updated',
|
||||||
|
sortDir: searchParams.sortDir === "asc"? "desc": "asc"
|
||||||
|
})
|
||||||
|
}}><Trans i18nKey="admin_plugins.last-update"/></th>
|
||||||
<th><Trans i18nKey="ep_admin_pads:ep_adminpads2_action"/></th>
|
<th><Trans i18nKey="ep_admin_pads:ep_adminpads2_action"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody style={{overflow: 'auto'}}>
|
<tbody style={{overflow: 'auto'}}>
|
||||||
{(plugins.length > 0) ?
|
{(filteredInstallablePlugins.length > 0) ?
|
||||||
plugins.map((plugin) => {
|
filteredInstallablePlugins.map((plugin) => {
|
||||||
return <tr key={plugin.name}>
|
return <tr key={plugin.name}>
|
||||||
<td><a rel="noopener noreferrer" href={`https://npmjs.com/${plugin.name}`} target="_blank">{plugin.name}</a></td>
|
<td><a rel="noopener noreferrer" href={`https://npmjs.com/${plugin.name}`} target="_blank">{plugin.name}</a></td>
|
||||||
<td>{plugin.description}</td>
|
<td>{plugin.description}</td>
|
||||||
|
|
|
@ -104,7 +104,7 @@ export const PadPage = ()=>{
|
||||||
<SearchField value={searchTerm} onChange={v=>setSearchTerm(v.target.value)} placeholder={t('ep_admin_pads:ep_adminpads2_search-heading')}/>
|
<SearchField value={searchTerm} onChange={v=>setSearchTerm(v.target.value)} placeholder={t('ep_admin_pads:ep_adminpads2_search-heading')}/>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr className="search-pads">
|
||||||
<th className={determineSorting(searchParams.sortBy, searchParams.ascending, 'padName')} onClick={()=>{
|
<th className={determineSorting(searchParams.sortBy, searchParams.ascending, 'padName')} onClick={()=>{
|
||||||
setSearchParams({
|
setSearchParams({
|
||||||
...searchParams,
|
...searchParams,
|
||||||
|
@ -136,7 +136,7 @@ export const PadPage = ()=>{
|
||||||
<th><Trans i18nKey="ep_admin_pads:ep_adminpads2_action"/></th>
|
<th><Trans i18nKey="ep_admin_pads:ep_adminpads2_action"/></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody className="search-pads-body">
|
||||||
{
|
{
|
||||||
pads?.results?.map((pad)=>{
|
pads?.results?.map((pad)=>{
|
||||||
return <tr key={pad.padName}>
|
return <tr key={pad.padName}>
|
||||||
|
|
|
@ -20,7 +20,7 @@ export type SearchParams = {
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
offset: number,
|
offset: number,
|
||||||
limit: number,
|
limit: number,
|
||||||
sortBy: 'name'|'version',
|
sortBy: 'name'|'version'|'last-updated',
|
||||||
sortDir: 'asc'|'desc'
|
sortDir: 'asc'|'desc'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue