Skip to content

Commit

Permalink
#73 - List view
Browse files Browse the repository at this point in the history
  • Loading branch information
estruyf committed Sep 3, 2021
1 parent 3b6a7e9 commit b8dee7a
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 34 deletions.
66 changes: 66 additions & 0 deletions .vscode/recoil.code-snippets
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"Recoil Atom": {
"prefix": "sq-atom",
"body": [
"import { atom } from 'recoil';",
"",
"export const ${1:CollectionId}Atom = atom({",
" key: '${1:CollectionId}Atom',",
" default: 1",
"});"
],
"description": "Creates a new atom",
"scope": "typescript"
},
"Recoil Selector (sync)": {
"prefix": "sq-selector-sync",
"body": [
"import { selector } from 'recoil';",
"",
"export const ${1:CollectionData}Selector = selector({",
" key: '${1:CollectionData}Selector',",
" get: ({get}) => {",
" return get(${2:CollectionIdState});",
" }",
"});"
],
"description": "Creates a new synchronous selector",
"scope": "typescript"
},
"Recoil Selector (async)": {
"prefix": "sq-selector-async",
"body": [
"import { selector } from 'recoil';",
"",
"export const ${1:CollectionData}Selector = selector({",
" key: '${1:CollectionData}Selector',",
" get: async ({get}) => {",
" return await dataFetch(get(${2:CollectionIdState}));",
" }",
"});"
],
"description": "Creates a new asynchronous selector",
"scope": "typescript"
},
"Recoil selectorFamily": {
"prefix": "sq-selector-fam",
"body": [
"import { selectorFamily } from 'recoil';",
"",
"export const ${1:CollectionData}Selector = selectorFamily({",
" key: '${1:CollectionData}Selector',",
" get: id => async () => {",
" return await dataFetch({id});",
" }",
"});"
],
"description": "Creates a selectorFamily (same as selector, but used to provide parameters)",
"scope": "typescript"
},
"useTranslation": {
"prefix": ["sq-translation", "useTranslation"],
"body": "const { t: strings } = useTranslation();",
"description": "Include the translations",
"scope": "typescriptreact"
}
}
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@
},
"devDependencies": {
"@bendera/vscode-webview-elements": "0.6.2",
"@headlessui/react": "1.4.0",
"@heroicons/react": "1.0.4",
"@iarna/toml": "2.2.3",
"@types/glob": "7.1.3",
"@types/js-yaml": "3.12.1",
Expand All @@ -410,22 +412,21 @@
"gray-matter": "4.0.2",
"html-loader": "1.3.2",
"html-webpack-plugin": "4.5.0",
"lodash.uniqby": "4.7.0",
"mdast-util-from-markdown": "1.0.0",
"postcss": "^8.3.6",
"postcss-loader": "4.3.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"recoil": "^0.4.1",
"style-loader": "2.0.0",
"tailwindcss": "^2.2.7",
"ts-loader": "8.0.3",
"tslint": "6.1.3",
"typescript": "4.0.2",
"wc-react": "github:estruyf/wc-react",
"webpack": "4.44.2",
"webpack-cli": "3.3.12",
"@headlessui/react": "1.4.0",
"@heroicons/react": "1.0.4",
"lodash.uniqby": "4.7.0"
"webpack-cli": "3.3.12"
},
"dependencies": {
"@docsearch/js": "^3.0.0-alpha.40"
Expand Down
7 changes: 5 additions & 2 deletions src/pagesView/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Button } from '../Button';
import { Navigation } from '../Navigation';
import { Grouping } from '.';
import { GroupOption } from '../../constants/GroupOption';
import { ViewSwitch } from './ViewSwitch';

export interface IHeaderProps {
settings: Settings;
Expand Down Expand Up @@ -66,11 +67,11 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({currentTab, curre
</div>

<div className="px-4 flex flex-col lg:flex-row items-center border-b border-gray-200 dark:border-whisper-600">
<div className={`w-full`}>
<div className={`w-full lg:w-auto`}>
<Navigation currentTab={currentTab} totalPages={totalPages} switchTab={switchTab} />
</div>

<div className={`my-4 lg:my-0 w-full flex items-center justify-between order-first lg:order-last `}>
<div className={`my-4 lg:my-0 w-full flex items-center justify-end space-x-4 lg:space-x-6 xl:space-x-8 order-first lg:order-last`}>
<Folders crntFolder={crntFolder} folders={folders} switchFolder={switchFolder} />

<Filter label={`Tag filter`} activeItem={crntTag} items={settings.tags} onClick={switchTag} />
Expand All @@ -80,6 +81,8 @@ export const Header: React.FunctionComponent<IHeaderProps> = ({currentTab, curre
<Grouping group={crntGroup} switchGroup={switchGroup} />

<Sorting currentSorting={currentSorting} switchSorting={switchSorting} />

<ViewSwitch />
</div>
</div>
</div>
Expand Down
30 changes: 30 additions & 0 deletions src/pagesView/components/Header/ViewSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react';
import { useRecoilState } from 'recoil';
import { ViewAtom, ViewType } from '../../state';
import { ViewGridIcon, ViewListIcon } from '@heroicons/react/solid';
import { STORAGE_VIEW_TYPE } from '../../constants/Storage';

export interface IViewSwitchProps {}

export const ViewSwitch: React.FunctionComponent<IViewSwitchProps> = (props: React.PropsWithChildren<IViewSwitchProps>) => {
const [ view, setView ] = useRecoilState(ViewAtom);

const toggleView = () => {
const newView = view === ViewType.Grid ? ViewType.List : ViewType.Grid;
window.localStorage.setItem(STORAGE_VIEW_TYPE, newView.toString());
setView(newView);
};

return (
<div className={`flex rounded-sm bg-vulcan-50 lg:mb-1`}>
<button className={`flex items-center p-2 rounded-l-sm ${view === ViewType.Grid ? 'bg-teal-500 text-vulcan-500' : 'text-whisper-500'}`} onClick={toggleView}>
<ViewGridIcon className={`w-4 h-4`} />
<span className={`sr-only`}>Change to grid</span>
</button>
<button className={`flex items-center p-2 rounded-r-sm ${view === ViewType.List ? 'bg-teal-500 text-vulcan-500' : 'text-whisper-500'}`} onClick={toggleView}>
<ViewListIcon className={`w-4 h-4`} />
<span className={`sr-only`}>Change to list</span>
</button>
</div>
);
};
82 changes: 56 additions & 26 deletions src/pagesView/components/Item.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,77 @@
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { MessageHelper } from '../../helpers/MessageHelper';
import { MarkdownIcon } from '../../viewpanel/components/Icons/MarkdownIcon';
import { DashboardMessage } from '../DashboardMessage';
import { Page } from '../models/Page';
import { ViewSelector, ViewType } from '../state';
import { DateField } from './DateField';
import { Status } from './Status';

export interface IItemProps extends Page {}

export const Item: React.FunctionComponent<IItemProps> = ({ fmFilePath, date, title, draft, description, preview }: React.PropsWithChildren<IItemProps>) => {
const view = useRecoilValue(ViewSelector);

let className = '';
if (view === ViewType.Grid) {
className = `grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8`;
} else if (view === ViewType.List) {
className = `divide-y divide-vulcan-200`;
}

const openFile = () => {
MessageHelper.sendMessage(DashboardMessage.openFile, fmFilePath);
};

return (
<li className="relative">
<button className={`group cursor-pointer flex flex-wrap items-start content-start h-full w-full bg-gray-50 dark:bg-vulcan-200 text-vulcan-500 dark:text-whisper-500 text-left overflow-hidden shadow-md hover:shadow-xl dark:hover:bg-vulcan-100`}
onClick={openFile}>
<div className="relative h-36 w-full overflow-hidden border-b border-gray-100 dark:border-vulcan-100 dark:group-hover:border-vulcan-200">
{
preview ? (
<img src={`${preview}`} alt={title} className="absolute inset-0 h-full w-full object-cover" loading="lazy" />
) : (
<div className={`flex items-center justify-center bg-whisper-500 dark:bg-vulcan-200 dark:group-hover:bg-vulcan-100`}>
<MarkdownIcon className={`h-32 text-vulcan-100 dark:text-whisper-100`} />
</div>
)
}
</div>

<div className="p-4 w-full">
<div className={`flex justify-between items-center`}>
<Status draft={!!draft} />
if (view === ViewType.Grid) {
return (
<li className="relative">
<button className={`group cursor-pointer flex flex-wrap items-start content-start h-full w-full bg-gray-50 dark:bg-vulcan-200 text-vulcan-500 dark:text-whisper-500 text-left overflow-hidden shadow-md hover:shadow-xl dark:hover:bg-vulcan-100`}
onClick={openFile}>
<div className="relative h-36 w-full overflow-hidden border-b border-gray-100 dark:border-vulcan-100 dark:group-hover:border-vulcan-200">
{
preview ? (
<img src={`${preview}`} alt={title} className="absolute inset-0 h-full w-full object-cover" loading="lazy" />
) : (
<div className={`flex items-center justify-center bg-whisper-500 dark:bg-vulcan-200 dark:group-hover:bg-vulcan-100`}>
<MarkdownIcon className={`h-32 text-vulcan-100 dark:text-whisper-100`} />
</div>
)
}
</div>

<div className="p-4 w-full">
<div className={`flex justify-between items-center`}>
<Status draft={!!draft} />

<DateField value={date} />
</div>

<h2 className="mt-2 mb-2 font-bold">{title}</h2>

<p className="text-xs text-vulcan-200 dark:text-whisper-800">{description}</p>
</div>
</button>
</li>
);
} else if (view === ViewType.List) {
return (
<li className="relative">
<button className={`px-5 cursor-pointer w-full text-left grid grid-cols-12 gap-x-4 sm:gap-x-6 xl:gap-x-8 py-2 border-b border-vulcan-50 hover:bg-vulcan-50 hover:bg-opacity-70`} onClick={openFile}>
<div className="col-span-8 font-bold truncate">
{title}
</div>
<div className="col-span-2">
<DateField value={date} />
</div>
<div className="col-span-2">
<Status draft={!!draft} />
</div>
</button>
</li>
);
}

<h2 className="mt-2 mb-2 font-bold">{title}</h2>

<p className="text-xs text-vulcan-200 dark:text-whisper-800">{description}</p>
</div>
</button>
</li>
);
return null;
};
28 changes: 27 additions & 1 deletion src/pagesView/components/List.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
import * as React from 'react';
import { useRecoilValue } from 'recoil';
import { ViewSelector, ViewType } from '../state';

export interface IListProps {}

export const List: React.FunctionComponent<IListProps> = ({children}: React.PropsWithChildren<IListProps>) => {
const view = useRecoilValue(ViewSelector);

let className = '';
if (view === ViewType.Grid) {
className = `grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8`;
} else if (view === ViewType.List) {
className = `-mx-5`;
}

return (
<ul role="list" className="grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-3 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8">
<ul role="list" className={className}>
{view === ViewType.List && (
<li className="px-5 relative uppercase text-vulcan-100 dark:text-whisper-900 py-2 border-b border-vulcan-50">
<div className={`grid grid-cols-12 gap-x-4 sm:gap-x-6 xl:gap-x-8`}>
<div className="col-span-8">
Title
</div>
<div className="col-span-2">
Date
</div>
<div className="col-span-2">
Status
</div>
</div>
</li>
)}
{children}
</ul>
);
Expand Down
1 change: 1 addition & 0 deletions src/pagesView/constants/Storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const STORAGE_VIEW_TYPE = 'FrontMatter:ListViewType';
3 changes: 2 additions & 1 deletion src/pagesView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from "react";
import { render } from "react-dom";
import { RecoilRoot } from "recoil";
import { Dashboard } from "./components/Dashboard";

import './styles.css';
Expand All @@ -12,4 +13,4 @@ declare const acquireVsCodeApi: <T = unknown>() => {

const elm = document.querySelector("#app");
const welcome = elm?.getAttribute("data-showWelcome");
render(<Dashboard showWelcome={!!welcome} />, elm);
render(<RecoilRoot><Dashboard showWelcome={!!welcome} /></RecoilRoot>, elm);
14 changes: 14 additions & 0 deletions src/pagesView/state/atom/ViewAtom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { atom } from 'recoil';
import { STORAGE_VIEW_TYPE } from '../../constants/Storage';

export enum ViewType {
Grid = 1,
List
}

const defaultView: number = parseInt(window.localStorage.getItem(STORAGE_VIEW_TYPE) as string);

export const ViewAtom = atom<ViewType>({
key: 'ViewAtom',
default: isNaN(defaultView) ? ViewType.Grid : defaultView
});
1 change: 1 addition & 0 deletions src/pagesView/state/atom/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ViewAtom';
2 changes: 2 additions & 0 deletions src/pagesView/state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './atom';
export * from './selectors';
9 changes: 9 additions & 0 deletions src/pagesView/state/selectors/ViewSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { selector } from 'recoil';
import { ViewAtom } from '..';

export const ViewSelector = selector({
key: 'ViewSelector',
get: ({get}) => {
return get(ViewAtom);
}
});
1 change: 1 addition & 0 deletions src/pagesView/state/selectors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ViewSelector';

1 comment on commit b8dee7a

@vercel
Copy link

@vercel vercel bot commented on b8dee7a Sep 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.