Add actions table column
This commit is contained in:
parent
817675ee0e
commit
179129b7cb
6 changed files with 79 additions and 24 deletions
22
src/renderer/components/virtual-table/cells/actions-cell.tsx
Normal file
22
src/renderer/components/virtual-table/cells/actions-cell.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||||
|
import { RiMoreFill } from 'react-icons/ri';
|
||||||
|
import { Button } from '/@/renderer/components/button';
|
||||||
|
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||||
|
|
||||||
|
export const ActionsCell = ({ context, api }: ICellRendererParams) => {
|
||||||
|
return (
|
||||||
|
<CellContainer position="center">
|
||||||
|
<Button
|
||||||
|
compact
|
||||||
|
variant="subtle"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
context.onCellContextMenu(undefined, api, e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RiMoreFill />
|
||||||
|
</Button>
|
||||||
|
</CellContainer>
|
||||||
|
);
|
||||||
|
};
|
|
@ -2,11 +2,11 @@ import type { ReactNode } from 'react';
|
||||||
import type { IHeaderParams } from '@ag-grid-community/core';
|
import type { IHeaderParams } from '@ag-grid-community/core';
|
||||||
import { AiOutlineNumber } from 'react-icons/ai';
|
import { AiOutlineNumber } from 'react-icons/ai';
|
||||||
import { FiClock } from 'react-icons/fi';
|
import { FiClock } from 'react-icons/fi';
|
||||||
import { RiHeartLine, RiStarLine } from 'react-icons/ri';
|
import { RiHeartLine, RiMoreFill, RiStarLine } from 'react-icons/ri';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { _Text } from '/@/renderer/components/text';
|
import { _Text } from '/@/renderer/components/text';
|
||||||
|
|
||||||
type Presets = 'duration' | 'rowIndex' | 'userFavorite' | 'userRating';
|
type Presets = 'duration' | 'rowIndex' | 'userFavorite' | 'userRating' | 'actions';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
@ -41,6 +41,12 @@ const TextHeaderWrapper = styled(_Text)<{ position: Options['position'] }>`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const headerPresets = {
|
const headerPresets = {
|
||||||
|
actions: (
|
||||||
|
<RiMoreFill
|
||||||
|
color="var(--ag-header-foreground-color)"
|
||||||
|
size="1em"
|
||||||
|
/>
|
||||||
|
),
|
||||||
duration: (
|
duration: (
|
||||||
<FiClock
|
<FiClock
|
||||||
color="var(--ag-header-foreground-color)"
|
color="var(--ag-header-foreground-color)"
|
||||||
|
|
|
@ -33,6 +33,7 @@ import { TableColumn, TablePagination as TablePaginationType } from '/@/renderer
|
||||||
import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorite-cell';
|
import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorite-cell';
|
||||||
import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell';
|
import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell';
|
||||||
import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination';
|
import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination';
|
||||||
|
import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell';
|
||||||
|
|
||||||
export * from './table-config-dropdown';
|
export * from './table-config-dropdown';
|
||||||
export * from './table-pagination';
|
export * from './table-pagination';
|
||||||
|
@ -50,6 +51,14 @@ const TableWrapper = styled.div`
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
const tableColumns: { [key: string]: ColDef } = {
|
const tableColumns: { [key: string]: ColDef } = {
|
||||||
|
actions: {
|
||||||
|
cellClass: 'ag-cell-favorite',
|
||||||
|
cellRenderer: (params: ICellRendererParams) => ActionsCell(params),
|
||||||
|
colId: TableColumn.ACTIONS,
|
||||||
|
headerComponent: () => <></>,
|
||||||
|
suppressSizeToFit: true,
|
||||||
|
width: 25,
|
||||||
|
},
|
||||||
album: {
|
album: {
|
||||||
cellRenderer: (params: ICellRendererParams) =>
|
cellRenderer: (params: ICellRendererParams) =>
|
||||||
GenericCell(params, { isLink: true, position: 'left' }),
|
GenericCell(params, { isLink: true, position: 'left' }),
|
||||||
|
|
|
@ -35,6 +35,7 @@ export const SONG_TABLE_COLUMNS = [
|
||||||
{ label: 'Size', value: TableColumn.SIZE },
|
{ label: 'Size', value: TableColumn.SIZE },
|
||||||
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
||||||
{ label: 'Rating', value: TableColumn.USER_RATING },
|
{ label: 'Rating', value: TableColumn.USER_RATING },
|
||||||
|
{ label: 'Actions', value: TableColumn.ACTIONS },
|
||||||
// { label: 'Skip', value: TableColumn.SKIP },
|
// { label: 'Skip', value: TableColumn.SKIP },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ export const ALBUM_TABLE_COLUMNS = [
|
||||||
{ label: 'Plays', value: TableColumn.PLAY_COUNT },
|
{ label: 'Plays', value: TableColumn.PLAY_COUNT },
|
||||||
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
||||||
{ label: 'Rating', value: TableColumn.USER_RATING },
|
{ label: 'Rating', value: TableColumn.USER_RATING },
|
||||||
|
{ label: 'Actions', value: TableColumn.ACTIONS },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ALBUMARTIST_TABLE_COLUMNS = [
|
export const ALBUMARTIST_TABLE_COLUMNS = [
|
||||||
|
@ -68,6 +70,7 @@ export const ALBUMARTIST_TABLE_COLUMNS = [
|
||||||
{ label: 'Song Count', value: TableColumn.SONG_COUNT },
|
{ label: 'Song Count', value: TableColumn.SONG_COUNT },
|
||||||
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
{ label: 'Favorite', value: TableColumn.USER_FAVORITE },
|
||||||
{ label: 'Rating', value: TableColumn.USER_RATING },
|
{ label: 'Rating', value: TableColumn.USER_RATING },
|
||||||
|
{ label: 'Actions', value: TableColumn.ACTIONS },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PLAYLIST_TABLE_COLUMNS = [
|
export const PLAYLIST_TABLE_COLUMNS = [
|
||||||
|
@ -78,6 +81,7 @@ export const PLAYLIST_TABLE_COLUMNS = [
|
||||||
{ label: 'Owner', value: TableColumn.OWNER },
|
{ label: 'Owner', value: TableColumn.OWNER },
|
||||||
// { label: 'Genre', value: TableColumn.GENRE },
|
// { label: 'Genre', value: TableColumn.GENRE },
|
||||||
{ label: 'Song Count', value: TableColumn.SONG_COUNT },
|
{ label: 'Song Count', value: TableColumn.SONG_COUNT },
|
||||||
|
{ label: 'Actions', value: TableColumn.ACTIONS },
|
||||||
];
|
];
|
||||||
|
|
||||||
interface TableConfigDropdownProps {
|
interface TableConfigDropdownProps {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { CellContextMenuEvent } from '@ag-grid-community/core';
|
import { CellContextMenuEvent, GridApi } from '@ag-grid-community/core';
|
||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
import { Album, AlbumArtist, Artist, LibraryItem, QueueSong, Song } from '/@/renderer/api/types';
|
import { Album, AlbumArtist, Artist, LibraryItem, QueueSong, Song } from '/@/renderer/api/types';
|
||||||
import { openContextMenu, SetContextMenuItems } from '/@/renderer/features/context-menu/events';
|
import { openContextMenu, SetContextMenuItems } from '/@/renderer/features/context-menu/events';
|
||||||
|
@ -8,27 +8,40 @@ export const useHandleTableContextMenu = (
|
||||||
contextMenuItems: SetContextMenuItems,
|
contextMenuItems: SetContextMenuItems,
|
||||||
context?: any,
|
context?: any,
|
||||||
) => {
|
) => {
|
||||||
const handleContextMenu = (e: CellContextMenuEvent) => {
|
const handleContextMenu = (
|
||||||
if (!e.event) return;
|
e?: CellContextMenuEvent,
|
||||||
const clickEvent = e.event as MouseEvent;
|
gridApi?: GridApi<any>,
|
||||||
clickEvent.preventDefault();
|
click?: MouseEvent,
|
||||||
|
) => {
|
||||||
let selectedNodes = sortBy(e.api.getSelectedNodes(), ['rowIndex']);
|
let clickEvent: MouseEvent | undefined = click;
|
||||||
let selectedRows = selectedNodes.map((node) => node.data);
|
if (e) {
|
||||||
|
if (!e?.event) return;
|
||||||
if (!e.data?.id) {
|
clickEvent = e?.event as MouseEvent;
|
||||||
return;
|
clickEvent.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldReplaceSelected = !selectedNodes
|
const api = gridApi || e?.api;
|
||||||
.map((node) => node.data.id)
|
|
||||||
.includes(e.data.id);
|
|
||||||
|
|
||||||
if (shouldReplaceSelected) {
|
console.log('api :>> ', api);
|
||||||
e.api.deselectAll();
|
|
||||||
e.node.setSelected(true);
|
if (!api) return;
|
||||||
selectedRows = [e.data];
|
|
||||||
selectedNodes = e.api.getSelectedNodes();
|
let selectedNodes = sortBy(api.getSelectedNodes(), ['rowIndex']);
|
||||||
|
let selectedRows = selectedNodes.map((node) => node.data);
|
||||||
|
|
||||||
|
if (e) {
|
||||||
|
if (!e.data?.id) return;
|
||||||
|
|
||||||
|
const shouldReplaceSelected = !selectedNodes
|
||||||
|
.map((node) => node.data.id)
|
||||||
|
.includes(e.data.id);
|
||||||
|
|
||||||
|
if (shouldReplaceSelected) {
|
||||||
|
e.api.deselectAll();
|
||||||
|
e.node.setSelected(true);
|
||||||
|
selectedRows = [e.data];
|
||||||
|
selectedNodes = e.api.getSelectedNodes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openContextMenu({
|
openContextMenu({
|
||||||
|
@ -36,10 +49,10 @@ export const useHandleTableContextMenu = (
|
||||||
data: selectedRows,
|
data: selectedRows,
|
||||||
dataNodes: selectedNodes,
|
dataNodes: selectedNodes,
|
||||||
menuItems: contextMenuItems,
|
menuItems: contextMenuItems,
|
||||||
tableApi: e.api,
|
tableApi: api,
|
||||||
type: itemType,
|
type: itemType,
|
||||||
xPos: clickEvent.clientX,
|
xPos: clickEvent?.clientX || 0,
|
||||||
yPos: clickEvent.clientY,
|
yPos: clickEvent?.clientY || 0,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ export type QueryBuilderGroup = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum TableColumn {
|
export enum TableColumn {
|
||||||
|
ACTIONS = 'actions',
|
||||||
ALBUM = 'album',
|
ALBUM = 'album',
|
||||||
ALBUM_ARTIST = 'albumArtist',
|
ALBUM_ARTIST = 'albumArtist',
|
||||||
ALBUM_COUNT = 'albumCount',
|
ALBUM_COUNT = 'albumCount',
|
||||||
|
|
Reference in a new issue