From 5e7406eb2e5786c5b25e8fac15edddb000c1fe56 Mon Sep 17 00:00:00 2001 From: juliopavila Date: Sun, 6 Aug 2023 18:16:44 -0300 Subject: [PATCH] feat: Enhance UI for User-Configured Pinning Service in Tabula --- .../commons/Editor/EditorInlineText.tsx | 1 - .../commons/Editor/EditorRichText.tsx | 24 ++++++++++++----- .../src/components/commons/PinningAlert.tsx | 26 ++++++++++++++++--- .../components/commons/PublicationAvatar.tsx | 1 - .../app/src/components/commons/UploadFile.tsx | 18 ++++++++++--- .../src/components/layout/ArticleHeader.tsx | 3 ++- .../views/publication/CreateArticleView.tsx | 8 ++++++ .../publication/components/ArticleSidebar.tsx | 25 +++++++++++------- packages/app/src/services/turndown.ts | 2 -- 9 files changed, 81 insertions(+), 27 deletions(-) diff --git a/packages/app/src/components/commons/Editor/EditorInlineText.tsx b/packages/app/src/components/commons/Editor/EditorInlineText.tsx index 4cbcb8f9..6d3a4185 100644 --- a/packages/app/src/components/commons/Editor/EditorInlineText.tsx +++ b/packages/app/src/components/commons/Editor/EditorInlineText.tsx @@ -151,7 +151,6 @@ const EditorInlineText: React.FC = ({ return } setShowInvalidUrl(true) - console.log("The user press enter") } return ( diff --git a/packages/app/src/components/commons/Editor/EditorRichText.tsx b/packages/app/src/components/commons/Editor/EditorRichText.tsx index bafbd77a..90f4627c 100644 --- a/packages/app/src/components/commons/Editor/EditorRichText.tsx +++ b/packages/app/src/components/commons/Editor/EditorRichText.tsx @@ -15,6 +15,7 @@ import { DragIndicator } from "@mui/icons-material" import { palette, typography } from "../../../theme" import { useOnClickOutside } from "../../../hooks/useOnClickOutside" import { useArticleContext } from "../../../services/publications/contexts" +import useLocalStorage from "../../../hooks/useLocalStorage" const RichTextButton = styled(Box)({ position: "relative", @@ -75,6 +76,7 @@ type RichTextItemProps = { color?: string icon: React.ReactNode selected?: boolean + disabled?: boolean } type RichTextProps = { @@ -190,7 +192,7 @@ const DragTooltipContent = () => { ) } -const RichTextItem: React.FC = ({ label, icon, color, selected }) => { +const RichTextItem: React.FC = ({ label, icon, color, selected, disabled }) => { return ( = ({ label, icon, color, selecte alignItems="center" sx={{ cursor: "pointer", - "& .rich-text-icon": { backgroundColor: selected ? palette.grays[100] : palette.grays[50] }, + "& .rich-text-icon": { + backgroundColor: selected ? palette.grays[100] : palette.grays[50], + opacity: disabled ? 0.5 : "initial", + }, "&:hover": { "& .rich-text-icon": { backgroundColor: palette.grays[100] }, }, @@ -211,7 +216,7 @@ const RichTextItem: React.FC = ({ label, icon, color, selecte {label && ( = ({ label, icon, color, selecte const EditorRichText: React.FC = ({ onRichTextSelected, showCommand, onDelete, onAdd }) => { const { setShowBlockTypePopup } = useArticleContext() - + const [pinning] = useLocalStorage("pinning", undefined) const containerRef = useRef Element | null) | null>(null) const richTextRef = useRef(null) const ref = useRef(null) @@ -283,7 +288,6 @@ const EditorRichText: React.FC = ({ onRichTextSelected, showComma case "Enter": event.preventDefault() setSelectedIndex((currentIndex) => { - console.log("currentIndex", currentIndex) const selectedOption = richTextOption[currentIndex] if (selectedOption) { handleSelection(selectedOption.value) @@ -348,6 +352,9 @@ const EditorRichText: React.FC = ({ onRichTextSelected, showComma }, [topOffset]) const handleSelection = (value: RICH_TEXT_ELEMENTS) => { + if (value === RICH_TEXT_ELEMENTS.IMAGE && !pinning) { + return + } if (onRichTextSelected) { onRichTextSelected(value) setShow(false) @@ -423,7 +430,12 @@ const EditorRichText: React.FC = ({ onRichTextSelected, showComma {OPTIONS.map(({ label, icon, value }, index) => (
value && handleSelection(value)} tabIndex={0}> - +
))} diff --git a/packages/app/src/components/commons/PinningAlert.tsx b/packages/app/src/components/commons/PinningAlert.tsx index c200383d..5f8da1d7 100644 --- a/packages/app/src/components/commons/PinningAlert.tsx +++ b/packages/app/src/components/commons/PinningAlert.tsx @@ -22,7 +22,11 @@ const StyledButton = styled(Button)({ }, }) -export const PinningAlert: React.FC = () => { +type PinningAlertProps = { + secondMsg?: boolean +} + +export const PinningAlert: React.FC = ({ secondMsg }) => { const navigate = useNavigate() const location = useLocation() const { setCurrentPath } = usePublicationContext() @@ -43,8 +47,24 @@ export const PinningAlert: React.FC = () => { - It is not recommended to publish an article without a configured pinning service. Without a configured - pinning service, your transactions will be much more expensive. + {secondMsg ? ( + <> + + Use the Public IPFS-Gateway: Retrieve the hash content, + but note that we don't store images or articles. + + + Set Up a Custom Pinning Service: Trust your preferred + service for more personalized control. + + + Post the Article Directly on Chain: Keep in mind, this + is more expensive, and images are not supported. + + + ) : ( + "It is not recommended to publish an article without a configured pinning service. Without a configured pinning service, your transactions will be much more expensive." + )} diff --git a/packages/app/src/components/commons/PublicationAvatar.tsx b/packages/app/src/components/commons/PublicationAvatar.tsx index f01a8d60..4fb9fdb5 100644 --- a/packages/app/src/components/commons/PublicationAvatar.tsx +++ b/packages/app/src/components/commons/PublicationAvatar.tsx @@ -103,7 +103,6 @@ const PublicationAvatar: React.FC = ({ defaultImage, onF } const handleShowImg = (): string | undefined => { - console.log('uri', uri) if (uri) { return uri } diff --git a/packages/app/src/components/commons/UploadFile.tsx b/packages/app/src/components/commons/UploadFile.tsx index 028def8a..ee9d33c4 100644 --- a/packages/app/src/components/commons/UploadFile.tsx +++ b/packages/app/src/components/commons/UploadFile.tsx @@ -41,9 +41,16 @@ type UploadFileProps = { defaultUri?: string | undefined onFileSelected: (file: File | undefined) => void convertedFile?: (uri: string | undefined) => void + disabled?: boolean } -export const UploadFile: React.FC = ({ defaultImage, defaultUri, onFileSelected, convertedFile }) => { +export const UploadFile: React.FC = ({ + defaultImage, + defaultUri, + onFileSelected, + convertedFile, + disabled, +}) => { const inputFile = useRef(null) const [file, setFile] = useState(null) const [uri, setUri] = useState(null) @@ -71,7 +78,7 @@ export const UploadFile: React.FC = ({ defaultImage, defaultUri } }, [defaultImage, ipfs, defaultImageSrc]) - const openImagePicker = () => inputFile && inputFile.current?.click() + const openImagePicker = () => !disabled && inputFile && inputFile.current?.click() const removeImage = () => { setFile(null) @@ -94,7 +101,12 @@ export const UploadFile: React.FC = ({ defaultImage, defaultUri return ( <> {!imageHash && !uri && ( - + Include a high-quality image in your post to make it more inviting. diff --git a/packages/app/src/components/layout/ArticleHeader.tsx b/packages/app/src/components/layout/ArticleHeader.tsx index 99e7a1d2..a6944959 100644 --- a/packages/app/src/components/layout/ArticleHeader.tsx +++ b/packages/app/src/components/layout/ArticleHeader.tsx @@ -225,7 +225,7 @@ const ArticleHeader: React.FC = ({ publication, type }) => { let hashArticle const { title, article: draftArticleText, description, tags } = article - if (draftArticleThumbnail) { + if (pinning && draftArticleThumbnail) { await ipfs.uploadContent(draftArticleThumbnail).then(async (img) => { articleThumbnail = img.path }) @@ -246,6 +246,7 @@ const ArticleHeader: React.FC = ({ publication, type }) => { if (title) { if (type === "new") { console.log("before start") + return await createArticle( { action: "article/create", diff --git a/packages/app/src/components/views/publication/CreateArticleView.tsx b/packages/app/src/components/views/publication/CreateArticleView.tsx index 7d889603..a112d294 100644 --- a/packages/app/src/components/views/publication/CreateArticleView.tsx +++ b/packages/app/src/components/views/publication/CreateArticleView.tsx @@ -7,12 +7,15 @@ import CreateArticlePage from "../../layout/CreateArticlePage" import { ArticleContentSection } from "./components/ArticleContentSection" import { palette } from "../../../theme" import useDebouncedState from "../../../hooks/useDebouncedState" +import useLocalStorage from "../../../hooks/useLocalStorage" +import { PinningAlert } from "../../commons/PinningAlert" interface CreateArticleViewProps { type: "new" | "edit" } export const CreateArticleView: React.FC = React.memo(({ type }) => { + const [pinning] = useLocalStorage("pinning", undefined) const { publication } = usePublicationContext() const { draftArticle, updateDraftArticle, articleTitleError, articleContentError } = useArticleContext() @@ -32,6 +35,11 @@ export const CreateArticleView: React.FC = React.memo(({ > + {!pinning && ( + + + + )} diff --git a/packages/app/src/components/views/publication/components/ArticleSidebar.tsx b/packages/app/src/components/views/publication/components/ArticleSidebar.tsx index 98693e08..72ed44d9 100644 --- a/packages/app/src/components/views/publication/components/ArticleSidebar.tsx +++ b/packages/app/src/components/views/publication/components/ArticleSidebar.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-hooks/exhaustive-deps */ import React, { useState, SetStateAction, useEffect, useCallback } from "react" -import { Box, InputLabel, Stack, TextField, Typography, useTheme } from "@mui/material" +import { Box, InputLabel, Stack, TextField, Tooltip, Typography, useTheme } from "@mui/material" import { useArticleContext } from "../../../../services/publications/contexts" import { Close } from "@mui/icons-material" import { palette, typography } from "../../../../theme" @@ -9,6 +9,7 @@ import { UploadFile } from "../../../commons/UploadFile" import { CreatableSelect } from "../../../commons/CreatableSelect" import { CreateSelectOption } from "../../../../models/dropdown" import useDebouncedState from "../../../../hooks/useDebouncedState" +import useLocalStorage from "../../../../hooks/useLocalStorage" export interface ArticleSidebarProps { showSidebar: boolean @@ -16,6 +17,7 @@ export interface ArticleSidebarProps { } const ArticleSidebar: React.FC = ({ showSidebar, setShowSidebar }) => { + const [pinning] = useLocalStorage("pinning", undefined) const { article } = useArticleContext() const { draftArticle, saveDraftArticle, setDraftArticleThumbnail, draftArticleThumbnail, updateDraftArticle } = useArticleContext() @@ -143,15 +145,18 @@ const ArticleSidebar: React.FC = ({ showSidebar, setShowSid }} > {/* Thumbnail */} - - Thumbnail - - + + + Thumbnail + + + {/* Post URL */} {/* diff --git a/packages/app/src/services/turndown.ts b/packages/app/src/services/turndown.ts index 78b61fc2..0f7429c7 100644 --- a/packages/app/src/services/turndown.ts +++ b/packages/app/src/services/turndown.ts @@ -24,11 +24,9 @@ turndownService.addRule("pre", { turndownService.addRule("figure", { filter: function (node) { const isMatch = node.nodeName === "FIGURE" && node.innerHTML.trim() === " " - // console.log(`Checking node: ${node.outerHTML}, isMatch: ${isMatch}`) return isMatch }, replacement: function () { - // console.log("Replacing figure node with divider") return "\n\n---\n\n" }, })