mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
fork refine
This commit is contained in:
113
documentation/src/components/blog/author-card/index.js
Normal file
113
documentation/src/components/blog/author-card/index.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
import Link from "@docusaurus/Link";
|
||||
import { useBlogPost } from "@docusaurus/theme-common/internal";
|
||||
|
||||
import { Github, Twitter, Linkedin } from "../icons";
|
||||
|
||||
export const AuthorCardWithHook = ({ className }) => {
|
||||
const { metadata } = useBlogPost();
|
||||
|
||||
const author = metadata.authors[0];
|
||||
|
||||
return <AuthorCard author={author} className={className} />;
|
||||
};
|
||||
|
||||
export const AuthorCardWithProps = ({ author, className }) => {
|
||||
return <AuthorCard author={author} className={className} />;
|
||||
};
|
||||
|
||||
const AuthorCard = ({ author }) => {
|
||||
const authorHasSocialInfo =
|
||||
author.github || author.twitter || author.linkedin;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"px-4",
|
||||
"blog-md:px-7",
|
||||
"blog-2xl:px-0",
|
||||
"max-w-[640px]",
|
||||
"blog-md:max-w-screen-blog-md",
|
||||
"blog-2xl:max-w-screen-blog-md",
|
||||
"w-full",
|
||||
"mx-auto",
|
||||
)}
|
||||
>
|
||||
<div className={clsx("flex", "justify-between", "items-center")}>
|
||||
<div
|
||||
className={clsx(
|
||||
"w-full",
|
||||
"flex items-center justify-between flex-wrap",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx("flex items-center", "gap-2 sm:gap-6")}
|
||||
>
|
||||
<Link
|
||||
to={`/blog/author/${author?.key}`}
|
||||
itemProp="url"
|
||||
className="flex-shrink-0"
|
||||
>
|
||||
<img
|
||||
src={author?.imageURL}
|
||||
alt={author?.name}
|
||||
loading="lazy"
|
||||
className={clsx(
|
||||
"flex flex-shrink-0",
|
||||
"h-12 w-12",
|
||||
"blog-sm:h-[88px] blog-sm:w-[88px]",
|
||||
"blog-md:h-[120px] blog-md:w-[120px]",
|
||||
"rounded-full object-cover",
|
||||
)}
|
||||
/>
|
||||
</Link>
|
||||
<div
|
||||
className={clsx(
|
||||
"not-prose flex flex-col justify-between",
|
||||
)}
|
||||
>
|
||||
<h1
|
||||
className={clsx(
|
||||
"text-xl sm:text-[40px] sm:leading-[56px]",
|
||||
"m-0 p-0 pb-2 font-bold text-gray-900 dark:text-gray-200",
|
||||
)}
|
||||
>
|
||||
{author?.name}
|
||||
</h1>
|
||||
<div
|
||||
className={clsx(
|
||||
"text-xs sm:text-base",
|
||||
"text-gray-600 dark:text-gray-400",
|
||||
)}
|
||||
>
|
||||
{author?.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{authorHasSocialInfo && (
|
||||
<div className="flex justify-center gap-3">
|
||||
{author?.github && (
|
||||
<Link to={author?.github}>
|
||||
<Github className="h-6 w-6" />
|
||||
</Link>
|
||||
)}
|
||||
{author?.twitter && (
|
||||
<Link to={author?.twitter}>
|
||||
<Twitter className="h-6 w-6" />
|
||||
</Link>
|
||||
)}
|
||||
{author?.linkedin && (
|
||||
<Link to={author?.linkedin}>
|
||||
<Linkedin className="h-6 w-6" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-b border-gray-200 dark:border-gray-700 mb-8" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
60
documentation/src/components/blog/author-page/index.js
Normal file
60
documentation/src/components/blog/author-page/index.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from "react";
|
||||
import BlogLayout from "@theme/BlogLayout";
|
||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||
import { PageMetadata } from "@docusaurus/theme-common";
|
||||
import SearchMetadata from "@theme/SearchMetadata";
|
||||
import BlogPostItems from "@theme/BlogPostItems";
|
||||
|
||||
import { AuthorCardWithProps } from "@site/src/components/blog";
|
||||
import clsx from "clsx";
|
||||
|
||||
const BlogListPageMetadata = () => {
|
||||
const {
|
||||
siteConfig: { title, tagline },
|
||||
} = useDocusaurusContext();
|
||||
return (
|
||||
<>
|
||||
<PageMetadata title={title} description={tagline} />
|
||||
<SearchMetadata tag="author_blog_posts_list" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const AuthorPage = (props) => {
|
||||
const { items } = props;
|
||||
|
||||
const author = items[0].content.metadata.authors[0];
|
||||
|
||||
return (
|
||||
<>
|
||||
<BlogListPageMetadata />
|
||||
<BlogLayout showSidebarBanner={false}>
|
||||
<div className="h-12" />
|
||||
<AuthorCardWithProps author={author} />
|
||||
<div
|
||||
className={clsx(
|
||||
"px-4",
|
||||
"max-w-[512px]",
|
||||
"blog-md:px-7",
|
||||
"blog-md:max-w-screen-blog-md",
|
||||
"blog-2xl:px-0",
|
||||
"blog-2xl:max-w-screen-blog-md",
|
||||
"w-full",
|
||||
"mx-auto",
|
||||
)}
|
||||
>
|
||||
<h1 className="text-4xl !mb-0 px-0 lg:px-4">Posts</h1>
|
||||
</div>
|
||||
<div className={clsx("px-4", "blog-md:px-7", "blog-2xl:px-0")}>
|
||||
<BlogPostItems
|
||||
items={items}
|
||||
showTitle={false}
|
||||
isAuthorPage={true}
|
||||
/>
|
||||
</div>
|
||||
</BlogLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthorPage;
|
||||
155
documentation/src/components/blog/blog-post-page/index.js
Normal file
155
documentation/src/components/blog/blog-post-page/index.js
Normal file
@@ -0,0 +1,155 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
import { useBlogPost } from "@docusaurus/theme-common/internal";
|
||||
import { blogPostContainerID } from "@docusaurus/utils-common";
|
||||
import MDXContent from "@theme/MDXContent";
|
||||
import BlogPostItemContainer from "@theme/BlogPostItem/Container";
|
||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||
import {
|
||||
LinkedinShareButton,
|
||||
RedditShareButton,
|
||||
TwitterShareButton,
|
||||
TwitterIcon,
|
||||
RedditIcon,
|
||||
LinkedinIcon,
|
||||
} from "react-share";
|
||||
import clsx from "clsx";
|
||||
|
||||
import { Date, ReadingTime } from "@site/src/components/blog/common";
|
||||
import { BannerRandom } from "@site/src/components/banner/banner-random";
|
||||
|
||||
import { Twitter } from "../icons";
|
||||
|
||||
export const BlogPostPageView = ({ children }) => {
|
||||
const { metadata, isBlogPostPage } = useBlogPost();
|
||||
const {
|
||||
permalink,
|
||||
title,
|
||||
date,
|
||||
formattedDate,
|
||||
readingTime,
|
||||
frontMatter,
|
||||
tags,
|
||||
description,
|
||||
authors,
|
||||
} = metadata;
|
||||
const author = authors[0];
|
||||
|
||||
const {
|
||||
siteConfig: { url },
|
||||
} = useDocusaurusContext();
|
||||
|
||||
return (
|
||||
<BlogPostItemContainer
|
||||
className={clsx(
|
||||
"py-10",
|
||||
"px-4 sm:px-0",
|
||||
"blog-sm:py-12",
|
||||
"blog-md:py-16",
|
||||
"w-full",
|
||||
"mx-auto",
|
||||
"max-w-[512px]",
|
||||
"blog-sm:max-w-screen-blog-sm",
|
||||
"blog-lg:max-w-screen-content-2xl",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex",
|
||||
"justify-between",
|
||||
"items-center",
|
||||
"blog-sm:px-6",
|
||||
)}
|
||||
>
|
||||
<Link
|
||||
to="/blog"
|
||||
className={clsx("!text-gray-500 text-sm no-underline")}
|
||||
>
|
||||
← Back to blog
|
||||
</Link>
|
||||
<div className="flex items-center space-x-2 px-2 py-1">
|
||||
<span className="text-gray-500 text-sm">Share on</span>
|
||||
<TwitterShareButton
|
||||
windowWidth={750}
|
||||
windowHeight={800}
|
||||
url={url + permalink}
|
||||
className="flex"
|
||||
title={title}
|
||||
hashtags={tags.map((tag) => tag.label)}
|
||||
>
|
||||
<Twitter width={26} height={26} />
|
||||
</TwitterShareButton>
|
||||
<RedditShareButton
|
||||
className="flex"
|
||||
windowWidth={750}
|
||||
windowHeight={600}
|
||||
url={url + permalink}
|
||||
title={title}
|
||||
>
|
||||
<RedditIcon size={26} round />
|
||||
</RedditShareButton>
|
||||
<LinkedinShareButton
|
||||
url={url + permalink}
|
||||
title={title}
|
||||
source={url}
|
||||
summary={description}
|
||||
className="flex"
|
||||
>
|
||||
<LinkedinIcon size={26} round />
|
||||
</LinkedinShareButton>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
className="mb-2 w-full rounded-xl"
|
||||
src={`https://refine-web.imgix.net${frontMatter.image?.replace(
|
||||
"https://refine.ams3.cdn.digitaloceanspaces.com",
|
||||
"",
|
||||
)}?w=800`}
|
||||
alt={title}
|
||||
/>
|
||||
</div>
|
||||
<div className="blog-sm:px-6">
|
||||
<div className="mb-6 text-sm">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex",
|
||||
"justify-between",
|
||||
"sm:flex-row flex-col",
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-center items-center gap-2"></div>
|
||||
<div className="flex items-center gap-2 text-gray-600 dark:text-gray-400">
|
||||
<Date date={date} formattedDate={formattedDate} />
|
||||
{typeof readingTime !== "undefined" && (
|
||||
<>
|
||||
<span className="w-[4px] h-[4px] rounded-full bg-gray-600 dark:bg-gray-500"></span>
|
||||
<ReadingTime readingTime={readingTime} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="m-6 mb-12">
|
||||
<BannerRandom />
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="text-xl md:text-4xl" itemProp="headline">
|
||||
{isBlogPostPage ? (
|
||||
title
|
||||
) : (
|
||||
<Link itemProp="url" to={permalink}>
|
||||
{title}
|
||||
</Link>
|
||||
)}
|
||||
</h1>
|
||||
<div
|
||||
id={blogPostContainerID}
|
||||
className="markdown"
|
||||
itemProp="articleBody"
|
||||
>
|
||||
<MDXContent>{children}</MDXContent>
|
||||
</div>
|
||||
</div>
|
||||
</BlogPostItemContainer>
|
||||
);
|
||||
};
|
||||
9
documentation/src/components/blog/common/date.js
Normal file
9
documentation/src/components/blog/common/date.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
export function Date({ date, formattedDate }) {
|
||||
return (
|
||||
<time dateTime={date} itemProp="datePublished">
|
||||
{formattedDate}
|
||||
</time>
|
||||
);
|
||||
}
|
||||
3
documentation/src/components/blog/common/index.js
Normal file
3
documentation/src/components/blog/common/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./date";
|
||||
export * from "./reading-time";
|
||||
export * from "./spacer";
|
||||
27
documentation/src/components/blog/common/reading-time.js
Normal file
27
documentation/src/components/blog/common/reading-time.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
import { usePluralForm } from "@docusaurus/theme-common";
|
||||
import { translate } from "@docusaurus/Translate";
|
||||
|
||||
function useReadingTimePlural() {
|
||||
const { selectMessage } = usePluralForm();
|
||||
return (readingTimeFloat) => {
|
||||
const readingTime = Math.ceil(readingTimeFloat);
|
||||
return selectMessage(
|
||||
readingTime,
|
||||
translate(
|
||||
{
|
||||
id: "theme.blog.post.readingTime.plurals",
|
||||
description:
|
||||
'Pluralized label for "{readingTime} min read". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
|
||||
message: "One min read|{readingTime} min read",
|
||||
},
|
||||
{ readingTime },
|
||||
),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function ReadingTime({ readingTime }) {
|
||||
const readingTimePlural = useReadingTimePlural();
|
||||
return <>{readingTimePlural(readingTime)}</>;
|
||||
}
|
||||
5
documentation/src/components/blog/common/spacer.js
Normal file
5
documentation/src/components/blog/common/spacer.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React from "react";
|
||||
|
||||
export function Spacer() {
|
||||
return <>{" · "}</>;
|
||||
}
|
||||
31
documentation/src/components/blog/discord-banner/index.js
Normal file
31
documentation/src/components/blog/discord-banner/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
|
||||
const DiscordBanner = () => {
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-0 h-auto md:h-[150px] bg-[#5865F2] w-full rounded-2xl py-5 px-5 md:px-12">
|
||||
<div className="flex items-center gap-16">
|
||||
<img
|
||||
className="hidden md:block"
|
||||
src="/img/blog-static/discord-banner.png"
|
||||
alt="Discord Logo"
|
||||
/>
|
||||
<div className="text-white font-montserrat font-bold max-w-md text-center md:text-left">
|
||||
<h1 className="text-2xl uppercase leading-tight mb-0 font-montserrat">
|
||||
Join to refine discord server
|
||||
</h1>
|
||||
<p className="mb-0 text-base">
|
||||
to get help, share ideas, and discuss the latest news.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Link to="https://discord.gg/refine">
|
||||
<button className="bg-transparent text-white font-bold py-2 px-4 rounded-lg h-12 w-44 border-white cursor-pointer font-montserrat uppercase text-xl border-solid active:scale-[0.99]">
|
||||
Join Us
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscordBanner;
|
||||
@@ -0,0 +1,108 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
import { useBlogPost } from "@docusaurus/theme-common/internal";
|
||||
import BlogPostItemContainer from "@theme/BlogPostItem/Container";
|
||||
|
||||
import { Date } from "@site/src/components/blog/common";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const FeaturedBlogPostItem = () => {
|
||||
const { metadata } = useBlogPost();
|
||||
const {
|
||||
permalink,
|
||||
title,
|
||||
date,
|
||||
formattedDate,
|
||||
frontMatter,
|
||||
description,
|
||||
tags,
|
||||
} = metadata;
|
||||
|
||||
const author = metadata.authors[0];
|
||||
|
||||
return (
|
||||
<BlogPostItemContainer>
|
||||
<Link itemProp="url" to={permalink}>
|
||||
<div className="not-prose relative m-0 h-40 hover:brightness-90 md:h-64">
|
||||
<img
|
||||
src={`https://refine-web.imgix.net${frontMatter.image?.replace(
|
||||
"https://refine.ams3.cdn.digitaloceanspaces.com",
|
||||
"",
|
||||
)}?h=256`}
|
||||
alt={title}
|
||||
className="absolute inset-0 mt-0 h-full w-full rounded-[10px] object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="px-4 py-4 md:px-6 md:py-6">
|
||||
<div
|
||||
className={clsx(
|
||||
"mb-2 gap-1 md:mb-4 2xl:mb-6",
|
||||
"flex flex-wrap items-center",
|
||||
)}
|
||||
>
|
||||
{tags.map((tag) => (
|
||||
<Link
|
||||
className={clsx(
|
||||
"text-xs",
|
||||
"bg-gray-100 dark:bg-gray-700",
|
||||
"text-gray-600 hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-400",
|
||||
"no-underline",
|
||||
"rounded",
|
||||
"px-2 py-1",
|
||||
)}
|
||||
href={tag.permalink}
|
||||
key={tag.permalink}
|
||||
>
|
||||
{tag.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="mb-2 md:mb-4 2xl:mb-6">
|
||||
<Link
|
||||
itemProp="url"
|
||||
to={permalink}
|
||||
className="no-underline hover:no-underline"
|
||||
rel="noopener dofollow"
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
"mb-2 md:mb-4 2xl:mb-6",
|
||||
"text-gray-700 dark:text-gray-200",
|
||||
"text-sm sm:text-2xl 2xl:text-[32px] 2xl:leading-10",
|
||||
"font-lg",
|
||||
"font-bold",
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
</Link>
|
||||
<div
|
||||
className={clsx(
|
||||
"line-clamp-3",
|
||||
"text-gray-700 dark:text-gray-300",
|
||||
"text-xs md:text-base 2xl:text-xl",
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={clsx(
|
||||
"text-gray-600 hover:text-gray-600",
|
||||
"dark:text-gray-400 hover:dark:text-gray-400",
|
||||
"text-xs 2xl:text-base",
|
||||
"leading-6",
|
||||
"no-underline",
|
||||
)}
|
||||
>
|
||||
<Date date={date} formattedDate={formattedDate} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</BlogPostItemContainer>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import { BlogPostProvider } from "@docusaurus/theme-common/internal";
|
||||
|
||||
import { FeaturedBlogPostItem } from "../featured-blog-post-item";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const FeaturedBlogPostItems = ({ items }) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"py-10",
|
||||
"px-4",
|
||||
"max-w-[512px]",
|
||||
"blog-md:px-7",
|
||||
"blog-md:max-w-screen-blog-md",
|
||||
"blog-2xl:px-0",
|
||||
"blog-2xl:max-w-screen-blog-md",
|
||||
"w-full",
|
||||
"mx-auto",
|
||||
"not-prose",
|
||||
)}
|
||||
>
|
||||
<h2
|
||||
className={clsx(
|
||||
"m-0 p-0",
|
||||
"blog-lg:mb-12 blog-md:mb-8 mb-10",
|
||||
"text-xl blog-sm:text-4xl blog-lg:text-5xl",
|
||||
"text-gray-900 dark:text-gray-0",
|
||||
"px-0 blog-sm:px-6",
|
||||
"font-semibold",
|
||||
)}
|
||||
>
|
||||
Featured Posts
|
||||
</h2>
|
||||
|
||||
<div className="grid grid-cols-1 blog-md:grid-cols-2 blog-lg:gap-12 gap-8">
|
||||
{items.map(({ content: BlogPostContent }) => (
|
||||
<BlogPostProvider
|
||||
key={BlogPostContent.metadata.permalink}
|
||||
content={BlogPostContent}
|
||||
>
|
||||
<FeaturedBlogPostItem />
|
||||
</BlogPostProvider>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
74
documentation/src/components/blog/github-banner/index.js
Normal file
74
documentation/src/components/blog/github-banner/index.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
|
||||
import { CloudTipIcon, GithubIcon } from "../../landing/icons";
|
||||
|
||||
const token = "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";
|
||||
const repo = "refine";
|
||||
const org = "pankod";
|
||||
|
||||
const GithubBanner = () => {
|
||||
const [githubStarCount, setGithubStarCount] = React.useState(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
const response = await fetch(
|
||||
`https://api.github.com/repos/${org}/${repo}?access_token=${token}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `token ${token}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
setGithubStarCount(json.stargazers_count ?? 2000);
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-0 h-auto md:h-[150px] w-full rounded-2xl py-5 px-5 md:px-12 github-banner-bg">
|
||||
<div className="flex items-center gap-16">
|
||||
<img
|
||||
className="hidden md:block"
|
||||
src="/img/blog-static/github-banner-icon.png"
|
||||
alt="Github Logo"
|
||||
/>
|
||||
<div className="font-montserrat max-w-md text-center md:text-left">
|
||||
<h1 className="text-2xl uppercase leading-tight mb-0 font-montserrat font-bold">
|
||||
Star us on github
|
||||
</h1>
|
||||
<p className="mb-0 text-base leading-tight">
|
||||
<b>refine</b> is an{" "}
|
||||
<b>open-source React-based framework</b>
|
||||
for building <b>CRUD applications</b> without
|
||||
constraints. Please show us your <b>support</b> with a
|
||||
shining <b>GitHub star</b>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* eslint-disable react/jsx-no-target-blank */}
|
||||
<Link
|
||||
to="https://github.com/refinedev/refine"
|
||||
rel="noopener"
|
||||
className="bg-[#211d21] no-underline rounded-xl h-[54px] flex gap-2 pl-3.5 py-2.5 pr-2.5 items-center"
|
||||
>
|
||||
<GithubIcon />
|
||||
<div className="font-bold font-montserrat text-base text-white">
|
||||
Star
|
||||
</div>
|
||||
<div className="flex items-start h-full">
|
||||
<CloudTipIcon className="mt-2 -mr-px" />
|
||||
<div className="cloud rounded-md bg-white text-[#211d21] h-full flex items-center justify-center px-1.5 font-montserrat font-bold text-base">
|
||||
{`${githubStarCount}`.padStart(4, "0")}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GithubBanner;
|
||||
91
documentation/src/components/blog/icons.tsx
Normal file
91
documentation/src/components/blog/icons.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
|
||||
export const ChevronLeft = (
|
||||
props: React.SVGProps<SVGSVGElement>,
|
||||
): JSX.Element => (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="h-5 w-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const ChevronRight = (
|
||||
props: React.SVGProps<SVGSVGElement>,
|
||||
): JSX.Element => (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="h-5 w-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Github = (props: React.SVGProps<SVGSVGElement>): JSX.Element => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="#fff"
|
||||
fillRule="evenodd"
|
||||
d="M12.058 0a11.894 11.894 0 0 0-7.814 2.929 12.37 12.37 0 0 0-4.088 7.404 12.523 12.523 0 0 0 1.588 8.344A12.094 12.094 0 0 0 8.25 23.98c.606.112.82-.273.82-.597V21.29c-3.364.747-4.073-1.655-4.073-1.655A3.285 3.285 0 0 0 3.66 17.83c-1.088-.755.088-.755.088-.755.382.055.745.196 1.064.417.32.22.584.511.777.85.164.304.384.571.65.787a2.523 2.523 0 0 0 2.855.241 2.631 2.631 0 0 1 .74-1.646c-2.677-.31-5.487-1.367-5.487-6.042a4.816 4.816 0 0 1 1.235-3.3A4.575 4.575 0 0 1 5.7 5.127s1.012-.333 3.311 1.261a11.156 11.156 0 0 1 6.034 0c2.3-1.593 3.305-1.261 3.305-1.261a4.55 4.55 0 0 1 .147 3.232 4.816 4.816 0 0 1 1.235 3.301c0 4.728-2.816 5.762-5.501 6.041.288.296.51.651.652 1.042.142.39.199.808.17 1.224v3.377c0 .4.213.71.827.59a12.1 12.1 0 0 0 6.414-5.322 12.524 12.524 0 0 0 1.548-8.29 12.37 12.37 0 0 0-4.047-7.36A11.897 11.897 0 0 0 12.058 0Z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Twitter = (props: React.SVGProps<SVGSVGElement>): JSX.Element => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 50 50"
|
||||
{...props}
|
||||
className={clsx("dark:text-[#e7e9ea] text-[#0f1419]")}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M 5.9199219 6 L 20.582031 27.375 L 6.2304688 44 L 9.4101562 44 L 21.986328 29.421875 L 31.986328 44 L 44 44 L 28.681641 21.669922 L 42.199219 6 L 39.029297 6 L 27.275391 19.617188 L 17.933594 6 L 5.9199219 6 z M 9.7167969 8 L 16.880859 8 L 40.203125 42 L 33.039062 42 L 9.7167969 8 z"
|
||||
clipRule="evenodd"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const Linkedin = (props: React.SVGProps<SVGSVGElement>): JSX.Element => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<rect width={24} height={24} fill="#0A66C2" rx={12} />
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M9.364 16.762H7.385V10.4h1.979v6.362ZM8.375 9.53a1.146 1.146 0 1 1 0-2.293 1.146 1.146 0 0 1 0 2.293Zm8.395 7.233h-1.977v-3.094c0-.738-.013-1.687-1.027-1.687-1.03 0-1.188.803-1.188 1.633v3.148h-1.974V10.4H12.5v.87h.027c.263-.5.908-1.028 1.871-1.028 2.003 0 2.372 1.318 2.372 3.031v3.49h-.001Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
9
documentation/src/components/blog/index.js
Normal file
9
documentation/src/components/blog/index.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from "./featured-blog-post-item";
|
||||
export * from "./featured-blog-post-items";
|
||||
export * from "./blog-post-page";
|
||||
export * from "./author-card";
|
||||
export * from "./discord-banner";
|
||||
export * from "./github-banner";
|
||||
export * from "./twitter-banner";
|
||||
export * from "./tags";
|
||||
export * from "./post-paginator";
|
||||
79
documentation/src/components/blog/post-paginator/index.js
Normal file
79
documentation/src/components/blog/post-paginator/index.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
|
||||
import { Date } from "@site/src/components/blog/common";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const PostPaginator = ({ posts, title }) => {
|
||||
if (posts.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"mx-auto w-full",
|
||||
"py-10",
|
||||
"blog-sm:py-12",
|
||||
"blog-md:py-16",
|
||||
"max-w-[512px]",
|
||||
"blog-sm:max-w-screen-blog-sm",
|
||||
"blog-lg:max-w-screen-content-2xl",
|
||||
)}
|
||||
>
|
||||
<div className="blog-sm:px-6 w-full px-4">
|
||||
<h2 className="m-0 mb-4 p-0 pl-4 text-2xl font-semibold text-gray-900 dark:text-gray-200">
|
||||
{title}
|
||||
</h2>
|
||||
<div className="flex flex-col">
|
||||
{posts.map((post) => (
|
||||
<div
|
||||
key={post.permalink ?? post.id}
|
||||
className={clsx(
|
||||
"flex",
|
||||
"flex-col",
|
||||
"p-5",
|
||||
"mb-5",
|
||||
"rounded-md",
|
||||
"bg-gray-50 dark:bg-gray-800",
|
||||
)}
|
||||
>
|
||||
<Link
|
||||
to={post.permalink}
|
||||
rel="dofollow"
|
||||
className={clsx(
|
||||
"font-bold",
|
||||
"text-gray-800 dark:text-gray-200",
|
||||
"no-underline",
|
||||
"hover:text-gray-800 hover:no-underline dark:hover:text-gray-200",
|
||||
"mb-2",
|
||||
)}
|
||||
>
|
||||
{post.title}
|
||||
</Link>
|
||||
|
||||
<p
|
||||
className={clsx(
|
||||
"font-sm",
|
||||
"text-gray-700 dark:text-gray-400",
|
||||
)}
|
||||
>
|
||||
{post.description}
|
||||
</p>
|
||||
|
||||
<div
|
||||
id="post-info"
|
||||
className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400"
|
||||
>
|
||||
<Date
|
||||
date={post.date}
|
||||
formattedDate={post.formattedDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
90
documentation/src/components/blog/promotion/index.js
Normal file
90
documentation/src/components/blog/promotion/index.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/* eslint-disable react/jsx-no-target-blank */
|
||||
import React from "react";
|
||||
|
||||
const PromotionBanner = ({ image, title, description, isDark }) => {
|
||||
let renderDescription;
|
||||
|
||||
if (description === "refineNew") {
|
||||
renderDescription = (
|
||||
<div>
|
||||
{" "}
|
||||
<a href="https://s.refine.dev/new-blog" target="_blank">
|
||||
refine.new
|
||||
</a>{" "}
|
||||
enables you to create React-based, headless UI enterprise
|
||||
applications within your browser that you can preview, tweak and
|
||||
download instantly.
|
||||
<br />
|
||||
<br />
|
||||
🚀 By visually combining options for your preferred ✨
|
||||
<b> React platform,</b> ✨ <b>UI framework</b>, ✨{" "}
|
||||
<b>backend connector</b>, and ✨ <b>auth provider</b>; you can
|
||||
create tailor-made architectures for your project in seconds. It
|
||||
feels like having access to thousands of project templates at
|
||||
your fingertips, allowing you to choose the one that best suits
|
||||
your needs!
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
renderDescription = description ?? (
|
||||
<div>
|
||||
Meet the headless, React-based solution to build sleek{" "}
|
||||
<b>CRUD</b> applications. With refine, you can be confident that
|
||||
your codebase will always stay clean and boilerplate-free.
|
||||
<br />
|
||||
<br />
|
||||
Try{" "}
|
||||
<a href="https://github.com/refinedev/refine" target="_blank">
|
||||
refine
|
||||
</a>{" "}
|
||||
to rapidly build your next <b>CRUD</b> project, whether {"it's"}{" "}
|
||||
an admin panel, dashboard, internal tool or storefront.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const imgBase =
|
||||
image ??
|
||||
"https://refine.ams3.cdn.digitaloceanspaces.com/website/static/img/generic_banner.png";
|
||||
|
||||
const imgUrl = imgBase.startsWith("http")
|
||||
? imgBase
|
||||
: `https://refine.ams3.cdn.digitaloceanspaces.com/website/static${
|
||||
imgBase.startsWith("/") ? imgBase : `/${imgBase}`
|
||||
}`;
|
||||
|
||||
return (
|
||||
/* <div className={`banner-container ${isDark && "dark"}`}>
|
||||
<div className="banner-header">
|
||||
{title ?? "Does your CRUD app need server state management?"}
|
||||
</div>
|
||||
|
||||
{renderDescription}
|
||||
<div>
|
||||
<a
|
||||
href={
|
||||
description === "refineNew"
|
||||
? "https://s.refine.dev/new-blog"
|
||||
: "https://github.com/refinedev/refine"
|
||||
}
|
||||
target="_blank"
|
||||
>
|
||||
<img src={imgUrl} alt="refine blog logo" />
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
</div> */
|
||||
<a
|
||||
href="https://s.refine.dev/hackathon2"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img src="https://refine.ams3.cdn.digitaloceanspaces.com/hackathon-2/hackathon_cover.png" />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default PromotionBanner;
|
||||
31
documentation/src/components/blog/tags/index.js
Normal file
31
documentation/src/components/blog/tags/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
import { useBlogPost } from "@docusaurus/theme-common/internal";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const Tags = () => {
|
||||
const { metadata } = useBlogPost();
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2 pb-6 pl-1">
|
||||
{metadata.tags.map((tag) => (
|
||||
<Link
|
||||
to={tag.permalink}
|
||||
className={clsx(
|
||||
"text-xs",
|
||||
"bg-gray-100 dark:bg-gray-700",
|
||||
"text-gray-600 dark:text-gray-400",
|
||||
"rounded",
|
||||
"py-1",
|
||||
"px-2",
|
||||
"no-underline hover:no-underline",
|
||||
"whitespace-nowrap",
|
||||
)}
|
||||
key={tag.permalink}
|
||||
>
|
||||
{tag.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
53
documentation/src/components/blog/twitter-banner/index.js
Normal file
53
documentation/src/components/blog/twitter-banner/index.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import Link from "@docusaurus/Link";
|
||||
|
||||
const TwitterBanner = ({ children }) => {
|
||||
return (
|
||||
<div className="flex flex-col md:flex-row items-center twitter-banner-bg px-5 md:px-10 py-5 rounded-xl gap-2">
|
||||
<div className="flex flex-col justify-center items-center md:items-start gap-4">
|
||||
<div className="text-center md:text-left">
|
||||
<h1 className="text-white font-montserrat text-2xl leading-tight mb-0">
|
||||
WANT TO HEAR THE LATEST DEVELOPMENTS ABOUT refine?
|
||||
</h1>
|
||||
<p className="mb-0 uppercase font-montserrat text-white">
|
||||
Follow us on Twitter.
|
||||
</p>
|
||||
</div>
|
||||
<Link to="https://twitter.com/refine_dev">
|
||||
<button className="bg-transparent text-white font-bold py-2 px-8 rounded-lg border-white cursor-pointer font-montserrat uppercase text-xl border-solid active:scale-[0.99]">
|
||||
Follow Us
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="w-[350px]">
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<blockquote className="twitter-tweet" data-cards="hidden">
|
||||
<p lang="en" dir="ltr">
|
||||
💥New Blog Post!
|
||||
<br />
|
||||
<br />
|
||||
Animations in React with Framer Motion
|
||||
<a href="https://t.co/7kWU1ROPYd">
|
||||
https://t.co/7kWU1ROPYd
|
||||
</a>
|
||||
<a href="https://twitter.com/hashtag/opensource?src=hash&ref_src=twsrc%5Etfw">
|
||||
#opensource
|
||||
</a>{" "}
|
||||
<a href="https://twitter.com/hashtag/ReactJS?src=hash&ref_src=twsrc%5Etfw">
|
||||
#ReactJS
|
||||
</a>
|
||||
</p>
|
||||
— refine (@refine_dev){" "}
|
||||
<a href="https://twitter.com/refine_dev/status/1565321477628510208?ref_src=twsrc%5Etfw">
|
||||
September 1, 2022
|
||||
</a>
|
||||
</blockquote>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TwitterBanner;
|
||||
Reference in New Issue
Block a user