Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ export const Executable: DynamicViewRenderer = ({ data, callbacks }) => {
window.newTab(window.layoutModel, {
type: 'tab',
name: 'Component preview',
component: `/pages/${data.uid}`,
component: `/pages/library/object`,
enableFloat: 'true',
config: {},
config: { uid: data.uid, type: '$/schema/executable' },
});
},
'lambda/js': async () => {
Expand Down
116 changes: 40 additions & 76 deletions packages/unigraph-dev-explorer/src/examples/todo/TodoDefaultViews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,6 @@ import { DynamicObjectListView } from '../../components/ObjectView/DynamicObject
import { withUnigraphSubscription } from '../../unigraph-react';
import { ATodoList, filters, groupByTags, groupers } from './utils';

function TodoListBody({ data }: { data: ATodoList[] }) {
const todoList = data;

const [filteredItems, setFilteredItems] = React.useState(todoList);

React.useEffect(() => {
const res = todoList;
setFilteredItems(res);
console.log('TodoListBody', { data });
}, [todoList]);

return (
<div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
<DynamicObjectListView
items={filteredItems}
context={null}
filters={filters}
defaultFilter="only-incomplete"
compact
groupers={{ tags: groupByTags }}
/>
</div>
);
}

export const TodoInbox = (props: any) => (
<AutoDynamicViewDetailed
object={{
Expand Down Expand Up @@ -107,68 +82,57 @@ const withSubscribeTodos = (component: React.FC<any>) => {
},
);
};

function TodoListBodyFactory(filtersMaker: any[], attrs?: any) {
return function ({ data }: { data: ATodoList[] }) {
const todoList = data;

// eslint-disable-next-line react-hooks/rules-of-hooks
const [filteredItems, setFilteredItems] = React.useState(todoList);

// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(() => {
const res = todoList;
setFilteredItems(res);
// console.log('TodoListBody', { data });
}, [todoList]);

return (
<div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
<DynamicObjectListView
items={filteredItems}
context={null}
filters={filters}
defaultFilter={filtersMaker}
compact
groupers={{ ...groupers, tags: groupByTags }}
{...(attrs || {})}
/>
</div>
);
};
}

const TodoListBody = TodoListBodyFactory(['only-incomplete']);
const UntaggedTodoListBody = TodoListBodyFactory(['only-incomplete', 'only-untagged']);
const TodoTodayBody = TodoListBodyFactory(['only-incomplete', 'until-today'], { groupBy: 'due_date' });
const TodoUpcomingBody = TodoListBodyFactory(['only-incomplete'], { groupBy: 'due_date' });

export const TodoAll = (props: any) => {
const Component = withSubscribeTodos(TodoListBody);
return <Component {...props} />;
};

function TodoTodayBody({ data }: { data: ATodoList[] }) {
const todoList = data;

const [filteredItems, setFilteredItems] = React.useState(todoList);

React.useEffect(() => {
const res = todoList;
setFilteredItems(res);
console.log('TodoUpcomingBody', { data });
}, [todoList]);

return (
<div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
<DynamicObjectListView
items={filteredItems}
context={null}
filters={filters}
defaultFilter={['only-incomplete', 'until-today']}
compact
groupers={groupers}
groupBy="due_date"
/>
</div>
);
}
export const TodoUntagged = (props: any) => {
const Component = withSubscribeTodos(UntaggedTodoListBody);
return <Component {...props} />;
};

export const TodoToday = (props: any) => {
const Component = withSubscribeTodos(TodoTodayBody);
return <Component {...props} />;
};

function TodoUpcomingBody({ data }: { data: ATodoList[] }) {
const todoList = data;

const [filteredItems, setFilteredItems] = React.useState(todoList);

React.useEffect(() => {
const res = todoList;
setFilteredItems(res);
console.log('TodoUpcomingBody', { data });
}, [todoList]);

return (
<div style={{ display: 'flex', height: '100%', overflow: 'hidden' }}>
<DynamicObjectListView
items={filteredItems}
context={null}
filters={filters}
defaultFilter="only-incomplete"
compact
groupers={groupers}
groupBy="due_date"
/>
</div>
);
}

export const TodoUpcoming = (props: any) => {
const Component = withSubscribeTodos(TodoUpcomingBody);
return <Component {...props} />;
Expand Down
59 changes: 53 additions & 6 deletions packages/unigraph-dev-explorer/src/examples/todo/TodoSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { mdiBookOpenOutline, mdiCalendarAlert, mdiCalendarOutline, mdiInboxOutline, mdiTagOutline } from '@mdi/js';
import {
mdiBookOpenOutline,
mdiCalendarAlert,
mdiCalendarOutline,
mdiInboxOutline,
mdiTagOffOutline,
mdiTagOutline,
} from '@mdi/js';
import Icon from '@mdi/react';
import { Drawer, ListItemText, ListSubheader } from '@mui/material';
import List from '@mui/material/List';
Expand All @@ -10,9 +17,10 @@ import { useEffectOnce } from 'react-use';
import { getRandomInt, UnigraphObject } from 'unigraph-dev-common/lib/utils/utils';
import { DynamicObjectListView } from '../../components/ObjectView/DynamicObjectListView';
import { pointerHoverSx, TabContext } from '../../utils';
import { TodoAll, TodoInbox, TodoToday, TodoUpcoming } from './TodoDefaultViews';
import { TodoAll, TodoInbox, TodoToday, TodoUntagged, TodoUpcoming } from './TodoDefaultViews';
import { TodoTagView } from './TodoTagView';
import {
filters,
getAllTodoCountFromRes,
getAllTodoCountQuery,
getTaggedTodoCountFromRes,
Expand All @@ -21,6 +29,8 @@ import {
getTodayTodoCountQuery,
getTodoInboxCountFromRes,
getTodoInboxCountQuery,
getUntaggedTodoCountFromRes,
getUntaggedTodoCountQuery,
getUpcomingTodoCountFromRes,
getUpcomingTodoCountQuery,
} from './utils';
Expand Down Expand Up @@ -91,6 +101,13 @@ export const todoDefaultMenuItems: TodoMenuItems = {
getCountQuery: getUpcomingTodoCountQuery,
getCountFromRes: getUpcomingTodoCountFromRes,
},
untagged: {
iconPath: mdiTagOffOutline,
text: 'Untagged',
component: TodoUntagged,
getCountQuery: getUntaggedTodoCountQuery,
getCountFromRes: getUntaggedTodoCountFromRes,
},
};

const useCount = (query: string | undefined, getCountFromRes: any | undefined) => {
Expand Down Expand Up @@ -149,7 +166,22 @@ const useTags = () => {
// Subscribe to tags in general
const subsId = getRandomInt();

tabContext.subscribeToType('$/schema/tag', setValidTags, subsId);
tabContext.subscribeToType('$/schema/tag', setValidTags, subsId, {
queryAs: `{
_value {
name {
<_value.%>
}
}
type { <unigraph.id> }
uid
<unigraph.origin> @filter(NOT eq(<_hide>, true)) {
type @filter(eq(<unigraph.id>, "$/schema/todo")) {
uid
}
}
}`,
});

return function cleanup() {
tabContext.unsubscribe(subsId);
Expand Down Expand Up @@ -282,14 +314,29 @@ export const TodoMenuSidebar = ({ mode, setMode, todoViews, setTodoViews, todoLi
.filter((key) => !_.keys(todoMenuItems.archivedTags).includes(key))
.map(renderMenuItem)} */}
<DynamicObjectListView
items={tags.filter(
(tag: any) => !_.keys(todoMenuItems.archivedTags).includes(tag.get('name').as('primitive')),
)}
items={tags
.filter(
(tag: any) => !_.keys(todoMenuItems.archivedTags).includes(tag.get('name').as('primitive')),
)
.sort((a: any, b: any) => {
return a.get('name')?.as('primitive') < b.get('name')?.as('primitive') ? 1 : -1;
})}
context={null}
noDrop
noBar
loadAll
compact
filters={[
...filters,
{
id: 'only-with-todo',
fn: (obj: any) => {
return obj?.['unigraph.origin']?.length > 0;
},
},
]}
defaultFilter="only-with-todo"
itemStyle={{ margin: '0px', padding: '0px' }}
style={{ height: 'auto' }}
components={{
'$/schema/tag': {
Expand Down
36 changes: 36 additions & 0 deletions packages/unigraph-dev-explorer/src/examples/todo/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ export type ATodoList = {
};

export const filters = [
{
id: 'only-untagged',
fn: (obj: any) => {
const children = new UnigraphObject(obj).get('children')?.['_value['] || [];
const tags = children.filter((el: any) => el?._value?._value?.type?.['unigraph.id'] === '$/schema/tag');
return tags.length === 0;
},
},
{
id: 'only-incomplete',
fn: (obj: any) => {
Expand Down Expand Up @@ -249,6 +257,34 @@ export const getAllTodoCountQuery = () =>
`;
export const getAllTodoCountFromRes = flow(prop(['0', '~type']), findLast(has('todoCounts')), prop('todoCounts'));

export const getUntaggedTodoCountQuery = () =>
`todos(func: uid(todos)) @filter(NOT uid(tagged) AND type(Entity)) {
todoCounts: count(uid)
}
var(func: eq(<unigraph.id>, "$/schema/todo")) @cascade {
<~type> @filter(NOT eq(<_hide>, true)) {
todos as uid
}
}
tagged as var(func: uid(todos)) @cascade {
uid
_value {
children {
<_value[> {
_value {
_value {
type @filter(eq(<unigraph.id>, "$/schema/tag")) {
uid
}
}
}
}
}
}
}
`;
export const getUntaggedTodoCountFromRes = prop(['0', 'todoCounts']);

export const getUpcomingTodoCountQuery = () =>
`todos(func: eq(<unigraph.id>, "$/schema/todo")) @cascade{
<~type> {
Expand Down