Skip to content

Commit

Permalink
support embed for kanban display
Browse files Browse the repository at this point in the history
  • Loading branch information
mdroidian committed Dec 14, 2023
1 parent 3a160ef commit 543d9a9
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 40 deletions.
72 changes: 63 additions & 9 deletions src/components/Kanban.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,57 @@ import toCellValue from "../utils/toCellValue";
import extractTag from "roamjs-components/util/extractTag";
import deleteBlock from "roamjs-components/writes/deleteBlock";
import getSubTree from "roamjs-components/util/getSubTree";
import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid";

const zPriority = z.record(z.number().min(0).max(1));

type Reprioritize = (args: { uid: string; x: number; y: number }) => void;

const CellEmbed = ({ uid, viewValue }: { uid: string; viewValue: string }) => {
const title = getPageTitleByPageUid(uid);
const contentRef = useRef(null);
const open =
viewValue === "open" ? true : viewValue === "closed" ? false : null;
useEffect(() => {
const el = contentRef.current;
if (el) {
window.roamAlphaAPI.ui.components.renderBlock({
uid,
el,
// "open?": open, // waiting for roamAlphaAPI to add a open/close to renderBlock
});
}
}, [contentRef]);
return (
<div className="roamjs-query-embed" style={{ marginLeft: "-15px" }}>
<Icon
icon="drag-handle-horizontal"
className="absolute right-2 top-2 text-gray-400 embed-handle cursor-move z-30"
/>
<div
ref={contentRef}
className={!!title ? "page-embed" : "block-embed"}
/>
</div>
);
};

const KanbanCard = (card: {
$priority: number;
$reprioritize: Reprioritize;
$displayKey: string;
$columnKey: string;
$selectionValues: string[];
$getColumnElement: (x: number) => HTMLDivElement | undefined;
result: Result;
view: string;
viewValue: string;
$columnKey: string;
$selectionValues: string[];
}) => {
const [isDragging, setIsDragging] = useState(false);

return (
<Draggable
handle={card.view === "embed" ? ".embed-handle" : ""}
onDrag={(_, data) => {
const { x, width } = data.node.getBoundingClientRect();
const el = card.$getColumnElement(x + width / 2);
Expand All @@ -61,6 +94,7 @@ const KanbanCard = (card: {
data-uid={card.result.uid}
data-priority={card.$priority}
onClick={(e) => {
if (card.view === "embed") return;
if (isDragging) return;
if (e.shiftKey) {
openBlockInSidebar(card.result.uid);
Expand All @@ -75,13 +109,23 @@ const KanbanCard = (card: {
}
}}
>
<div className={`rounded-xl bg-white p-4 hover:bg-gray-200`}>
<div className="card-display-value">
{toCellValue({
value: card.result[card.$displayKey],
uid: card.result[`${card.$displayKey}-uid`],
})}
</div>
<div
className={`rounded-xl bg-white p-4 ${
card.view !== "embed" ? "hover:bg-gray-200" : ""
}`}
>
{card.view === "embed" ? (
<div className="card-display-value">
<CellEmbed uid={card.result.uid} viewValue={card.viewValue} />
</div>
) : (
<div className="card-display-value ">
{toCellValue({
value: card.result[card.$displayKey],
uid: card.result[`${card.$displayKey}-uid`],
})}
</div>
)}
<div className="card-selections mt-3">
<HTMLTable condensed={true}>
<tbody>
Expand Down Expand Up @@ -126,12 +170,14 @@ const Kanban = ({
onQuery,
resultKeys,
parentUid,
views,
}: {
resultKeys: Column[];
data: Result[];
layout: Record<string, string | string[]>;
onQuery: () => void;
parentUid: string;
views: { column: string; mode: string; value: string }[];
}) => {
const byUid = useMemo(
() => Object.fromEntries(data.map((d) => [d.uid, d] as const)),
Expand Down Expand Up @@ -375,6 +421,12 @@ const Kanban = ({
setOpenedPopoverIndex(null);
};

const viewsByColumn = useMemo(
() => Object.fromEntries(views.map((v) => [v.column, v])),
[views]
);
const { mode: view, value: viewValue } = viewsByColumn[displayKey] || {};

return (
<>
{showLegend === "Yes" && (
Expand Down Expand Up @@ -466,6 +518,8 @@ const Kanban = ({
<KanbanCard
key={d.uid}
result={d}
view={view}
viewValue={viewValue}
// we use $ to prefix these props to avoid collisions with the result object
$priority={prioritization[d.uid]}
$reprioritize={reprioritizeAndUpdateBlock}
Expand Down
7 changes: 5 additions & 2 deletions src/components/ResultsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,18 @@ const ResultHeader = React.forwardRef<
}
);

const CellEmbed = ({ uid }: { uid: string }) => {
const CellEmbed = ({ uid, viewValue }: { uid: string; viewValue: string }) => {
const title = getPageTitleByPageUid(uid);
const contentRef = useRef(null);
useEffect(() => {
const el = contentRef.current;
const open =
viewValue === "open" ? true : viewValue === "closed" ? false : null;
if (el) {
window.roamAlphaAPI.ui.components.renderBlock({
uid,
el,
// "open?": open, // waiting for roamAlphaAPI to add a open/close to renderBlock
});
}
}, [contentRef]);
Expand Down Expand Up @@ -335,7 +338,7 @@ const ResultRow = ({
{view === "alias" ? viewValue : cell(key)}
</a>
) : view === "embed" ? (
<CellEmbed uid={uid} />
<CellEmbed uid={uid} viewValue={viewValue} />
) : (
cell(key)
)}
Expand Down
112 changes: 84 additions & 28 deletions src/components/ResultsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Intent,
Label,
Divider,
HTMLTable,
} from "@blueprintjs/core";
import { MultiSelect } from "@blueprintjs/select";
import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid";
Expand Down Expand Up @@ -46,6 +47,8 @@ const VIEWS: Record<string, { value: boolean }> = {
alias: { value: true },
};

const EMBED_FOLD_VALUES = ["default", "open", "closed"]; // waiting for roamAlphaAPI to add a open/close to renderBlock

type EnglishQueryPart = { text: string; clickId?: string };

const QueryUsed = ({ parentUid }: { parentUid: string }) => {
Expand Down Expand Up @@ -393,6 +396,9 @@ const ResultsView: ResultsViewComponent = ({
);
};
const debounceRef = useRef(0);
const showColumnViewOptions = views.some(
(view) => VIEWS[view.mode]?.value === true
);

return (
<div
Expand Down Expand Up @@ -838,39 +844,88 @@ const ResultsView: ResultsViewComponent = ({
</div>
</div>
) : isEditViews ? (
<div className="relative w-72 p-4">
<div
style={{ minWidth: "26rem" }}
className="relative max-w-md p-4 roamjs-query-column-views"
>
<MenuHeading
onClear={() => setIsEditViews(false)}
text="Column Views"
/>
<div className="flex flex-col gap-1">
{views.map(({ column, mode, value }, i) => (
<React.Fragment key={i}>
<div className="flex items-center justify-between gap-2">
<span style={{ flex: 1 }}>{column}</span>
<MenuItemSelect
className="roamjs-view-select"
items={Object.keys(VIEWS)}
activeItem={mode}
onItemSelect={(m) => {
onViewChange({ mode: m, column, value }, i);
}}
/>
</div>
{VIEWS[mode]?.value && (
<InputGroup
value={value}
onChange={(e) => {
onViewChange(
{ mode, column, value: e.target.value },
i
);
}}
/>
<HTMLTable className="min-w-full">
<thead className="bg-gray-50">
<tr>
<th className="text-xs font-medium !text-gray-500 uppercase tracking-wider">
Column
</th>
<th className="text-xs font-medium !text-gray-500 uppercase tracking-wider">
View
</th>
{showColumnViewOptions && (
<th className="text-xs font-medium !text-gray-500 uppercase tracking-wider">
Options
</th>
)}
</React.Fragment>
))}
</div>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{views.map(({ column, mode, value }, i) => (
<tr key={i}>
<td className="whitespace-nowrap">{column}</td>
<td className="whitespace-nowrap">
<MenuItemSelect
className="roamjs-view-select"
items={Object.keys(VIEWS)}
activeItem={mode}
onItemSelect={(m) =>
onViewChange({ mode: m, column, value }, i)
}
/>
</td>
{showColumnViewOptions && (
<td className="whitespace-nowrap">
{mode === "alias" && (
<InputGroup
value={value}
onChange={(e) =>
onViewChange(
{
mode,
column,
value: e.target.value,
},
i
)
}
/>
)}
{/* {mode === "embed" && (
<div className="flex items-center">
<MenuItemSelect
className="roamjs-view-select"
items={EMBED_FOLD_VALUES}
activeItem={
!!value ? value : EMBED_FOLD_VALUES[0]
}
onItemSelect={(value) => {
onViewChange({ mode, column, value }, i);
}}
/>
<Tooltip content="Initial folded state">
<Icon
icon="info-sign"
iconSize={12}
className="opacity-80 ml-2 align-middle"
/>
</Tooltip>
</div>
)} */}
</td>
)}
</tr>
))}
</tbody>
</HTMLTable>
</div>
) : (
<Menu>
Expand Down Expand Up @@ -1099,6 +1154,7 @@ const ResultsView: ResultsViewComponent = ({
onQuery={() => onRefresh(true)}
resultKeys={columns}
parentUid={parentUid}
views={views}
/>
) : (
<div style={{ padding: "16px 8px" }}>
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ svg.rs-svg-container {
}
.roamjs-kanban-container div.react-draggable-dragging.roamjs-kanban-card > div {
transform: rotate(20deg);
transform: rotate(5deg);
cursor: grabbing;
z-index: 1000;
}
Expand Down Expand Up @@ -192,6 +192,12 @@ svg.rs-svg-container {
.roamjs-query-results-view .roamjs-kanban-card .card-selections table.bp3-html-table td {
padding: 0.50rem;
}
.roamjs-query-column-views .bp3-running-text table th,
.roamjs-query-column-views table.bp3-html-table th,
.roamjs-query-column-views .bp3-running-text table td,
.roamjs-query-column-views table.bp3-html-table td {
vertical-align: initial;
}
`);
const isCanvasPage = (title: string) => {
const canvasPageFormat =
Expand Down

0 comments on commit 543d9a9

Please sign in to comment.