diff --git a/api/src/types/fragments.js b/api/src/types/fragments.js index 252f8086..e64d6a9c 100644 --- a/api/src/types/fragments.js +++ b/api/src/types/fragments.js @@ -22,6 +22,12 @@ export const appBundleFragment = ` Index_updatedAt: updatedAt Index_deletedAt: deletedAt } + ... on Article { + Article_id: id + Article_title: title + Article_url: url + Article_createdAt: createdAt + } ... on WebPage { WebPage_title: title WebPage_favicon: favicon diff --git a/web-app/public/images/article.svg b/web-app/public/images/article.svg new file mode 100644 index 00000000..1e92c8b7 --- /dev/null +++ b/web-app/public/images/article.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/web-app/src/components/site/index-details/ArticleItem/index.tsx b/web-app/src/components/site/index-details/ArticleItem/index.tsx new file mode 100644 index 00000000..c0eac08f --- /dev/null +++ b/web-app/src/components/site/index-details/ArticleItem/index.tsx @@ -0,0 +1,116 @@ +import Freizeit from "@/fonts/loader"; +import { shortStr } from "@/utils/helper"; +import Button from "components/base/Button"; +import IconContextMenu from "components/base/Icon/IconContextMenu"; +import Text from "components/base/Text"; +import Col from "components/layout/base/Grid/Col"; +import FlexRow from "components/layout/base/Grid/FlexRow"; +import IndexDetailItemPopup from "components/site/popup/IndexDetailItemPopup"; +import { useRole } from "hooks/useRole"; +import moment from "moment"; +import React from "react"; +import sanitize from "sanitize-html"; +import { ArticleIndexNodeItem, DefaultIndexNodeItem } from "types/entity"; + +export interface ArticleItemProps { + item: ArticleIndexNodeItem; + onChange?(val: DefaultIndexNodeItem[]): void; + search?: boolean; + handleRemove?(): void; +} + +const ArticleItem: React.FC = ({ + item, + search = false, + handleRemove, +}) => { + const { node } = item; + + const { isCreator } = useRole(); + + return ( +
+ + + + + favicon) => { + const target = e.target as HTMLImageElement; + target.onerror = null; // Prevents infinite loop in case fallback image also fails + target.src = "/images/article.svg"; + }} + style={{ + verticalAlign: "middle", + }} + /> + + + + + {!search && isCreator ? ( + + + + + + + + + + + ) : ( + + + + + + + + + )} + + + + + {item.type} + {" • "} + + {node.url} + + {" • "} + + + + {node?.createdAt + ? `Published ${moment(new Date(node.createdAt)).fromNow()}` + : ""} + + + +
+ ); +}; +export default ArticleItem; diff --git a/web-app/src/components/site/index-details/IndexItemList/index.tsx b/web-app/src/components/site/index-details/IndexItemList/index.tsx index 21621d4f..df2c2723 100644 --- a/web-app/src/components/site/index-details/IndexItemList/index.tsx +++ b/web-app/src/components/site/index-details/IndexItemList/index.tsx @@ -9,6 +9,7 @@ import { IndexItem, IndexTeamNodeItem, IndexWebPageItem, + ArticleIndexNodeItem, } from "types/entity"; import NoLinks from "../../indexes/NoLinks"; @@ -17,6 +18,7 @@ import TeamItem from "../TeamItem"; import IndexIndexItem from "../IndexIndexItem"; import DefaultIndexItem from "../DefaultIndexItem"; import CastItem from "../CastItem"; +import ArticleItem from "../ArticleItem"; export interface IndexItemListProps { search: string; @@ -31,6 +33,7 @@ const MemoTeamItem = memo(TeamItem); const MemoIndexItem = memo(IndexIndexItem); const MemoDefaultIndexItem = memo(DefaultIndexItem); const MemoCastItem = memo(CastItem); +const MemoArticleItem = memo(ArticleItem); const IndexItemList: FC = ({ search, @@ -62,6 +65,16 @@ const IndexItemList: FC = ({ ); } + if (item.type === "Article") { + return ( + removeItem(item)} + search={!!search} + item={item as ArticleIndexNodeItem} + /> + ); + } + if (item.type === "Index") { return ( { const profileData = { name: values.name, bio: values.bio, - avatar: (avatar || userProfile.avatar).replace( + avatar: undefined, + }; + + if (avatar || userProfile.avatar) { + profileData.avatar = (avatar || userProfile.avatar).replace( `${appConfig.ipfsProxy}/`, "", - ), - }; + ); + } await dispatch(updateProfile({ profile: profileData, api })).unwrap(); toast.success("Profile updated successfully"); diff --git a/web-app/src/types/entity.ts b/web-app/src/types/entity.ts index 2606afaf..3a6d48bb 100644 --- a/web-app/src/types/entity.ts +++ b/web-app/src/types/entity.ts @@ -74,6 +74,12 @@ export type CastIndexNode = { username: string; }; }; +export type ArticleIndexNode = { + id: string; + title: string; + url: string; + createdAt: string; +}; export type IndexWebPageItem = { id: string; @@ -105,11 +111,18 @@ export type CastIndexNodeItem = { node: CastIndexNode; }; +export type ArticleIndexNodeItem = { + id: string; + type: string; + node: ArticleIndexNode; +}; + export type IndexItem = | IndexWebPageItem | IndexTeamNodeItem | IndexIndexNodeItem | DefaultIndexNodeItem + | ArticleIndexNodeItem | CastIndexNodeItem; export type IndexLink = {