+
{titleArea}
{labelList}
diff --git a/src/devhub/entity/addon/kanban/Configurator.jsx b/src/devhub/entity/addon/kanban/Configurator.jsx
index 1af5109e1..ffe1480d7 100644
--- a/src/devhub/entity/addon/kanban/Configurator.jsx
+++ b/src/devhub/entity/addon/kanban/Configurator.jsx
@@ -28,42 +28,19 @@ const settings = {
};
const KanbanPostBoardBasicInfoSchema = {
- title: { label: "Title", order: 1, placeholder: "Enter board title." },
-
+ title: { label: "Title", order: 1, placeholder: "Enter board title" },
description: {
label: "Description",
order: 2,
- placeholder: "Enter board description.",
- },
-};
-
-const KanbanPostBoardTagsSchema = {
- required: {
- label:
- "Enter tags you want to include. Posts with these tags will display.",
-
- order: 1,
- placeholder: "tag1, tag2",
- },
-
- excluded: {
- label:
- "Enter tags you want to exclude. Posts with these tags will not show.",
-
- order: 2,
- placeholder: "tag3, tag4",
+ placeholder: "Enter board description",
},
};
const KanbanPostBoardTicketFeaturesSchema = {
author: { label: "Author" },
like_count: { label: "Likes" },
- reply_count: { label: "Replies", noop: true },
- sponsorship_request_indicator: { label: "Sponsorship request indicator" },
- requested_sponsorship_value: { label: "Amount of requested funds" },
- requested_sponsor: { label: "Requested sponsor" },
- approved_sponsorship_value: { label: "Approved amount" },
- sponsorship_supervisor: { label: "Supervisor" },
+ approved_sponsorship_value: { label: "Funding amount" },
+ sponsorship_supervisor: { label: "Supervisor/Sponser" },
tags: { label: "Tags" },
type: { label: "Post type" },
};
@@ -79,20 +56,16 @@ const KanbanPostBoardDefaults = {
features: {
author: true,
like_count: true,
- reply_count: false,
- sponsorship_request_indicator: false,
- requested_sponsorship_value: false,
- requested_sponsor: false,
approved_sponsorship_value: true,
sponsorship_supervisor: true,
tags: true,
type: true,
},
+ sortBy: "",
},
},
payload: {
columns: {},
- tags: { excluded: [], required: [] },
},
};
@@ -116,6 +89,20 @@ const toMigrated = ({ config, metadata, payload }) => ({
},
});
+const sortByOptions = [
+ { label: "None", value: "none" },
+ { label: "Amount: High to Low", value: "descending-amount" },
+ { label: "Amount: Low to High", value: "ascending-amount" },
+ { label: "Date: Newest to Oldest", value: "descending-date" },
+ { label: "Date: Oldest to Newest", value: "ascending-date" },
+ { label: "Author: A-Z", value: "ascending-author" },
+ { label: "Author: Z-A", value: "descending-author" },
+ { label: "Sponsor/Supervisor: A-Z", value: "ascending-sponsor" },
+ { label: "Sponsor/Supervisor: Z-A", value: "descending-sponsor" },
+ { label: "Most Likes", value: "descending-likes" },
+ { label: "Fewest Likes", value: "ascending-likes" },
+];
+
const KanbanViewConfigurator = ({ handle, data, permissions, onSubmit }) => {
const tags = useCache(
() =>
@@ -200,9 +187,9 @@ const KanbanViewConfigurator = ({ handle, data, permissions, onSubmit }) => {
const onSave = () => onSubmit(formState);
const formElement = (
- <>
-
-
+
+
-
-
-
-
- {`Columns ( max. ${settings.maxColumnsNumber} )`}
-
-
+
+
+ Fields to display
+
+
+
+
+
+
+
+ Sort by
+
+
+
+
+
+
+
-
- {Object.values(formState.payload.columns ?? {}).map(
- ({ id, description, tag, title }) => (
-
-
-
-
-
-
+
+
+
+ {`Columns ( max. ${settings.maxColumnsNumber} )`}
+
+
-
+ {Object.values(formState.payload.columns ?? {}).map(
+ ({ id, description, tag, title }) => (
+
-
-
-
- )
- )}
+
+
+
+
+
+ Enter a tag to filter posts in this column
+
+
+
+
+
+
-
-
-
+
+
+
+
+ )
+ )}
+
+
+
+ =
+ settings.maxColumnsNumber,
+ icon: { type: "bootstrap_icon", variant: "bi-plus-lg" },
+ onClick: formUpdate({
+ path: ["payload", "columns"],
+ via: columnsCreateNew,
+ }),
+ }}
+ />
+
+
+
+
+
- >
+
);
return (
@@ -395,28 +447,7 @@ const KanbanViewConfigurator = ({ handle, data, permissions, onSubmit }) => {
Kanban board configuration
- {Object.keys(formState.metadata ?? {}).length > 0 && (
-
- {formElement}
- =
- settings.maxColumnsNumber,
- icon: { type: "bootstrap_icon", variant: "bi-plus-lg" },
- onClick: formUpdate({
- path: ["payload", "columns"],
- via: columnsCreateNew,
- }),
- }}
- />
-
- )}
+ {Object.keys(formState.metadata ?? {}).length > 0 && formElement}
)}
{!Object.keys(formState.metadata ?? {}).length && (
diff --git a/src/devhub/entity/addon/kanban/post_board.jsx b/src/devhub/entity/addon/kanban/post_board.jsx
index e14116002..36ba05e45 100644
--- a/src/devhub/entity/addon/kanban/post_board.jsx
+++ b/src/devhub/entity/addon/kanban/post_board.jsx
@@ -1,6 +1,10 @@
const { getPostsByLabel } = VM.require(
"${REPL_DEVHUB}/widget/core.adapter.devhub-contract"
);
+const { getPost } = VM.require(
+ "${REPL_DEVHUB}/widget/core.adapter.devhub-contract"
+);
+getPost || (getPost = () => {});
getPostsByLabel || (getPostsByLabel = () => {});
const postTagsToIdSet = (tags) => {
@@ -9,6 +13,19 @@ const postTagsToIdSet = (tags) => {
);
};
+const sortByValues = {
+ descendingAmount: "descending-amount",
+ ascendingAmount: "ascending-amount",
+ descendingDate: "descending-date",
+ ascendingDate: "ascending-date",
+ ascendingAuthor: "ascending-author",
+ descendingAuthor: "descending-author",
+ ascendingSponsor: "ascending-sponsor",
+ descendingSponsor: "descending-sponsor",
+ descendingLikes: "descending-likes",
+ ascendingLikes: "ascending-likes",
+};
+
const configToColumnData = ({ columns, tags }) =>
Object.entries(columns).reduce((registry, [columnId, column]) => {
const postIds = (getPostsByLabel({ label: column.tag }) ?? []).reverse();
@@ -16,28 +33,101 @@ const configToColumnData = ({ columns, tags }) =>
...registry,
[columnId]: {
...column,
- postIds:
- tags.required.length > 0
- ? postIds.filter(
- (postId) =>
- postTagsToIdSet(tags.required).has(postId) &&
- !postTagsToIdSet(tags.excluded).has(postId)
- )
- : postIds,
+ postIds: postIds,
},
};
}, {});
+const basicAlphabeticalComparison = (a, b) => {
+ if (a < b) return -1;
+ if (a > b) return 1;
+ return 0;
+};
+
const KanbanPostBoard = ({ metadata, payload }) => {
- const columns = Object.entries(configToColumnData(payload) ?? {}).map(
- ([columnId, column]) => (
-
+ const boardData = Object.entries(configToColumnData(payload) ?? {});
+
+ const view = boardData.map(([columnId, column]) => {
+ const data = [];
+ column.postIds?.map((postId) => {
+ if (postId) {
+ const postData = getPost({
+ post_id: postId ? parseInt(postId) : 0,
+ });
+ data.push(postData);
+ }
+ });
+
+ // sort data by selected sorting mechanism
+ switch (metadata.ticket.sortBy) {
+ case sortByValues.descendingAmount:
+ data.sort((a, b) => b?.snapshot?.amount - a?.snapshot?.amount);
+ break;
+ case sortByValues.ascendingAmount:
+ data.sort((a, b) => a?.snapshot?.amount - b?.snapshot?.amount);
+ break;
+ case sortByValues.descendingDate:
+ data.sort(
+ (a, b) =>
+ parseInt(b?.snapshot?.timestamp) - parseInt(a?.snapshot?.timestamp)
+ );
+ break;
+ case sortByValues.ascendingDate:
+ data.sort(
+ (a, b) =>
+ parseInt(a?.snapshot?.timestamp) - parseInt(b?.snapshot?.timestamp)
+ );
+ break;
+ case sortByValues.ascendingAuthor:
+ data.sort((a, b) =>
+ basicAlphabeticalComparison(a.author_id, b.author_id)
+ );
+ break;
+ case sortByValues.descendingAuthor:
+ data.sort((a, b) =>
+ basicAlphabeticalComparison(b.author_id, a.author_id)
+ );
+ break;
+ case sortByValues.ascendingSponsor:
+ data.sort((a, b) =>
+ basicAlphabeticalComparison(
+ a?.snapshot?.requested_sponsor || a?.snapshot?.supervisor,
+ b?.snapshot?.requested_sponsor || b?.snapshot?.supervisor
+ )
+ );
+ break;
+ case sortByValues.descendingSponsor:
+ data.sort((a, b) =>
+ basicAlphabeticalComparison(
+ b?.snapshot?.requested_sponsor || b?.snapshot?.supervisor,
+ a?.snapshot?.requested_sponsor || a?.snapshot?.supervisor
+ )
+ );
+ break;
+ case sortByValues.descendingLikes:
+ data.sort((a, b) => b.likes.length - a.likes.length);
+ break;
+ case sortByValues.ascendingLikes:
+ data.sort((a, b) => a.likes.length - b.likes.length);
+ break;
+ default:
+ data;
+ break;
+ }
+
+ return (
+
@@ -51,33 +141,41 @@ const KanbanPostBoard = ({ metadata, payload }) => {
{column.description}
-
- {column.postIds?.map((postId) => (
-
- ))}
+
+ {data.length === column.postIds.length &&
+ data.map((postData) => (
+
+ ))}
- )
- );
+ );
+ });
return (