mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-10 15:57:53 +00:00
refactor(dashboard): revamp how lists work entirely
This commit is contained in:
parent
a62b6d53e2
commit
39e18704a6
19 changed files with 1090 additions and 613 deletions
162
dashboard/src/components/list/functions.ts
Normal file
162
dashboard/src/components/list/functions.ts
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
import type { Group, Member } from '../../api/types';
|
||||
import type { ListOptions, PageOptions } from './types';
|
||||
|
||||
export function filterList<T extends Member|Group>(list: T[], options: ListOptions, type?: string): T[] {
|
||||
let searchedList = search(list, options);
|
||||
let groupedList = [...searchedList];
|
||||
if (type)
|
||||
groupedList = group(searchedList, options, type);
|
||||
let filteredList = filter(groupedList, options);
|
||||
let sortedList = sort(filteredList, options);
|
||||
let orderedList = reorder(sortedList, options);
|
||||
|
||||
return orderedList;
|
||||
}
|
||||
|
||||
export function paginateList<T extends Member|Group>(list: T[], options: PageOptions): T[] {
|
||||
let indexLast = options.currentPage * options.itemsPerPage;
|
||||
let indexFirst = indexLast - options.itemsPerPage;
|
||||
return list.slice(indexFirst, indexLast);
|
||||
}
|
||||
|
||||
export function getPageAmount<T extends Member|Group>(list: T[], options: PageOptions): number {
|
||||
return Math.ceil(list.length / options.itemsPerPage);
|
||||
}
|
||||
|
||||
export function createShortList<T extends Member|Group>(list: T[]) {
|
||||
return list.map(function(item) {
|
||||
return {
|
||||
name: item.name,
|
||||
shortid: item.id,
|
||||
id: item.uuid,
|
||||
members: (item as Group).members,
|
||||
display_name: item.display_name};
|
||||
})
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
function search<T extends Member|Group>(list: T[], options: ListOptions): T[] {
|
||||
Object.keys(options.search).forEach(x => {
|
||||
if (options.search[x]) {
|
||||
if (options.searchMode[x] !== false)
|
||||
list = list.filter(item => item[x] ? item[x].toLowerCase().includes(options.search[x].toLowerCase()) : false);
|
||||
else list = list.filter(item => item[x] ? !item[x].toLowerCase().includes(options.search[x].toLowerCase()) : true);
|
||||
}
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function filter<T extends Member|Group>(list: T[], options: ListOptions): T[] {
|
||||
let newList = [...list];
|
||||
Object.keys(options.filter).forEach(x => {
|
||||
if (options.filter[x] === 'include') {
|
||||
newList = [...list].filter(item => item[x] && true);
|
||||
} else if (options.filter[x] === 'exclude') {
|
||||
newList = [...list].filter(item => !item[x] && true)
|
||||
}
|
||||
});
|
||||
|
||||
let anotherList = [...newList];
|
||||
|
||||
if (options.show === 'private') {
|
||||
anotherList = [...newList].filter(item => item.privacy && item.privacy.visibility === 'private');
|
||||
} else if (options.show === 'public') {
|
||||
anotherList = [...newList].filter(item => item.privacy && item.privacy.visibility === 'public');
|
||||
}
|
||||
|
||||
return anotherList;
|
||||
}
|
||||
|
||||
function sort<T extends Member|Group>(list: T[], options: ListOptions): T[] {
|
||||
if (options.sort === 'none')
|
||||
return list;
|
||||
|
||||
let newList: T[] = [];
|
||||
if (options.sort && options.sort === 'display_name' || options.sort === 'name' || options.sort === 'id') {
|
||||
newList = [...list].sort((a, b) => {
|
||||
let aa = a[options.sort] || a.name;
|
||||
let bb = b[options.sort] || b.name;
|
||||
return aa.localeCompare(bb);
|
||||
});
|
||||
} else if (options.sort === 'pronouns') {
|
||||
newList = [...list].sort((a, b) => {
|
||||
let aa = (a as Member).pronouns;
|
||||
let bb = (b as Member).pronouns;
|
||||
if (aa === bb) return a.name.localeCompare(b.name);
|
||||
if (aa === null) return 1;
|
||||
if (bb === null) return -1;
|
||||
return aa.localeCompare(bb);
|
||||
});
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
function group<T extends Member|Group>(list: T[], options: ListOptions, type?: string): T[] {
|
||||
let groupIncludedList = [...list];
|
||||
|
||||
if (options.groups.include.list.length > 0) {
|
||||
// include has items! check the type and whether to match exactly
|
||||
if (type === 'member')
|
||||
if (options.groups.include.exact === true)
|
||||
// match exact, include only members in EVERY group
|
||||
groupIncludedList = [...list].filter(m =>
|
||||
(options.groups.include.list as Group[]).every(g => g.members?.includes(m.uuid))
|
||||
);
|
||||
else
|
||||
// just include any member in at least one group
|
||||
groupIncludedList = [...list].filter(m =>
|
||||
(options.groups.include.list as Group[]).some(g => g.members?.includes(m.uuid))
|
||||
);
|
||||
|
||||
else if (type === 'group')
|
||||
if (options.groups.include.exact === true)
|
||||
groupIncludedList = [...list].filter(g =>
|
||||
(g as Group).members && (options.groups.include.list as Member[])
|
||||
.every(m => (g as Group).members.includes(m.id))
|
||||
);
|
||||
else
|
||||
groupIncludedList = [...list].filter(g =>
|
||||
(g as Group).members && (options.groups.include.list as Member[])
|
||||
.some(m => (g as Group).members.includes(m.id))
|
||||
);
|
||||
}
|
||||
|
||||
let groupExcludedList = [...groupIncludedList];
|
||||
|
||||
if (options.groups.exclude.list.length > 0) {
|
||||
if (type === 'member')
|
||||
if (options.groups.exclude.exact === true)
|
||||
groupExcludedList = [...groupIncludedList].filter(m =>
|
||||
!(options.groups.exclude.list as Group[]).every(g => g.members?.includes(m.uuid))
|
||||
);
|
||||
else
|
||||
groupExcludedList = [...groupIncludedList].filter(m =>
|
||||
!(options.groups.exclude.list as Group[]).some(g => g.members?.includes(m.uuid))
|
||||
);
|
||||
|
||||
else if (type === 'group')
|
||||
if (options.groups.exclude.exact === true)
|
||||
groupExcludedList = [...groupIncludedList].filter(g =>
|
||||
(g as Group).members && (options.groups.exclude.list as Member[])
|
||||
.some(m => !(g as Group).members.includes(m.id))
|
||||
);
|
||||
else
|
||||
groupExcludedList = [...groupIncludedList].filter(g =>
|
||||
(g as Group).members && (options.groups.exclude.list as Member[])
|
||||
.every(m => !(g as Group).members.includes(m.id))
|
||||
);
|
||||
}
|
||||
|
||||
return groupExcludedList;
|
||||
}
|
||||
|
||||
function reorder<T extends Member|Group>(list: T[], options: ListOptions): T[] {
|
||||
if (options.order === 'descending') {
|
||||
return [...list].reverse();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue