Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds pages and published pages grids to grid list #17489

Closed
wants to merge 10 commits into from
15 changes: 8 additions & 7 deletions client/src/api/schema/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18570,8 +18570,6 @@ export interface operations {
*/
parameters?: {
/** @description Whether to include deleted pages in the result. */
/** @description Sort page index by this specified attribute on the page model */
/** @description Sort in descending order? */
/**
* @description A mix of free text and GitHub-style tags used to filter the index operation.
*
Expand Down Expand Up @@ -18608,16 +18606,19 @@ export interface operations {
* Free text search terms will be searched against the following attributes of the
* Pages: `title`, `slug`, `tag`, `user`.
*/
/** @description Sort page index by this specified attribute on the page model */
/** @description Sort in descending order? */
query?: {
deleted?: boolean;
user_id?: string | null;
show_published?: boolean;
show_shared?: boolean;
sort_by?: "update_time" | "title" | "username";
sort_desc?: boolean;
limit?: number;
offset?: number;
search?: string | null;
show_own?: boolean;
show_published?: boolean;
show_shared?: boolean;
sort_by?: "create_time" | "title" | "update_time" | "username";
sort_desc?: boolean;
user_id?: string | null;
};
/** @description The user ID that will be used to effectively make this API call. Only admins and designated users can make API calls on behalf of other users. */
header?: {
Expand Down
186 changes: 186 additions & 0 deletions client/src/components/Grid/configs/pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { faEdit, faEye, faPlus, faShareAlt, faTrash } from "@fortawesome/free-solid-svg-icons";
import { useEventBus } from "@vueuse/core";

import { fetcher } from "@/api/schema";
import { getGalaxyInstance } from "@/app";
import Filtering, { contains, equals, expandNameTag, toBool, type ValidFilter } from "@/utils/filtering";

Check failure on line 6 in client/src/components/Grid/configs/pages.ts

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

'expandNameTag' is defined but never used. Allowed unused vars must match /_.+/u

Check failure on line 6 in client/src/components/Grid/configs/pages.ts

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

'expandNameTag' is defined but never used. Allowed unused vars must match /_.+/u
import { errorMessageAsString, rethrowSimple } from "@/utils/simple-error";

import type { ActionArray, FieldArray, GridConfig } from "./types";

const { emit } = useEventBus<string>("grid-router-push");

/**
* Api endpoint handlers
*/
const getPages = fetcher.path("/api/pages").method("get").create();
const deletePage = fetcher.path("/api/pages/{id}").method("delete").create();

/**
* Local types
*/
type SortKeyLiteral = "create_time" | "title" | "update_time" | "username" | undefined;
type PageEntry = Record<string, unknown>;

/**
* Request and return data from server
*/
async function getData(offset: number, limit: number, search: string, sort_by: string, sort_desc: boolean) {
// TODO: Avoid using Galaxy instance to identify current user
const Galaxy = getGalaxyInstance();
const userId = !Galaxy.isAnonymous && Galaxy.user.id;
if (!userId) {
rethrowSimple("Please login to access this page.");
}
const { data, headers } = await getPages({
limit,
offset,
search,
sort_by: sort_by as SortKeyLiteral,
sort_desc,
show_published: false,
user_id: userId,
});
const totalMatches = parseInt(headers.get("total_matches") ?? "0");
return [data, totalMatches];
}

/**
* Actions are grid-wide operations
*/
const actions: ActionArray = [
{
title: "Create",
icon: faPlus,
handler: () => {
emit("/pages/create");
},
},
];

/**
* Declare columns to be displayed
*/
const fields: FieldArray = [
{
title: "Title",
key: "title",
type: "operations",
width: 40,
operations: [
{
title: "View",
icon: faEye,
condition: (data: PageEntry) => !data.deleted,
handler: (data: PageEntry) => {
emit(`/published/page?id=${data.id}`);
},
},
{
title: "Edit Content",
icon: faEdit,
condition: (data: PageEntry) => !data.deleted,
handler: (data: PageEntry) => {
emit(`/pages/edit?id=${data.id}`);
},
},
{
title: "Edit Content",
icon: faEdit,
condition: (data: PageEntry) => !data.deleted,
handler: (data: PageEntry) => {
emit(`/pages/editor?id=${data.id}`);
},
},
{
title: "Share and Publish",
icon: faShareAlt,
condition: (data: PageEntry) => !data.deleted,
handler: (data: PageEntry) => {
emit(`/pages/sharing?id=${data.id}`);
},
},
{
title: "Delete",
icon: faTrash,
condition: (data: PageEntry) => !data.deleted,
handler: async (data: PageEntry) => {
try {
await deletePage({ id: String(data.id) });
return {
status: "success",
message: `'${data.title}' has been deleted.`,
};
} catch (e) {
return {
status: "danger",
message: `Failed to delete '${data.title}': ${errorMessageAsString(e)}.`,
};
}
},
},
],
},
{
key: "create_time",
title: "Created",
type: "date",
},
{
key: "update_time",
title: "Updated",
type: "date",
},
{
key: "sharing",
title: "Status",
type: "sharing",
},
];

/**
* Declare filter options
*/
const validFilters: Record<string, ValidFilter<string | boolean | undefined>> = {
title: { placeholder: "title", type: String, handler: contains("title"), menuItem: true },
slug: { handler: contains("slug"), menuItem: false },
published: {
placeholder: "Filter on published pages",
type: Boolean,
boolType: "is",
handler: equals("published", "published", toBool),
menuItem: true,
},
importable: {
placeholder: "Filter on importable pages",
type: Boolean,
boolType: "is",
handler: equals("importable", "importable", toBool),
menuItem: true,
},
deleted: {
placeholder: "Filter on deleted pages",
type: Boolean,
boolType: "is",
handler: equals("deleted", "deleted", toBool),
menuItem: true,
},
};

/**
* Grid configuration
*/
const gridConfig: GridConfig = {
id: "pages-grid",
actions: actions,
fields: fields,
filtering: new Filtering(validFilters, undefined, false, false),
getData: getData,
plural: "Pages",
sortBy: "update_time",
sortDesc: true,
sortKeys: ["create_time", "title", "update_time"],
title: "Saved Pages",
};

export default gridConfig;
121 changes: 121 additions & 0 deletions client/src/components/Grid/configs/pagesPublished.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { faEye, faPlus } from "@fortawesome/free-solid-svg-icons";
import { useEventBus } from "@vueuse/core";

import { fetcher } from "@/api/schema";
import { getGalaxyInstance } from "@/app";
import Filtering, { contains, type ValidFilter } from "@/utils/filtering";
import { rethrowSimple } from "@/utils/simple-error";

import type { ActionArray, FieldArray, GridConfig } from "./types";

const { emit } = useEventBus<string>("grid-router-push");

/**
* Api endpoint handlers
*/
const getPages = fetcher.path("/api/pages").method("get").create();

/**
* Local types
*/
type SortKeyLiteral = "create_time" | "title" | "update_time" | "username" | undefined;
type PageEntry = Record<string, unknown>;

/**
* Request and return data from server
*/
async function getData(offset: number, limit: number, search: string, sort_by: string, sort_desc: boolean) {
// TODO: Avoid using Galaxy instance to identify current user
const Galaxy = getGalaxyInstance();
const userId = !Galaxy.isAnonymous && Galaxy.user.id;
if (!userId) {
rethrowSimple("Please login to access this page.");
}
const { data, headers } = await getPages({
limit,
offset,
search,
sort_by: sort_by as SortKeyLiteral,
sort_desc,
show_published: false,
user_id: userId,
});
const totalMatches = parseInt(headers.get("total_matches") ?? "0");
return [data, totalMatches];
}

/**
* Actions are grid-wide operations
*/
const actions: ActionArray = [
{
title: "Create",
icon: faPlus,
handler: () => {
emit("/pages/create");
},
},
];

/**
* Declare columns to be displayed
*/
const fields: FieldArray = [
{
title: "Title",
key: "title",
type: "operations",
width: 40,
operations: [
{
title: "View",
icon: faEye,
condition: (data: PageEntry) => !data.deleted,
handler: (data: PageEntry) => {
emit(`/published/page?id=${data.id}`);
},
},
],
},
{
key: "create_time",
title: "Created",
type: "date",
},
{
key: "update_time",
title: "Updated",
type: "date",
},
{
key: "username",
title: "Owner",
type: "text",
},
];

/**
* Declare filter options
*/
const validFilters: Record<string, ValidFilter<string | boolean | undefined>> = {
title: { placeholder: "title", type: String, handler: contains("title"), menuItem: true },
slug: { handler: contains("slug"), menuItem: false },
};

/**
* Grid configuration
*/
const gridConfig: GridConfig = {
id: "pages-published-grid",
actions: actions,
fields: fields,
filtering: new Filtering(validFilters, undefined, false, false),
getData: getData,
plural: "Pages",
sortBy: "update_time",
sortDesc: true,
sortKeys: ["create_time", "title", "update_time"],
title: "Published Pages",
};

export default gridConfig;
Loading
Loading