Compare commits
9 Commits
update-fla
...
@portaljs/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9482483b51 | ||
|
|
8d74fd9844 | ||
|
|
3ae685253b | ||
|
|
56cb6e7912 | ||
|
|
71716ab018 | ||
|
|
06d39779ce | ||
|
|
aec67de35c | ||
|
|
68fbf2cda6 | ||
|
|
83fd7727ba |
1572
package-lock.json
generated
1572
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,11 @@
|
|||||||
# @portaljs/components
|
# @portaljs/components
|
||||||
|
|
||||||
|
## 0.4.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#1022](https://github.com/datopian/portaljs/pull/1022) [`83fd7727`](https://github.com/datopian/portaljs/commit/83fd7727bafb4902218777597e9848a3e3a71d87) Thanks [@luccasmmg](https://github.com/luccasmmg)! - FlatUiTables now accepts a bytes param and a parsingConfig param for CSV links
|
||||||
|
|
||||||
## 0.3.2
|
## 0.3.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@portaljs/components",
|
"name": "@portaljs/components",
|
||||||
"version": "0.3.2",
|
"version": "0.4.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "https://portaljs.org",
|
"description": "https://portaljs.org",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
@@ -5,22 +5,20 @@ import LoadingSpinner from './LoadingSpinner';
|
|||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export async function getCsv(url: string, corsProxy?: string) {
|
export async function getCsv(url: string, bytes) {
|
||||||
if (corsProxy) {
|
|
||||||
url = corsProxy + url;
|
|
||||||
}
|
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Range: 'bytes=0-5132288',
|
Range: `bytes=0-${bytes}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseCsv(file: string): Promise<any> {
|
export async function parseCsv(file: string, parsingConfig): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Papa.parse(file, {
|
Papa.parse(file, {
|
||||||
|
...parsingConfig,
|
||||||
header: true,
|
header: true,
|
||||||
dynamicTyping: true,
|
dynamicTyping: true,
|
||||||
skipEmptyLines: true,
|
skipEmptyLines: true,
|
||||||
@@ -41,25 +39,28 @@ export interface FlatUiTableProps {
|
|||||||
url?: string;
|
url?: string;
|
||||||
data?: { [key: string]: number | string }[];
|
data?: { [key: string]: number | string }[];
|
||||||
rawCsv?: string;
|
rawCsv?: string;
|
||||||
corsProxy?: string;
|
|
||||||
randomId?: number;
|
randomId?: number;
|
||||||
|
bytes: number;
|
||||||
|
parsingConfig: any;
|
||||||
}
|
}
|
||||||
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
|
export const FlatUiTable: React.FC<FlatUiTableProps> = ({
|
||||||
url,
|
url,
|
||||||
data,
|
data,
|
||||||
rawCsv,
|
rawCsv,
|
||||||
corsProxy,
|
bytes = 5132288,
|
||||||
|
parsingConfig = {},
|
||||||
}) => {
|
}) => {
|
||||||
const randomId = Math.random();
|
const randomId = Math.random();
|
||||||
return (
|
return (
|
||||||
// Provide the client to your App
|
// Provide the client to your App
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<TableInner
|
<TableInner
|
||||||
corsProxy={corsProxy}
|
bytes={bytes}
|
||||||
url={url}
|
url={url}
|
||||||
data={data}
|
data={data}
|
||||||
rawCsv={rawCsv}
|
rawCsv={rawCsv}
|
||||||
randomId={randomId}
|
randomId={randomId}
|
||||||
|
parsingConfig={parsingConfig}
|
||||||
/>
|
/>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
@@ -69,8 +70,9 @@ const TableInner: React.FC<FlatUiTableProps> = ({
|
|||||||
url,
|
url,
|
||||||
data,
|
data,
|
||||||
rawCsv,
|
rawCsv,
|
||||||
corsProxy,
|
|
||||||
randomId,
|
randomId,
|
||||||
|
bytes,
|
||||||
|
parsingConfig,
|
||||||
}) => {
|
}) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
return (
|
return (
|
||||||
@@ -81,12 +83,16 @@ const TableInner: React.FC<FlatUiTableProps> = ({
|
|||||||
}
|
}
|
||||||
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
|
const { data: csvString, isLoading: isDownloadingCSV } = useQuery(
|
||||||
['dataCsv', url, randomId],
|
['dataCsv', url, randomId],
|
||||||
() => getCsv(url as string, corsProxy),
|
() => getCsv(url as string, bytes),
|
||||||
{ enabled: !!url }
|
{ enabled: !!url }
|
||||||
);
|
);
|
||||||
const { data: parsedData, isLoading: isParsing } = useQuery(
|
const { data: parsedData, isLoading: isParsing } = useQuery(
|
||||||
['dataPreview', csvString, randomId],
|
['dataPreview', csvString, randomId],
|
||||||
() => parseCsv(rawCsv ? (rawCsv as string) : (csvString as string)),
|
() =>
|
||||||
|
parseCsv(
|
||||||
|
rawCsv ? (rawCsv as string) : (csvString as string),
|
||||||
|
parsingConfig
|
||||||
|
),
|
||||||
{ enabled: rawCsv ? true : !!csvString }
|
{ enabled: rawCsv ? true : !!csvString }
|
||||||
);
|
);
|
||||||
if (isParsing || isDownloadingCSV)
|
if (isParsing || isDownloadingCSV)
|
||||||
|
|||||||
@@ -9,17 +9,24 @@ const meta: Meta = {
|
|||||||
tags: ['autodocs'],
|
tags: ['autodocs'],
|
||||||
argTypes: {
|
argTypes: {
|
||||||
data: {
|
data: {
|
||||||
description: "Data to be displayed in the table, must be setup as an array of key value pairs"
|
description:
|
||||||
|
'Data to be displayed in the table, must be setup as an array of key value pairs',
|
||||||
},
|
},
|
||||||
csv: {
|
csv: {
|
||||||
description: "CSV data as string.",
|
description: 'CSV data as string.',
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
description: "Fetch the data from a CSV file remotely. only the first 5MB of data will be displayed"
|
description:
|
||||||
|
'Fetch the data from a CSV file remotely. only the first 5MB of data will be displayed',
|
||||||
|
},
|
||||||
|
bytes: {
|
||||||
|
description:
|
||||||
|
'Fetch the data from a CSV file remotely. only the first <bytes> of data will be displayed',
|
||||||
|
},
|
||||||
|
parsingConfig: {
|
||||||
|
description:
|
||||||
|
'Configuration for parsing the CSV data. See https://www.papaparse.com/docs#config for more details',
|
||||||
},
|
},
|
||||||
corsProxy: {
|
|
||||||
description: "Optionally you cant set a CORS Proxy to which all your requests you be redirected"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,7 +36,7 @@ type Story = StoryObj<FlatUiTableProps>;
|
|||||||
|
|
||||||
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
|
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
|
||||||
export const FromColumnsAndData: Story = {
|
export const FromColumnsAndData: Story = {
|
||||||
name: "Table data",
|
name: 'Table data',
|
||||||
args: {
|
args: {
|
||||||
data: [
|
data: [
|
||||||
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
|
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 35 },
|
||||||
@@ -44,20 +51,19 @@ export const FromColumnsAndData: Story = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const FromRawCSV: Story = {
|
export const FromRawCSV: Story = {
|
||||||
name: "Table from raw CSV",
|
name: 'Table from raw CSV',
|
||||||
args: {
|
args: {
|
||||||
rawCsv: `
|
rawCsv: `
|
||||||
Year,Temp Anomaly
|
Year,Temp Anomaly
|
||||||
1850,-0.418
|
1850,-0.418
|
||||||
2020,0.923
|
2020,0.923
|
||||||
`
|
`,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FromURL: Story = {
|
export const FromURL: Story = {
|
||||||
name: "Table from URL",
|
name: 'Table from URL',
|
||||||
args: {
|
args: {
|
||||||
url: "https://raw.githubusercontent.com/datasets/finance-vix/main/data/vix-daily.csv"
|
url: 'https://ckan-dev.sse.datopian.com/datastore/dump/601c9cf0-595e-46d8-88fc-d1ab2904e2db',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const config: StorybookConfig = {
|
|||||||
addons: [
|
addons: [
|
||||||
'@storybook/addon-essentials',
|
'@storybook/addon-essentials',
|
||||||
'@storybook/addon-interactions',
|
'@storybook/addon-interactions',
|
||||||
|
'@storybook/addon-a11y',
|
||||||
'@nrwl/react/plugins/storybook',
|
'@nrwl/react/plugins/storybook',
|
||||||
'storybook-tailwind-dark-mode'
|
'storybook-tailwind-dark-mode'
|
||||||
],
|
],
|
||||||
@@ -12,6 +13,9 @@ const config: StorybookConfig = {
|
|||||||
name: '@storybook/react-webpack5',
|
name: '@storybook/react-webpack5',
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
|
docs: {
|
||||||
|
autodocs: 'tag',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import './tailwind-imports.css';
|
import './tailwind-imports.css';
|
||||||
|
|
||||||
const preview = {
|
const preview = {
|
||||||
|
parameters: {
|
||||||
|
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||||
|
},
|
||||||
globalTypes: {
|
globalTypes: {
|
||||||
darkMode: {
|
darkMode: {
|
||||||
defaultValue: false, // Enable dark mode by default on all stories
|
defaultValue: false, // Enable dark mode by default on all stories
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @portaljs/core
|
# @portaljs/core
|
||||||
|
|
||||||
|
## 1.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [`8d74fd98`](https://github.com/datopian/portaljs/commit/8d74fd98443bb3c0a28325be27b41281b59f3581) Thanks [@olayway](https://github.com/olayway)! - Minor footer style fixes.
|
||||||
|
|
||||||
## 1.0.6
|
## 1.0.6
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@portaljs/core",
|
"name": "@portaljs/core",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"description": "Core Portal.JS components, configs and utils.",
|
"description": "Core Portal.JS components, configs and utils.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -46,10 +46,13 @@
|
|||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
"mdx-mermaid": "2.0.0-rc7",
|
||||||
"next": "^13.2.1",
|
"next": "^13.2.1",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0"
|
||||||
"mdx-mermaid": "2.0.0-rc7"
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@storybook/addon-a11y": "^7.4.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
packages/core/src/ui/Layout/Footer.stories.tsx
Normal file
47
packages/core/src/ui/Layout/Footer.stories.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { Footer } from './Footer';
|
||||||
|
|
||||||
|
const meta: Meta<typeof Footer> = {
|
||||||
|
component: Footer,
|
||||||
|
tags: ['autodocs'],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof Footer>;
|
||||||
|
|
||||||
|
export const Basic: Story = {
|
||||||
|
args: {
|
||||||
|
author: {
|
||||||
|
name: "John Doe",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const Links: Story = {
|
||||||
|
args: {
|
||||||
|
links: [
|
||||||
|
{ name: "Link A", href: "#" },
|
||||||
|
{ name: "Link B", href: "#" }
|
||||||
|
],
|
||||||
|
author: {
|
||||||
|
name: "John Doe",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const Logo: Story = {
|
||||||
|
args: {
|
||||||
|
links: [
|
||||||
|
{ name: "Link A", href: "#" },
|
||||||
|
{ name: "Link B", href: "#" }
|
||||||
|
],
|
||||||
|
author: {
|
||||||
|
name: "John Doe",
|
||||||
|
logo: "https://via.placeholder.com/150"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -3,59 +3,77 @@ import Link from "next/link.js";
|
|||||||
import { AuthorConfig, NavLink } from "../types";
|
import { AuthorConfig, NavLink } from "../types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
links: Array<NavLink>;
|
author: AuthorConfig;
|
||||||
author: AuthorConfig;
|
links?: Array<NavLink>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO replace this with some nice tailwindui footer
|
||||||
export const Footer: React.FC<Props> = ({ links, author }) => {
|
export const Footer: React.FC<Props> = ({ links, author }) => {
|
||||||
return (
|
return (
|
||||||
<footer className="bg-background dark:bg-background-dark prose dark:prose-invert max-w-none flex flex-col items-center justify-center w-full h-auto pt-10 pb-20">
|
<footer className="bg-background dark:bg-background-dark text-primary dark:text-primary-dark pt-16 pb-20 px-14 flex flex-col items-center justify-center gap-3">
|
||||||
<div className="flex w-full flex-wrap justify-center">
|
{links && (
|
||||||
{links.map((item) => (
|
<div className="flex w-full flex-wrap justify-center mb-2">
|
||||||
<Link
|
{links.map((item) => (
|
||||||
key={item.href}
|
<Link
|
||||||
href={item.href}
|
key={item.href}
|
||||||
className="inline-flex items-center mx-4 px-1 pt-1 font-regular hover:text-slate-300 no-underline"
|
href={item.href}
|
||||||
>
|
className="inline-flex items-center mx-4 px-1 py-1 text-black hover:text-primary dark:text-white hover:dark:text-primary-dark no-underline font-semibold"
|
||||||
{/* TODO aria-current={item.current ? "page" : undefined} */}
|
>
|
||||||
{item.name}
|
{/* TODO aria-current={item.current ? "page" : undefined} */}
|
||||||
</Link>
|
{item.name}
|
||||||
))}
|
</Link>
|
||||||
</div>
|
))}
|
||||||
<p className="flex items-center justify-center">
|
</div>
|
||||||
Created by
|
)}
|
||||||
<a
|
<p className="flex items-center justify-center gap-2">
|
||||||
href={author.url}
|
<span>Created by</span>
|
||||||
target="_blank"
|
{author.url ? (
|
||||||
rel="noopener noreferrer"
|
<a
|
||||||
className="flex items-center no-underline"
|
href={author.url}
|
||||||
>
|
target="_blank"
|
||||||
{author.logo && (
|
rel="noopener noreferrer"
|
||||||
<img
|
className="flex items-center gap-1 no-underline font-semibold text-black dark:text-white"
|
||||||
src={author.logo}
|
>
|
||||||
alt={author.name}
|
{author.logo && (
|
||||||
className="my-0 mx-1 h-6 block"
|
<img
|
||||||
/>
|
src={author.logo}
|
||||||
)}
|
alt="Logo"
|
||||||
{author.name}
|
className="h-6 block"
|
||||||
</a>
|
/>
|
||||||
</p>
|
)}
|
||||||
<p className="flex items-center justify-center">
|
<span>{author.name}</span>
|
||||||
Made with
|
</a>
|
||||||
<a
|
) : (
|
||||||
href="https://flowershow.app/"
|
<span
|
||||||
target="_blank"
|
className="flex items-center gap-1 no-underline font-semibold text-black dark:text-white"
|
||||||
rel="noopener noreferrer"
|
>
|
||||||
className="flex items-center no-underline"
|
{author.logo && (
|
||||||
>
|
<img
|
||||||
<img
|
src={author.logo}
|
||||||
src="https://flowershow.app/images/logo.svg"
|
alt={author.name}
|
||||||
alt="Flowershow"
|
className="h-6 block"
|
||||||
className="my-0 mx-1 h-6 block"
|
/>
|
||||||
/>
|
)}
|
||||||
Flowershow
|
<span>{author.name}</span>
|
||||||
</a>
|
</span>
|
||||||
</p>
|
)}
|
||||||
</footer>
|
</p>
|
||||||
);
|
<p className="flex items-center justify-center gap-1">
|
||||||
|
<span>Made with</span>
|
||||||
|
<a
|
||||||
|
href="https://flowershow.app/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center gap-1 no-underline font-semibold text-black dark:text-white"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="https://flowershow.app/images/logo.svg"
|
||||||
|
alt="Logo"
|
||||||
|
className="h-6 block"
|
||||||
|
/>
|
||||||
|
<span>Flowershow</span>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export {
|
|||||||
TocSection,
|
TocSection,
|
||||||
EditThisPage,
|
EditThisPage,
|
||||||
useTableOfContents,
|
useTableOfContents,
|
||||||
|
Footer
|
||||||
} from "./Layout";
|
} from "./Layout";
|
||||||
export { Pre } from "./Pre";
|
export { Pre } from "./Pre";
|
||||||
export { CustomLink } from "./Base/CustomLink";
|
export { CustomLink } from "./Base/CustomLink";
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ export interface NavLink {
|
|||||||
|
|
||||||
export interface AuthorConfig {
|
export interface AuthorConfig {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url?: string;
|
||||||
logo: string;
|
logo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// social
|
// social
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @portaljs/remark-embed
|
# @portaljs/remark-embed
|
||||||
|
|
||||||
|
## 1.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [`71716ab0`](https://github.com/datopian/portaljs/commit/71716ab01875f04f51bc23ba551c7a6a9a24a335) Thanks [@olayway](https://github.com/olayway)! - Add support for shortened yt links (https://youtu.be).
|
||||||
|
|
||||||
## 1.0.4
|
## 1.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@portaljs/remark-embed",
|
"name": "@portaljs/remark-embed",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"description": "Converts youtube link in mdx to an iframe embed",
|
"description": "Converts youtube link in mdx to an iframe embed",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -1,14 +1,29 @@
|
|||||||
import { visit } from "unist-util-visit";
|
import { visit } from "unist-util-visit";
|
||||||
|
|
||||||
|
// https://youtu.be/vDuh7vDgGIg
|
||||||
|
|
||||||
|
// TODO write tests!
|
||||||
function transformer(tree) {
|
function transformer(tree) {
|
||||||
visit(tree, "paragraph", (node) => {
|
visit(tree, "paragraph", (node) => {
|
||||||
visit(node, "text", (textNode) => {
|
visit(node, "text", (textNode) => {
|
||||||
if (
|
if (
|
||||||
textNode.value.includes("https://www.youtube.com") &&
|
(textNode.value.includes("https://www.youtube.com") ||
|
||||||
|
textNode.value.includes("https://youtu.be")
|
||||||
|
) &&
|
||||||
!textNode.value.includes("\n")
|
!textNode.value.includes("\n")
|
||||||
) {
|
) {
|
||||||
const urlSplit = textNode.value.split(/[=&]+/);
|
let videoId: string;
|
||||||
const iframeUrl = `https://www.youtube.com/embed/${urlSplit[1]}`;
|
|
||||||
|
if (textNode.value.includes("https://youtu.be")) {
|
||||||
|
// Extract video ID for short YT URLs
|
||||||
|
videoId = textNode.value.split("/").pop();
|
||||||
|
} else {
|
||||||
|
// Extract video ID for full YT URLs
|
||||||
|
const urlSplit = textNode.value.split(/[=&]+/);
|
||||||
|
videoId = urlSplit[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const iframeUrl = `https://www.youtube.com/embed/${videoId}`;
|
||||||
Object.assign(node, {
|
Object.assign(node, {
|
||||||
...node,
|
...node,
|
||||||
type: "element",
|
type: "element",
|
||||||
|
|||||||
BIN
site/content/assets/blog/life-itself-blog-post.png
Normal file
BIN
site/content/assets/blog/life-itself-blog-post.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
site/content/assets/blog/life-itself-categories.png
Normal file
BIN
site/content/assets/blog/life-itself-categories.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 410 KiB |
BIN
site/content/assets/blog/life-itself-latest-blogs.png
Normal file
BIN
site/content/assets/blog/life-itself-latest-blogs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 449 KiB |
BIN
site/content/assets/blog/life-itself-top-picks.png
Normal file
BIN
site/content/assets/blog/life-itself-top-picks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
69
site/content/blog/summer-updates-2023.md
Normal file
69
site/content/blog/summer-updates-2023.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
title: What We Shipped in Jul-Aug 2023
|
||||||
|
authors: ['ola-rubaj']
|
||||||
|
date: 2023-09-2
|
||||||
|
---
|
||||||
|
|
||||||
|
Hey everyone! 👋 Summer has been in full swing, and while I've managed to catch some vacation vibes, I've also been deep into code. I'm super excited to share some of the latest updates and features we've rolled out over the past two months. Let's dive in:
|
||||||
|
|
||||||
|
## 🌷 Flowershow
|
||||||
|
|
||||||
|
https://flowershow.app/
|
||||||
|
|
||||||
|
1. **CLI is old news**: the Flowershow CLI has been deprecated in favor of our new [Flowershow Obsidian plugin](https://github.com/datopian/obsidian-flowershow).
|
||||||
|
|
||||||
|
2. **Self-publishing made even easier**: I wrote a [self-publish tutorial](https://flowershow.app/docs/publish-howto) to guide you through using our Obsidian plugin for publishing your digital garden.
|
||||||
|
|
||||||
|
3. **Cloud-publishing MVP**: The first version of our Flowershow Cloud which aims to make publishing your digital garden notes a breeze! [Check out the overview](https://flowershow.app#cloud-publish) and stay tuned 📻!
|
||||||
|
|
||||||
|
4. **Hydration errors from Obsidian transclusions/note embeddings are fixed**: For now, note transclusions will convert to regular links, but stay tuned — support for note embeds may be on the horizon. [Learn more](https://github.com/datopian/flowershow/issues/545)
|
||||||
|
|
||||||
|
5. **New Obsidian tags list format support**: I added support for Obsidian's new tag list format, so now your notes can be even more organized. [Learn more](https://github.com/datopian/flowershow/issues/543)
|
||||||
|
|
||||||
|
## 🗂️ MarkdownDB
|
||||||
|
|
||||||
|
https://github.com/datopian/markdowndb
|
||||||
|
|
||||||
|
1. **Auto-Publishing to npm**: Changesets now trigger auto-publishing, so we're always up to date.
|
||||||
|
2. **Obsidian-style wiki links**: Extracting wiki links with Obsidian-style shortest paths is supported now.
|
||||||
|
|
||||||
|
## 📚 The Guide
|
||||||
|
|
||||||
|
https://portaljs.org/guide
|
||||||
|
|
||||||
|
I’ve sketched overviews for two upcoming tutorials:
|
||||||
|
|
||||||
|
1. **Collaborating with others on your website**: Learn how to make your website projects a team effort. [See it here](https://portaljs.org/guide#tutorial-3-collaborating-with-others-on-your-website-project)
|
||||||
|
2. **Customising your website and previewing your changes locally**: Customize and preview your site changes locally, without headaches. [See it here](https://portaljs.org/guide#tutorial-4-customising-your-website-locally-and-previewing-your-changes-locally)
|
||||||
|
|
||||||
|
## 🌐 LifeItself.org
|
||||||
|
|
||||||
|
https://lifeitself.org/
|
||||||
|
|
||||||
|
LifeItself.org is our website built on the Flowershow template, and it's been getting some extra care too.
|
||||||
|
|
||||||
|
1. New blog home page layout with:
|
||||||
|
|
||||||
|
- **Team Top Selection**
|
||||||
|
|
||||||
|
![[life-itself-top-picks.png]]
|
||||||
|
|
||||||
|
- **Latest Blog Posts**
|
||||||
|
|
||||||
|
![[life-itself-latest-blogs.png]]
|
||||||
|
|
||||||
|
- And the long awaited filtering by category 🎉
|
||||||
|
|
||||||
|
![[life-itself-categories.png]]
|
||||||
|
|
||||||
|
[👉 Check out the changes!](https://lifeitself.org/blog)
|
||||||
|
|
||||||
|
2. **Blog posts layout revamp**: Refreshed design with share options, reading time estimates, and more.
|
||||||
|
|
||||||
|
![[life-itself-blog-post.png]]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
That wraps it up for now! As always, I'm eager to hear your thoughts and feedback. Feel free to report issues or ask for features on our GitHub repositories. Until next time and happy publishing!
|
||||||
|
|
||||||
|
— Ola Rubaj, Developer at Datopian
|
||||||
Reference in New Issue
Block a user