From 39695e8fcee26354224df6011bd30c0d5a075689 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 28 Jun 2021 21:30:06 +0800 Subject: [PATCH 1/7] chore: basic setup --- server/routes.js | 5 + .../CommunityContent/{index.js => index.tsx} | 11 +- .../CommunityContent/{logic.js => logic.ts} | 10 +- .../content/CommunityContent/store.js | 37 ---- .../content/CommunityContent/store.ts | 40 ++++ .../digest/CommunityDigest/index.js | 2 + src/pages/home/blogs.js | 172 ++++++++++++++++++ utils/constant/route.ts | 2 + utils/constant/thread.ts | 1 + 9 files changed, 237 insertions(+), 43 deletions(-) rename src/containers/content/CommunityContent/{index.js => index.tsx} (85%) rename src/containers/content/CommunityContent/{logic.js => logic.ts} (87%) delete mode 100755 src/containers/content/CommunityContent/store.js create mode 100755 src/containers/content/CommunityContent/store.ts create mode 100755 src/pages/home/blogs.js diff --git a/server/routes.js b/server/routes.js index fab301e0f..9153c9e8d 100644 --- a/server/routes.js +++ b/server/routes.js @@ -124,6 +124,11 @@ router.route('/:community/help-center').get((req, res) => { return renderAndCache({ req, res, path: '/help-center' }) }) +// NOTE: TMP: 博客 +router.route('/:community/blogs').get((req, res) => { + return renderAndCache({ req, res, path: '/home/blogs' }) +}) + // 社区主页 router.route('/:community/:thread').get((req, res) => { if ( diff --git a/src/containers/content/CommunityContent/index.js b/src/containers/content/CommunityContent/index.tsx similarity index 85% rename from src/containers/content/CommunityContent/index.js rename to src/containers/content/CommunityContent/index.tsx index a27362bd6..0d3cbcba1 100755 --- a/src/containers/content/CommunityContent/index.js +++ b/src/containers/content/CommunityContent/index.tsx @@ -4,7 +4,7 @@ * */ -import React from 'react' +import { FC } from 'react' import { ROUTE, C11N } from '@/constant' import { useDevice } from '@/hooks' @@ -17,6 +17,7 @@ import JobsThread from '@/containers/thread/JobsThread' import UsersThread from '@/containers/thread/UsersThread' import CheatsheetThread from '@/containers/thread/CheatsheetThread' +import type { TStore } from './store' import { Wrapper, InnerWrapper } from './styles' import { useInit } from './logic' @@ -46,7 +47,11 @@ const ComunityContent = ({ curRoute }) => { } } -const CommunityContentContainer = ({ communityContent: store }) => { +type TProps = { + communityContent?: TStore +} + +const CommunityContentContainer: FC = ({ communityContent: store }) => { useInit(store) const { isMobile } = useDevice() @@ -68,4 +73,4 @@ const CommunityContentContainer = ({ communityContent: store }) => { ) } -export default pluggedIn(CommunityContentContainer) +export default pluggedIn(CommunityContentContainer) as FC diff --git a/src/containers/content/CommunityContent/logic.js b/src/containers/content/CommunityContent/logic.ts similarity index 87% rename from src/containers/content/CommunityContent/logic.js rename to src/containers/content/CommunityContent/logic.ts index 3cf95bbd6..47f32ac20 100755 --- a/src/containers/content/CommunityContent/logic.js +++ b/src/containers/content/CommunityContent/logic.ts @@ -3,6 +3,8 @@ import { useEffect } from 'react' import { ERR } from '@/constant' import { asyncSuit, buildLog, errRescue } from '@/utils' +import type { TStore } from './store' + /* eslint-disable-next-line */ const log = buildLog('L:CommunityContent') @@ -11,7 +13,7 @@ const { SR71, $solver, asyncErr } = asyncSuit const sr71$ = new SR71() let sub$ = null -let store = null +let store: TStore | undefined // ############################### // Data & Error handlers @@ -21,7 +23,9 @@ const DataSolver = [] const ErrSolver = [ { match: asyncErr(ERR.GRAPHQL), - action: () => {}, + action: () => { + /** */ + }, }, { match: asyncErr(ERR.TIMEOUT), @@ -40,7 +44,7 @@ const ErrSolver = [ // ############################### // init & uninit // ############################### -export const useInit = (_store) => { +export const useInit = (_store: TStore): void => { useEffect(() => { store = _store log('effect init', store) diff --git a/src/containers/content/CommunityContent/store.js b/src/containers/content/CommunityContent/store.js deleted file mode 100755 index 606bafeb9..000000000 --- a/src/containers/content/CommunityContent/store.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * CommunityContent store - * - */ - -import { types as T, getParent } from 'mobx-state-tree' - -import { markStates, buildLog } from '@/utils' - -/* eslint-disable-next-line */ -const log = buildLog('S:CommunityContent') - -const CommunityContent = T.model('CommunityContent', {}) - .views((self) => ({ - get root() { - return getParent(self) - }, - get curRoute() { - return self.root.curRoute - }, - get accountInfo() { - return self.root.accountInfo - }, - })) - .actions((self) => ({ - setViewing(sobj) { - self.root.setViewing(sobj) - }, - markRoute(query) { - self.root.markRoute(query) - }, - mark(sobj) { - markStates(sobj, self) - }, - })) - -export default CommunityContent diff --git a/src/containers/content/CommunityContent/store.ts b/src/containers/content/CommunityContent/store.ts new file mode 100755 index 000000000..38ef3fe0a --- /dev/null +++ b/src/containers/content/CommunityContent/store.ts @@ -0,0 +1,40 @@ +/* + * CommunityContent store + * + */ + +import { types as T, getParent, Instance } from 'mobx-state-tree' + +import type { TRootStore, TAccount, TRoute } from '@/spec' +import { markStates, buildLog } from '@/utils' + +/* eslint-disable-next-line */ +const log = buildLog('S:CommunityContent') + +const CommunityContent = T.model('CommunityContent', {}) + .views((self) => ({ + get curRoute(): TRoute { + const root = getParent(self) as TRootStore + return root.curRoute + }, + get accountInfo(): TAccount { + const root = getParent(self) as TRootStore + return root.accountInfo + }, + })) + .actions((self) => ({ + setViewing(sobj): void { + const root = getParent(self) as TRootStore + root.setViewing(sobj) + }, + markRoute(query): void { + const root = getParent(self) as TRootStore + root.markRoute(query) + }, + mark(sobj: Record): void { + markStates(sobj, self) + }, + })) + +export type TStore = Instance +export default CommunityContent diff --git a/src/containers/digest/CommunityDigest/index.js b/src/containers/digest/CommunityDigest/index.js index 1d3b498cd..66f378a85 100755 --- a/src/containers/digest/CommunityDigest/index.js +++ b/src/containers/digest/CommunityDigest/index.js @@ -29,6 +29,8 @@ const CommunityDigestContainer = ({ communityDigest: store, metric }) => { isHeaderFixed, } = store + console.log('community --> ', community) + return ( {bannerLayout === C11N.BRIEF ? ( diff --git a/src/pages/home/blogs.js b/src/pages/home/blogs.js new file mode 100755 index 000000000..3c39120a7 --- /dev/null +++ b/src/pages/home/blogs.js @@ -0,0 +1,172 @@ +import React from 'react' +import { Provider } from 'mobx-react' +import { merge, pick, toLower } from 'ramda' + +import { PAGE_SIZE, SITE_URL } from '@/config' +import { METRIC } from '@/constant' +import { useStore } from '@/stores/init' + +import { + getJwtToken, + makeGQClient, + queryStringToJSON, + ssrParseURL, + akaTranslate, + buildLog, + nilOrEmpty, + ssrPagedSchema, + ssrPagedFilter, + ssrContentsThread, + ssrAmbulance, + validCommunityFilters, + parseTheme, +} from '@/utils' + +import GlobalLayout from '@/containers/layout/GlobalLayout' +import CommunityDigest from '@/containers/digest/CommunityDigest' +import CommunityContent from '@/containers/content/CommunityContent' + +import { P } from '@/schemas' + +/* eslint-disable-next-line */ +const log = buildLog('page:community') + +const fetchData = async (props, opt) => { + const { realname } = merge({ realname: true }, opt) + + const token = realname ? getJwtToken(props) : null + const gqClient = makeGQClient(token) + const userHasLogin = nilOrEmpty(token) === false + + // const { asPath } = props + // schema + + const { communityPath, thread } = ssrParseURL(props.req) + const community = akaTranslate(communityPath) + + let filter = { + ...queryStringToJSON(props.req.url, { pagi: 'number' }), + community, + thread, + } + + filter = pick(validCommunityFilters, filter) + + // query data + const sessionState = gqClient.request(P.sessionState) + const curCommunity = gqClient.request(P.community, { + raw: community, + userHasLogin, + }) + + // const partialTags = gqClient.request(P.partialTags, { thread, community }) + const subscribedCommunities = gqClient.request(P.subscribedCommunities, { + filter: { + page: 1, + size: PAGE_SIZE.M, + }, + }) + + return { + filter, + ...(await sessionState), + ...(await curCommunity), + // ...(await pagedContents), + // ...(await partialTags), + ...(await subscribedCommunities), + } +} + +export const getServerSideProps = async (props) => { + const { communityPath, thread, threadPath } = ssrParseURL(props.req) + + let resp + try { + resp = await fetchData(props) + } catch (e) { + const { + response: { errors }, + } = e + if (ssrAmbulance.hasLoginError(errors)) { + resp = await fetchData(props, { realname: false }) + } else { + return { + props: { + errorCode: 404, + target: communityPath, + viewing: { + community: { + raw: communityPath, + title: communityPath, + desc: communityPath, + }, + }, + }, + } + } + } + + const { + sessionState, + // partialTags, + community, + subscribedCommunities, + } = resp + + // // init state on server side + const initProps = merge( + { + theme: { + curTheme: parseTheme(sessionState), + }, + account: { + user: sessionState.user || {}, + isValidSession: sessionState.isValid, + userSubscribedCommunities: subscribedCommunities, + }, + route: { + communityPath: community.raw, + mainPath: community.raw, + threadPath, + subPath: threadPath, + }, + viewing: { + community, + activeThread: toLower(thread), + }, + // tagsBar: { tags: partialTags }, + }, + {}, + ) + + return { props: { errorCode: null, ...initProps } } +} + +const BlogsPage = (props) => { + const store = useStore(props) + + const { errorCode, viewing } = store + const { community, activeThread } = viewing + + const seoConfig = { + url: `${SITE_URL}/${community.raw}/${activeThread}`, + title: `${community.title} | coderplanets`, + description: `${community.desc}`, + } + + return ( + + + + + + + ) +} + +export default BlogsPage diff --git a/utils/constant/route.ts b/utils/constant/route.ts index b2ebca03b..000d8fe02 100755 --- a/utils/constant/route.ts +++ b/utils/constant/route.ts @@ -6,6 +6,7 @@ const ROUTE = { DISCOVERY: 'discovery', CHEATSHEETS: 'cheatsheets', POSTS: 'posts', + BLOGS: 'blogs', JOBS: 'jobs', USERS: 'users', REPOS: 'repos', @@ -16,6 +17,7 @@ const ROUTE = { CHEATSHEET: 'cheatsheet', POST: 'post', + BLOG: 'blog', USER: 'user', JOB: 'job', REPO: 'repo', diff --git a/utils/constant/thread.ts b/utils/constant/thread.ts index 13f9e798d..e5022e28b 100755 --- a/utils/constant/thread.ts +++ b/utils/constant/thread.ts @@ -9,6 +9,7 @@ export const COMMUNITY_SPEC_THREADS = { export const THREAD = { ...COMMUNITY_SPEC_THREADS, POST: 'post', + BLOG: 'blog', // home spec TECH: 'tech', SHARE: 'share', From 21180f8ee2640a5c5576271b02d2ca2f3e33588f Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 28 Jun 2021 21:32:45 +0800 Subject: [PATCH 2/7] chore: clean warnings --- src/pages/home/{blogs.js => blogs.tsx} | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) rename src/pages/home/{blogs.js => blogs.tsx} (97%) diff --git a/src/pages/home/blogs.js b/src/pages/home/blogs.tsx similarity index 97% rename from src/pages/home/blogs.js rename to src/pages/home/blogs.tsx index 3c39120a7..bf5988349 100755 --- a/src/pages/home/blogs.js +++ b/src/pages/home/blogs.tsx @@ -14,9 +14,6 @@ import { akaTranslate, buildLog, nilOrEmpty, - ssrPagedSchema, - ssrPagedFilter, - ssrContentsThread, ssrAmbulance, validCommunityFilters, parseTheme, @@ -31,7 +28,7 @@ import { P } from '@/schemas' /* eslint-disable-next-line */ const log = buildLog('page:community') -const fetchData = async (props, opt) => { +const fetchData = async (props, opt = {}) => { const { realname } = merge({ realname: true }, opt) const token = realname ? getJwtToken(props) : null @@ -45,6 +42,7 @@ const fetchData = async (props, opt) => { const community = akaTranslate(communityPath) let filter = { + // @ts-ignore TODO: ...queryStringToJSON(props.req.url, { pagi: 'number' }), community, thread, From f61e4e8b48c809234f043b2d20b97496955dbf2d Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 28 Jun 2021 23:50:06 +0800 Subject: [PATCH 3/7] chore: tmp solve the postsThread ts convert --- .../{OptionPanel.js => OptionPanel.tsx} | 33 +++---- .../Buttons/DropdownButton/index.js | 96 ------------------- .../Buttons/DropdownButton/index.tsx | 70 ++++++++++++++ src/components/PromotionList/index.tsx | 3 +- src/components/TabBar/spec.ts | 4 +- .../PostsThread/{index.js => index.tsx} | 13 ++- .../thread/PostsThread/{logic.js => logic.ts} | 31 +++--- .../thread/PostsThread/{store.js => store.ts} | 92 +++++++++++------- .../tool/CommunityJoinBadge/index.tsx | 2 +- src/containers/unit/TagsBar/CardView.js | 77 --------------- src/containers/unit/TagsBar/CardView.tsx | 71 ++++++++++++++ .../DesktopView/{Folder.js => Folder.tsx} | 23 ++++- .../{GobackTag.js => GobackTag.tsx} | 10 +- .../DesktopView/{TagCount.js => TagCount.tsx} | 0 .../DesktopView/{TagItem.js => TagItem.tsx} | 19 +++- .../DesktopView/{index.js => index.tsx} | 36 +++---- .../unit/TagsBar/{index.js => index.tsx} | 24 ++--- .../unit/TagsBar/{logic.js => logic.ts} | 21 ++-- src/containers/unit/TagsBar/store.ts | 5 +- src/spec/community.ts | 10 +- src/spec/comp.ts | 3 +- src/spec/utils.ts | 4 +- utils/helper.ts | 4 +- 23 files changed, 338 insertions(+), 313 deletions(-) rename src/components/Buttons/DropdownButton/{OptionPanel.js => OptionPanel.tsx} (74%) delete mode 100644 src/components/Buttons/DropdownButton/index.js create mode 100644 src/components/Buttons/DropdownButton/index.tsx rename src/containers/thread/PostsThread/{index.js => index.tsx} (95%) rename src/containers/thread/PostsThread/{logic.js => logic.ts} (87%) rename src/containers/thread/PostsThread/{store.js => store.ts} (57%) delete mode 100644 src/containers/unit/TagsBar/CardView.js create mode 100644 src/containers/unit/TagsBar/CardView.tsx rename src/containers/unit/TagsBar/DesktopView/{Folder.js => Folder.tsx} (88%) rename src/containers/unit/TagsBar/DesktopView/{GobackTag.js => GobackTag.tsx} (68%) rename src/containers/unit/TagsBar/DesktopView/{TagCount.js => TagCount.tsx} (100%) rename src/containers/unit/TagsBar/DesktopView/{TagItem.js => TagItem.tsx} (72%) rename src/containers/unit/TagsBar/DesktopView/{index.js => index.tsx} (66%) rename src/containers/unit/TagsBar/{index.js => index.tsx} (61%) rename src/containers/unit/TagsBar/{logic.js => logic.ts} (85%) diff --git a/src/components/Buttons/DropdownButton/OptionPanel.js b/src/components/Buttons/DropdownButton/OptionPanel.tsx similarity index 74% rename from src/components/Buttons/DropdownButton/OptionPanel.js rename to src/components/Buttons/DropdownButton/OptionPanel.tsx index d51679dec..87d84fa87 100644 --- a/src/components/Buttons/DropdownButton/OptionPanel.js +++ b/src/components/Buttons/DropdownButton/OptionPanel.tsx @@ -1,8 +1,9 @@ -import React from 'react' +import { FC, memo } from 'react' import T from 'prop-types' import { ICON } from '@/config' import { cutRest } from '@/utils' +import type { TOption } from './index' import { Wrapper, @@ -37,7 +38,13 @@ const LinkBlock = ({ children, link }) => { ) } -const OptionPanel = ({ options, onClick, panelMinWidth }) => { +type TProps = { + options: TOption[] + panelMinWidth: string + onClick?: (key?: string) => void +} + +const OptionPanel: FC = ({ options, onClick, panelMinWidth }) => { return ( {options.map((item, index) => ( @@ -49,7 +56,7 @@ const OptionPanel = ({ options, onClick, panelMinWidth }) => { {/* common_check icon is special, smaller than normal icons, and check icon is always the first icon */} - +
@@ -64,22 +71,4 @@ const OptionPanel = ({ options, onClick, panelMinWidth }) => { ) } -OptionPanel.propTypes = { - onClick: T.func, - options: T.arrayOf( - T.shape({ - title: T.stirng, - desc: T.string, - icon: T.string, - link: T.string, - }), - ), - panelMinWidth: T.string.isRequired, -} - -OptionPanel.defaultProps = { - options: [], - onClick: console.log, -} - -export default React.memo(OptionPanel) +export default memo(OptionPanel) diff --git a/src/components/Buttons/DropdownButton/index.js b/src/components/Buttons/DropdownButton/index.js deleted file mode 100644 index ee940e848..000000000 --- a/src/components/Buttons/DropdownButton/index.js +++ /dev/null @@ -1,96 +0,0 @@ -import React from 'react' -import T from 'prop-types' - -import { ICON_CMD } from '@/config' - -import Tooltip from '@/components/Tooltip' -import OptionPanel from './OptionPanel' - -import { - Wrapper, - ButtonWrapper, - DropdownButtonWrapper, - Divider, - MoreIcon, -} from '../styles/dropdown_button' - -// -const DropdownButton = ({ - children, - options, - onClick, - placement, - panelMinWidth, -}) => { - return ( - - {children} - - } - noPadding - > - - - - - - - ) -} - -DropdownButton.propTypes = { - children: T.oneOfType([T.string, T.node]), - onClick: T.func, - options: T.arrayOf( - T.shape({ - title: T.stirng, - desc: T.string, - icon: T.string, - link: T.string, - }), - ), - placement: T.oneOf([ - 'top', - 'top-start', - 'top-end', - 'bottom', - 'bottom-start', - 'bottom-end', - 'left', - 'left-start', - 'left-end', - 'right', - 'right-start', - 'right-end', - ]), - panelMinWidth: T.string, - // ghost: T.bool, - // type: T.oneOf(['primary', 'red', 'ghost']), - // onClick: T.func, - // className: T.string, -} - -DropdownButton.defaultProps = { - children: 'Button', - onClick: console.log, - options: [], - placement: 'bottom', - panelMinWidth: '100%', - // ghost: false, - // type: 'primary', - // size: 'default', - // // eslint-disable-next-line no-console - // onClick: console.log, - // className: '', -} - -export default React.memo(DropdownButton) diff --git a/src/components/Buttons/DropdownButton/index.tsx b/src/components/Buttons/DropdownButton/index.tsx new file mode 100644 index 000000000..13c1d608a --- /dev/null +++ b/src/components/Buttons/DropdownButton/index.tsx @@ -0,0 +1,70 @@ +import { FC, ReactNode, memo } from 'react' + +import { ICON_CMD } from '@/config' +import { buildLog } from '@/utils' + +import type { TTooltipPlacement } from '@/spec' + +import Tooltip from '@/components/Tooltip' +import OptionPanel from './OptionPanel' + +import { + Wrapper, + ButtonWrapper, + DropdownButtonWrapper, + Divider, + MoreIcon, +} from '../styles/dropdown_button' + +const log = buildLog('C:PostsThread') + +export type TOption = { + title: string + key: string + desc?: string + icon?: string + link?: string +} + +type TProps = { + children: ReactNode + options: TOption[] + placement?: TTooltipPlacement + panelMinWidth?: string + onClick: (key?: string) => void +} + +// +const DropdownButton: FC = ({ + children, + options, + onClick = log, + placement = 'bottom', + panelMinWidth = '100%', +}) => { + return ( + + {children} + + } + noPadding + > + + + + + + + ) +} + +export default memo(DropdownButton) diff --git a/src/components/PromotionList/index.tsx b/src/components/PromotionList/index.tsx index 39b6dc2ee..b7dfd4dfd 100755 --- a/src/components/PromotionList/index.tsx +++ b/src/components/PromotionList/index.tsx @@ -26,8 +26,9 @@ const log = buildLog('c:PromotionList:index') type TProps = { show?: boolean onAbout?: () => void - items: TItem[] + items?: TItem[] intervalSec?: number + onClose?: () => void } const PromotionList: FC = ({ diff --git a/src/components/TabBar/spec.ts b/src/components/TabBar/spec.ts index 795e54f2b..55fc4c87b 100644 --- a/src/components/TabBar/spec.ts +++ b/src/components/TabBar/spec.ts @@ -1,8 +1,8 @@ import { ReactNode } from 'react' export type TTabItem = { - title: string - raw: string + title?: string + raw?: string alias?: string icon?: string | ReactNode localIcon?: string diff --git a/src/containers/thread/PostsThread/index.js b/src/containers/thread/PostsThread/index.tsx similarity index 95% rename from src/containers/thread/PostsThread/index.js rename to src/containers/thread/PostsThread/index.tsx index 96541f350..2545d9aca 100755 --- a/src/containers/thread/PostsThread/index.js +++ b/src/containers/thread/PostsThread/index.tsx @@ -4,7 +4,7 @@ * */ -import React from 'react' +import { FC } from 'react' import { Waypoint } from 'react-waypoint' import { contains } from 'ramda' @@ -26,6 +26,8 @@ import PromotionList from '@/components/PromotionList' import CityList from './CityList' +import type { TStore } from './store' + import { Wrapper, LeftPart, @@ -78,7 +80,11 @@ const SpecThread = ({ community, thread, cityCommunities }) => { return } -const PostsThreadContainer = ({ postsThread: store }) => { +type TProps = { + postsThread?: TStore +} + +const PostsThreadContainer: FC = ({ postsThread: store }) => { useInit(store) const { @@ -149,7 +155,6 @@ const PostsThreadContainer = ({ postsThread: store }) => { { ) } -export default pluggedIn(PostsThreadContainer) +export default pluggedIn(PostsThreadContainer) as FC diff --git a/src/containers/thread/PostsThread/logic.js b/src/containers/thread/PostsThread/logic.ts similarity index 87% rename from src/containers/thread/PostsThread/logic.js rename to src/containers/thread/PostsThread/logic.ts index 80a7ccbf4..8d7e92cc7 100755 --- a/src/containers/thread/PostsThread/logic.js +++ b/src/containers/thread/PostsThread/logic.ts @@ -1,4 +1,4 @@ -import { values, contains, pickBy, merge } from 'ramda' +import { values, contains, pickBy } from 'ramda' import { useEffect } from 'react' import { @@ -10,6 +10,8 @@ import { COMMUNITY_SPEC_THREADS, } from '@/constant' +import type { TCommunity, TTag } from '@/spec' + import { asyncSuit, buildLog, @@ -20,6 +22,8 @@ import { scrollToTabber, } from '@/utils' +import type { TStore } from './store' + import S from './schema' /* eslint-disable-next-line */ @@ -27,6 +31,7 @@ const log = buildLog('L:PostsThread') const { SR71, $solver, asyncRes, asyncErr } = asyncSuit const sr71$ = new SR71({ + // @ts-ignore receive: [ EVENT.REFRESH_POSTS, EVENT.DRAWER.AFTER_CLOSE, @@ -47,7 +52,7 @@ export const outAnchor = () => { if (store) store.showTopModeline(true) } -export const loadPosts = (page = 1) => { +export const loadPosts = (page = 1): void => { const { curCommunity } = store const userHasLogin = store.isLogin @@ -70,25 +75,25 @@ export const loadPosts = (page = 1) => { store.markRoute({ page, ...store.filtersData }) } -export const onPageChange = (page) => { +export const onPageChange = (page = 1): void => { scrollToTabber() loadPosts(page) } -export const onFilterSelect = (option) => { +export const onFilterSelect = (option): void => { store.selectFilter(option) log('cur filter: ', store.filtersData) store.markRoute({ ...store.filtersData }) loadPosts() } -export const onTagSelect = (tag) => { +export const onTagSelect = (tag: TTag): void => { store.selectTag(tag) loadPosts() store.markRoute({ tag: tag.title }) } -export const onUserSelect = () => { +export const onUserSelect = (): void => { // } @@ -97,7 +102,7 @@ export const onUserSelect = () => { * * @param {*} data {id: string, title: string} */ -export const onPreview = (data) => { +export const onPreview = (data): void => { setTimeout(() => store.setViewedFlag(data.id), 1500) const type = TYPE.DRAWER.POST_VIEW const thread = THREAD.POST @@ -106,13 +111,13 @@ export const onPreview = (data) => { store.markRoute(data.id) } -export const onContentCreate = () => { +export const onContentCreate = (): void => { if (!store.isLogin) return store.authWarning() send(EVENT.DRAWER.OPEN, { type: TYPE.DRAWER.POST_CREATE }) } -export const onAdsClose = () => { +export const onAdsClose = (): void => { log('onAdsClose') if (store.isMemberOf('seniorMember') || store.isMemberOf('sponsorMember')) { return log('do custom ads') @@ -128,7 +133,7 @@ const loadCityCommunities = () => { } } -export const onCommunitySelect = (community) => { +export const onCommunitySelect = (community: TCommunity): void => { store.setViewing({ community, activeThread: THREAD.POST, post: {} }) store.markRoute({ @@ -140,7 +145,7 @@ export const onCommunitySelect = (community) => { } // toggle FAQ active state -export const onFaqChange = () => { +export const onFaqChange = (): void => { const { faqActive } = store store.mark({ faqActive: !faqActive }) } @@ -240,7 +245,7 @@ const ErrSolver = [ // ############################### // init & uninit // ############################### -export const useInit = (_store) => +export const useInit = (_store: TStore): void => useEffect(() => { store = _store sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) @@ -251,7 +256,7 @@ export const useInit = (_store) => loadCityCommunities() return () => { - if (store.curView === TYPE.LOADING || !sub$) return false + if (store.curView === TYPE.LOADING || !sub$) return // log('===== do uninit') sr71$.stop() sub$.unsubscribe() diff --git a/src/containers/thread/PostsThread/store.js b/src/containers/thread/PostsThread/store.ts similarity index 57% rename from src/containers/thread/PostsThread/store.js rename to src/containers/thread/PostsThread/store.ts index 5c58b13c7..b95148d36 100755 --- a/src/containers/thread/PostsThread/store.js +++ b/src/containers/thread/PostsThread/store.ts @@ -3,12 +3,21 @@ * */ -import { types as T, getParent } from 'mobx-state-tree' +import { types as T, getParent, Instance } from 'mobx-state-tree' import { merge, isEmpty, findIndex, propEq, pickBy } from 'ramda' import { TYPE, THREAD } from '@/constant' import { markStates, buildLog, stripMobx, nilOrEmpty, isObject } from '@/utils' +import type { + TRootStore, + TPost, + TAccount, + TRoute, + TCommunity, + TThread, +} from '@/spec' + import { PagedPosts, Tag, @@ -37,26 +46,28 @@ const PostsThreadStore = T.model('PostsThreadStore', { faqActive: T.optional(T.boolean, false), }) .views((self) => ({ - get root() { - return getParent(self) - }, - get curRoute() { - return self.root.curRoute + get curRoute(): TRoute { + const root = getParent(self) as TRootStore + return root.curRoute }, - get curCommunity() { - return stripMobx(self.root.viewing.community) + get curCommunity(): TCommunity { + const root = getParent(self) as TRootStore + return stripMobx(root.viewing.community) }, - get curThread() { - return self.root.viewing.activeThread + get curThread(): TThread { + const root = getParent(self) as TRootStore + return root.viewing.activeThread }, get pagedPostsData() { return stripMobx(self.pagedPosts) }, - get accountInfo() { - return self.root.account.accountInfo + get accountInfo(): TAccount { + const root = getParent(self) as TRootStore + return root.account.accountInfo }, - get isLogin() { - return self.root.account.isLogin + get isLogin(): boolean { + const root = getParent(self) as TRootStore + return root.account.isLogin }, get filtersData() { return stripMobx(pickBy((v) => !isEmpty(v), self.filters)) @@ -69,14 +80,16 @@ const PostsThreadStore = T.model('PostsThreadStore', { if (nilOrEmpty(curTag)) return {} return { tag: curTag.title } }, - get activePost() { - return stripMobx(self.root.viewing.post) + get activePost(): TPost { + const root = getParent(self) as TRootStore + return stripMobx(root.viewing.post) }, get pagedCityCommunitiesData() { return stripMobx(self.pagedCityCommunities) }, - get pageDensity() { - return self.root.account.pageDensity + get pageDensity(): number { + const root = getParent(self) as TRootStore + return root.account.pageDensity }, get showFilterBar() { const curFilter = stripMobx(pickBy((v) => !isEmpty(v), self.filters)) @@ -84,19 +97,23 @@ const PostsThreadStore = T.model('PostsThreadStore', { return !isEmpty(curFilter) || !isEmpty(pagedPosts.entries) }, - get isCommunityDigestInViewport() { - return self.root.communityDigest.inViewport + get isCommunityDigestInViewport(): boolean { + const root = getParent(self) as TRootStore + return root.communityDigest.inViewport }, })) .actions((self) => ({ - toastInfo(options) { - self.root.toast('info', merge({ position: 'topCenter' }, options)) + toastInfo(options): void { + const root = getParent(self) as TRootStore + root.toast('info', merge({ position: 'topCenter' }, options)) }, - isMemberOf(type) { - return self.root.isMemberOf(type) + isMemberOf(type): boolean { + const root = getParent(self) as TRootStore + return root.isMemberOf(type) }, - authWarning(options) { - self.root.authWarning(options) + authWarning(options = {}): void { + const root = getParent(self) as TRootStore + root.authWarning(options) }, selectFilter(option) { const curfilter = self.filtersData @@ -107,11 +124,13 @@ const PostsThreadStore = T.model('PostsThreadStore', { self.activeTag = cur }, - showTopModeline(fix) { - self.root.showTopModeline(fix) + showTopModeline(fix): void { + const root = getParent(self) as TRootStore + root.showTopModeline(fix) }, - setViewing(sobj) { - self.root.setViewing(sobj) + setViewing(sobj): void { + const root = getParent(self) as TRootStore + root.setViewing(sobj) }, setViewedFlag(id) { const { entries } = self.pagedPostsData @@ -120,7 +139,7 @@ const PostsThreadStore = T.model('PostsThreadStore', { self.pagedPosts.entries[index].viewerHasViewed = true } }, - updateItem(item) { + updateItem(item): void { const { entries } = self.pagedPostsData const index = findIndex(propEq('id', item.id), entries) if (index >= 0) { @@ -130,10 +149,11 @@ const PostsThreadStore = T.model('PostsThreadStore', { ) } }, - updateC11N(option) { - self.root.updateC11N(option) + updateC11N(option): void { + const root = getParent(self) as TRootStore + root.updateC11N(option) }, - markRoute(target) { + markRoute(target): void { const query = isObject(target) ? target : { @@ -144,11 +164,13 @@ const PostsThreadStore = T.model('PostsThreadStore', { ...self.filtersData, } - self.root.markRoute(query, { onlyDesktop: true }) + const root = getParent(self) as TRootStore + root.markRoute(query, { onlyDesktop: true }) }, mark(sobj) { markStates(sobj, self) }, })) +export type TStore = Instance export default PostsThreadStore diff --git a/src/containers/tool/CommunityJoinBadge/index.tsx b/src/containers/tool/CommunityJoinBadge/index.tsx index a7af51497..398d6c982 100755 --- a/src/containers/tool/CommunityJoinBadge/index.tsx +++ b/src/containers/tool/CommunityJoinBadge/index.tsx @@ -18,7 +18,7 @@ import { useInit } from './logic' const log = buildLog('C:CommunityJoinBadge') type TProps = { - communityJoinBadge: TStore + communityJoinBadge?: TStore testid?: string } diff --git a/src/containers/unit/TagsBar/CardView.js b/src/containers/unit/TagsBar/CardView.js deleted file mode 100644 index e165468da..000000000 --- a/src/containers/unit/TagsBar/CardView.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * TagsBar - * - */ - -import React from 'react' -import T from 'prop-types' - -import { ICON_CMD } from '@/config' -import { THREAD } from '@/constant' -import { buildLog, pluggedIn, sortByColor, Trans } from '@/utils' - -import { - Wrapper, - TagItem, - TagDot, - TagTitle, - AllTagIcon, -} from './styles/card_view' - -import { useInit, onTagSelect } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:TagsBar') - -const TagsBarContainer = ({ tagsBar: store, thread, active, onSelect }) => { - useInit(store, thread, active) - - const { tagsData, activeTagData } = store - - const sortedTags = sortByColor(tagsData) - const emptytag = { id: '', title: '', color: '' } - - return ( - - {activeTagData.title && ( - - - 全部 - - )} - - {sortedTags.map(({ id, color, title }) => ( - - - - {Trans(title)} - - - ))} - - ) -} - -TagsBarContainer.propTypes = { - tagsBar: T.object.isRequired, - thread: T.string, - onSelect: T.func.isRequired, - active: T.shape({ - id: T.string, - title: T.string, - color: T.string, - }), -} - -TagsBarContainer.defaultProps = { - thread: THREAD.POST, - active: {}, -} - -export default pluggedIn(TagsBarContainer) diff --git a/src/containers/unit/TagsBar/CardView.tsx b/src/containers/unit/TagsBar/CardView.tsx new file mode 100644 index 000000000..045395143 --- /dev/null +++ b/src/containers/unit/TagsBar/CardView.tsx @@ -0,0 +1,71 @@ +/* + * + * TagsBar + * + */ + +import { FC } from 'react' + +import { ICON_CMD } from '@/config' +import { buildLog, pluggedIn, sortByColor, Trans } from '@/utils' + +import type { TProps as TTagProps } from './index' +import { + Wrapper, + TagItem, + TagDot, + TagTitle, + AllTagIcon, +} from './styles/card_view' + +import { useInit, onTagSelect } from './logic' + +/* eslint-disable-next-line */ +const log = buildLog('C:TagsBar') + +type TProps = Omit + +const TagsBarContainer: FC = ({ + tagsBar: store, + thread, + active, + onSelect, +}) => { + useInit(store, thread, active) + + const { tagsData, activeTagData } = store + + const sortedTags = sortByColor(tagsData) + const emptytag = { id: '', title: '', color: '' } + + return ( + + {activeTagData.title && ( + { + onTagSelect(emptytag) + onSelect(emptytag) + }} + > + + 全部 + + )} + + {sortedTags.map(({ id, color, title }) => ( + { + onTagSelect(emptytag) + onSelect(emptytag) + }} + > + + {Trans(title)} + + ))} + + ) +} + +export default pluggedIn(TagsBarContainer) as FC diff --git a/src/containers/unit/TagsBar/DesktopView/Folder.js b/src/containers/unit/TagsBar/DesktopView/Folder.tsx similarity index 88% rename from src/containers/unit/TagsBar/DesktopView/Folder.js rename to src/containers/unit/TagsBar/DesktopView/Folder.tsx index 9bff75c09..bcf53c2c6 100644 --- a/src/containers/unit/TagsBar/DesktopView/Folder.js +++ b/src/containers/unit/TagsBar/DesktopView/Folder.tsx @@ -1,10 +1,12 @@ -import React, { useState, useRef, useEffect } from 'react' +import { FC, useState, useRef, useEffect } from 'react' import { findIndex } from 'ramda' import { ICON } from '@/config' import { sortByColor } from '@/utils' +import type { TTag } from '@/spec' + import TagItem from './TagItem' import { TagsWrapper } from '../styles/desktop_view' @@ -22,7 +24,21 @@ import { const MAX_DISPLAY_COUNT = 5 const TOGGLE_SUB_TOGGLE_THROLD = 15 -const Folder = ({ title, groupTags, allTags, activeTag, onSelect }) => { +type TProps = { + title: string + allTags: TTag[] + activeTag: TTag + groupTags: any + onSelect: (tag?: TTag) => void +} + +const Folder: FC = ({ + title, + groupTags, + allTags, + activeTag, + onSelect, +}) => { // 决定是否显示 '展示更多' 的时候参考标签总数 const needSubToggle = allTags?.length > TOGGLE_SUB_TOGGLE_THROLD && @@ -36,6 +52,7 @@ const Folder = ({ title, groupTags, allTags, activeTag, onSelect }) => { const sortedTags = sortByColor(groupTags) const isActiveTagInFolder = + // @ts-ignore findIndex((item) => item.id === activeTag.id, groupTags) >= 0 const subToggleRef = useRef(null) @@ -76,7 +93,7 @@ const Folder = ({ title, groupTags, allTags, activeTag, onSelect }) => { key={tag.id} tag={tag} active={activeTag.title === tag.title} - activeid={activeTag.id} + activeid={String(activeTag.id)} onSelect={onSelect} /> ))} diff --git a/src/containers/unit/TagsBar/DesktopView/GobackTag.js b/src/containers/unit/TagsBar/DesktopView/GobackTag.tsx similarity index 68% rename from src/containers/unit/TagsBar/DesktopView/GobackTag.js rename to src/containers/unit/TagsBar/DesktopView/GobackTag.tsx index a8a082d41..b10f58082 100644 --- a/src/containers/unit/TagsBar/DesktopView/GobackTag.js +++ b/src/containers/unit/TagsBar/DesktopView/GobackTag.tsx @@ -1,10 +1,14 @@ -import React from 'react' +import { FC } from 'react' +import type { TTag } from '@/spec' import { ICON } from '@/config' - import { Wrapper, TagIcon, TagTitle } from '../styles/desktop_view/goback_tag' -const GobackTag = ({ onSelect }) => { +type TProps = { + onSelect?: (tag?: TTag) => void +} + +const GobackTag: FC = ({ onSelect }) => { const emptytag = { id: '', title: '', color: '' } return ( diff --git a/src/containers/unit/TagsBar/DesktopView/TagCount.js b/src/containers/unit/TagsBar/DesktopView/TagCount.tsx similarity index 100% rename from src/containers/unit/TagsBar/DesktopView/TagCount.js rename to src/containers/unit/TagsBar/DesktopView/TagCount.tsx diff --git a/src/containers/unit/TagsBar/DesktopView/TagItem.js b/src/containers/unit/TagsBar/DesktopView/TagItem.tsx similarity index 72% rename from src/containers/unit/TagsBar/DesktopView/TagItem.js rename to src/containers/unit/TagsBar/DesktopView/TagItem.tsx index 7078d308c..ae7a8dc6f 100644 --- a/src/containers/unit/TagsBar/DesktopView/TagItem.js +++ b/src/containers/unit/TagsBar/DesktopView/TagItem.tsx @@ -1,7 +1,8 @@ -import React from 'react' +import { FC } from 'react' import { getRandomInt, Trans } from '@/utils' import { SpaceGrow } from '@/components/Common' +import type { TTag } from '@/spec' import TagCount from './TagCount' @@ -12,7 +13,21 @@ import { CountInfoWrapper, } from '../styles/desktop_view/tag_item' -const TagItem = ({ tag, active, activeid, inline, onSelect }) => { +type TProps = { + tag: TTag + active: boolean + activeid?: string + inline?: boolean + onSelect?: (tag?: TTag) => void +} + +const TagItem: FC = ({ + tag, + active, + activeid, + inline = true, + onSelect, +}) => { return ( { +type TProps = Omit + +const TagsBarContainer: FC = ({ + tagsBar: store, + thread = THREAD.POST, + active, + onSelect, +}) => { useInit(store, thread, active) const { groupedTags, tagsData, activeTagData } = store const groupsKeys = keys(groupedTags) @@ -38,8 +46,8 @@ const TagsBarContainer = ({ tagsBar: store, thread, active, onSelect }) => { )} {groupsKeys.map((groupKey) => ( { ) } -TagsBarContainer.propTypes = { - tagsBar: T.object.isRequired, - thread: T.string, - onSelect: T.func.isRequired, - active: T.shape({ - id: T.string, - title: T.string, - color: T.string, - }), -} - -TagsBarContainer.defaultProps = { - thread: THREAD.POST, - active: {}, -} - -export default pluggedIn(TagsBarContainer) +export default pluggedIn(TagsBarContainer) as FC diff --git a/src/containers/unit/TagsBar/index.js b/src/containers/unit/TagsBar/index.tsx similarity index 61% rename from src/containers/unit/TagsBar/index.js rename to src/containers/unit/TagsBar/index.tsx index a8f81ce0c..65a11758f 100755 --- a/src/containers/unit/TagsBar/index.js +++ b/src/containers/unit/TagsBar/index.tsx @@ -4,16 +4,26 @@ * */ -import React from 'react' -import T from 'prop-types' +import { FC } from 'react' import { VIEW } from '@/constant' +import type { TTag, TThread } from '@/spec' +import type { TStore } from './store' import DesktopView from './DesktopView/index' import CardView from './CardView' -const TagsBar = (props) => { +export type TProps = { + view?: string + tagsBar?: TStore + thread: TThread + onSelect: (tag?: TTag) => void + active: TTag +} + +const TagsBar: FC = (props) => { const { view } = props + switch (view) { case VIEW.MOBILE: { // TODO: @@ -30,12 +40,4 @@ const TagsBar = (props) => { } } -TagsBar.propTypes = { - view: T.oneOf([VIEW.DESKTOP, VIEW.MOBILE, VIEW.COMMUNITY_CARD]), -} - -TagsBar.defaultProps = { - view: VIEW.DESKTOP, -} - export default TagsBar diff --git a/src/containers/unit/TagsBar/logic.js b/src/containers/unit/TagsBar/logic.ts similarity index 85% rename from src/containers/unit/TagsBar/logic.js rename to src/containers/unit/TagsBar/logic.ts index c4d2d977f..68e2aca5f 100755 --- a/src/containers/unit/TagsBar/logic.js +++ b/src/containers/unit/TagsBar/logic.ts @@ -1,6 +1,8 @@ import { useEffect } from 'react' import { isEmpty, pick, contains, toUpper } from 'ramda' +import type { TTag, TThread } from '@/spec' +import type { TStore } from './store' import { EVENT, ERR, THREAD } from '@/constant' import { asyncSuit, buildLog, errRescue } from '@/utils' @@ -11,23 +13,20 @@ const log = buildLog('L:TagsBar') const { SR71, $solver, asyncRes, asyncErr } = asyncSuit const sr71$ = new SR71({ + // @ts-ignore receive: [EVENT.COMMUNITY_CHANGE, EVENT.THREAD_CHANGE], }) let sub$ = null -let store = null +let store: TStore | undefined -export const onTagSelect = (tag, cb) => { - store.selectTag(tag) - - if (cb) cb(tag) -} +export const onTagSelect = (tag: TTag): void => store.selectTag(tag) const NO_TAG_THREADS = [THREAD.USER, THREAD.CHEATSHEET, THREAD.WIKI] -export const loadTags = () => { +export const loadTags = (): void => { const { curThread } = store - if (contains(curThread, NO_TAG_THREADS)) return false + if (contains(curThread, NO_TAG_THREADS)) return const community = store.curCommunity.raw const thread = toUpper(curThread) @@ -90,7 +89,11 @@ const ErrSolver = [ // init & uninit // ############################### -export const useInit = (_store, thread, active) => { +export const useInit = ( + _store: TStore, + thread: TThread, + active: TTag, +): void => { useEffect(() => { store = _store log('effect init') diff --git a/src/containers/unit/TagsBar/store.ts b/src/containers/unit/TagsBar/store.ts index 38d328a15..aad4d06d7 100755 --- a/src/containers/unit/TagsBar/store.ts +++ b/src/containers/unit/TagsBar/store.ts @@ -41,7 +41,7 @@ const TagsBar = T.model('TagsBar', { return groupByKey( tagsData.map((tag) => { - if (tag.id < 4) { + if (parseInt(tag.id, 10) < 4) { tag.group = '这是第一组' } else { tag.group = '这是第二组' // '__default__' @@ -58,9 +58,10 @@ const TagsBar = T.model('TagsBar', { self.activeTag = cur }, - getTagIdByTitle(title: string): boolean | number { + getTagIdByTitle(title: string): boolean | string { if (!title) return false + // @ts-ignore const index = findIndex(propEq('title', title), self.tagsData) if (index >= 0) { return self.tagsData[index].id diff --git a/src/spec/community.ts b/src/spec/community.ts index 792ce8834..b80250218 100644 --- a/src/spec/community.ts +++ b/src/spec/community.ts @@ -1,8 +1,8 @@ export type TCommunity = { id?: string - title: string + title?: string logo?: string - raw: string + raw?: string subscribersCount?: number viewerHasSubscribed?: boolean desc?: string @@ -18,8 +18,8 @@ export type TPagedCommunities = { } export type TTag = { - id: number - title: string - color: string + id?: string + title?: string + color?: string group?: string } diff --git a/src/spec/comp.ts b/src/spec/comp.ts index cb2bf1b1a..17864431e 100644 --- a/src/spec/comp.ts +++ b/src/spec/comp.ts @@ -2,11 +2,12 @@ import { TSIZE } from './size' // @/components/button export type TButton = { - size: TSIZE + size?: TSIZE active?: boolean ghost?: boolean disabled?: boolean noBorder?: boolean + onClick?: (key?: string) => void } // @/components/FiltersMenu diff --git a/src/spec/utils.ts b/src/spec/utils.ts index f4cf634e0..52799857d 100644 --- a/src/spec/utils.ts +++ b/src/spec/utils.ts @@ -85,8 +85,8 @@ export type TAttInfo = { export type TTabItem = { id?: string - title: string - raw: string + title?: string + raw?: string alias?: string icon?: string | ReactNode localIcon?: string diff --git a/utils/helper.ts b/utils/helper.ts index 429ae801b..8e0217574 100755 --- a/utils/helper.ts +++ b/utils/helper.ts @@ -13,8 +13,8 @@ type TSORTABLE_ITEMS = { color?: string index?: number id?: string - title: string - raw: string + title?: string + raw?: string logo?: string }[] From 4ec74e4ab46923c8de9ca2a29cfd5186fcfc5661 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 29 Jun 2021 14:53:54 +0800 Subject: [PATCH 4/7] chore(blog): basic thread setup --- .../content/CommunityContent/index.tsx | 4 + .../digest/CommunityDigest/index.js | 2 - src/containers/thread/BlogsThread/index.tsx | 156 ++++++++++++++++++ src/containers/thread/BlogsThread/logic.ts | 80 +++++++++ src/containers/thread/BlogsThread/schema.ts | 23 +++ src/containers/thread/BlogsThread/store.ts | 143 ++++++++++++++++ .../thread/BlogsThread/styles/index.ts | 45 +++++ .../thread/BlogsThread/tests/index.test.js | 10 ++ .../thread/BlogsThread/tests/store.test.js | 10 ++ src/spec/article.ts | 5 + src/spec/index.ts | 1 + src/stores/RootStore/index.ts | 2 + src/stores/SharedModel/Blog.ts | 50 ++++++ src/stores/SharedModel/index.ts | 1 + src/stores/ViewingStore/index.ts | 5 +- src/stores/index.ts | 1 + utils/constant/type.ts | 5 + 17 files changed, 540 insertions(+), 3 deletions(-) create mode 100755 src/containers/thread/BlogsThread/index.tsx create mode 100755 src/containers/thread/BlogsThread/logic.ts create mode 100755 src/containers/thread/BlogsThread/schema.ts create mode 100755 src/containers/thread/BlogsThread/store.ts create mode 100755 src/containers/thread/BlogsThread/styles/index.ts create mode 100755 src/containers/thread/BlogsThread/tests/index.test.js create mode 100755 src/containers/thread/BlogsThread/tests/store.test.js create mode 100755 src/stores/SharedModel/Blog.ts diff --git a/src/containers/content/CommunityContent/index.tsx b/src/containers/content/CommunityContent/index.tsx index 0d3cbcba1..32befd0da 100755 --- a/src/containers/content/CommunityContent/index.tsx +++ b/src/containers/content/CommunityContent/index.tsx @@ -11,6 +11,7 @@ import { useDevice } from '@/hooks' import { pluggedIn, buildLog } from '@/utils' import PostsThread from '@/containers//thread/PostsThread' +import BlogsThread from '@/containers//thread/BlogsThread' import ReposThread from '@/containers/thread/ReposThread' import WikiThread from '@/containers/thread/WikiThread' import JobsThread from '@/containers/thread/JobsThread' @@ -30,6 +31,9 @@ const ComunityContent = ({ curRoute }) => { case ROUTE.REPOS: return + case ROUTE.BLOGS: + return + case ROUTE.USERS: return diff --git a/src/containers/digest/CommunityDigest/index.js b/src/containers/digest/CommunityDigest/index.js index 66f378a85..1d3b498cd 100755 --- a/src/containers/digest/CommunityDigest/index.js +++ b/src/containers/digest/CommunityDigest/index.js @@ -29,8 +29,6 @@ const CommunityDigestContainer = ({ communityDigest: store, metric }) => { isHeaderFixed, } = store - console.log('community --> ', community) - return ( {bannerLayout === C11N.BRIEF ? ( diff --git a/src/containers/thread/BlogsThread/index.tsx b/src/containers/thread/BlogsThread/index.tsx new file mode 100755 index 000000000..fffc9f7fa --- /dev/null +++ b/src/containers/thread/BlogsThread/index.tsx @@ -0,0 +1,156 @@ +// + +/* + * + * BlogsThread + * + */ + +import { FC } from 'react' + +import { ICON } from '@/config' +import { pluggedIn, buildLog } from '@/utils' +import { C11N, THREAD, ROUTE } from '@/constant' + +import CommunityJoinBadge from '@/containers/tool/CommunityJoinBadge' +import TagsBar from '@/containers/unit/TagsBar' + +import Sticky from '@/components/Sticky' +import PagedContents from '@/components/PagedContents' +import ContentFilter from '@/components/ContentFilter' +import { DropdownButton } from '@/components/Buttons' +import PromotionList from '@/components/PromotionList' + +import type { TStore } from './store' + +import { + Wrapper, + LeftPart, + RightPart, + FilterWrapper, + BadgeWrapper, + PublisherWrapper, +} from './styles' + +import { + useInit, + onFilterSelect, + onUserSelect, + onPreview, + onPageChange, + onContentCreate, + onTagSelect, + onAdsClose, +} from './logic' + +/* eslint-disable-next-line */ +const log = buildLog('C:BlogsThread') + +type TProps = { + blogsThread?: TStore + testid?: string +} + +const BlogsThreadContainer: FC = ({ + blogsThread: store, + testid = 'blogs-thread', +}) => { + useInit(store) + + const { + pagedBlogsData, + curView, + filtersData, + activeBlog, + curRoute, + accountInfo, + isLogin, + activeTagData, + curCommunity, + curThread, + showFilterBar, + accountInfo: { + customization: { bannerLayout }, + }, + isCommunityDigestInViewport, + } = store + + const { subPath } = curRoute + const { totalCount } = pagedBlogsData + + return ( + + + {showFilterBar && ( + + + + )} + + + + + + + { + if (key === 'publish') onContentCreate() + }} + > + 提交博客 + + + + + + + + + + + + + ) +} + +export default pluggedIn(BlogsThreadContainer) as FC diff --git a/src/containers/thread/BlogsThread/logic.ts b/src/containers/thread/BlogsThread/logic.ts new file mode 100755 index 000000000..fa1ec44a6 --- /dev/null +++ b/src/containers/thread/BlogsThread/logic.ts @@ -0,0 +1,80 @@ +import { useEffect } from 'react' +// import { } from 'ramda' + +import type { TTag } from '@/spec' + +import { TYPE, EVENT, THREAD } from '@/constant' +import { send, buildLog, scrollToTabber } from '@/utils' + +// import S from './service' +import type { TStore } from './store' + +let store: TStore | undefined + +/* eslint-disable-next-line */ +const log = buildLog('L:BlogsThread') + +export const loadBlogs = (page = 1): void => { + log('loadBlogs') +} + +/** + * preview the current article + * + * @param {*} data {id: string, title: string} + */ +export const onPreview = (data): void => { + setTimeout(() => store.setViewedFlag(data.id), 1500) + const type = TYPE.DRAWER.BLOG_VIEW + const thread = THREAD.BLOG + + send(EVENT.DRAWER.OPEN, { type, thread, data }) + store.markRoute(data.id) +} + +export const onContentCreate = (): void => { + if (!store.isLogin) return store.authWarning() + + send(EVENT.DRAWER.OPEN, { type: TYPE.DRAWER.BLOG_CREATE }) +} + +export const onAdsClose = (): void => { + log('onAdsClose') + if (store.isMemberOf('seniorMember') || store.isMemberOf('sponsorMember')) { + return log('do custom ads') + } +} + +export const onPageChange = (page = 1): void => { + scrollToTabber() + loadBlogs(page) +} + +export const onFilterSelect = (option): void => { + store.selectFilter(option) + log('cur filter: ', store.filtersData) + store.markRoute({ ...store.filtersData }) + loadBlogs() +} + +export const onTagSelect = (tag: TTag): void => { + store.selectTag(tag) + loadBlogs() + store.markRoute({ tag: tag.title }) +} + +export const onUserSelect = (): void => { + // +} + +// ############################### +// init & uninit handlers +// ############################### + +export const useInit = (_store: TStore): void => { + useEffect(() => { + store = _store + log('useInit: ', store) + // return () => store.reset() + }, [_store]) +} diff --git a/src/containers/thread/BlogsThread/schema.ts b/src/containers/thread/BlogsThread/schema.ts new file mode 100755 index 000000000..0035db982 --- /dev/null +++ b/src/containers/thread/BlogsThread/schema.ts @@ -0,0 +1,23 @@ +import gql from 'graphql-tag' + +const simpleMutation = gql` + mutation($id: ID!) { + post(id: $id) { + id + } + } +` +const simpleQuery = gql` + query($filter: filter!) { + post(id: $id) { + id + } + } +` + +const schema = { + simpleMutation, + simpleQuery, +} + +export default schema diff --git a/src/containers/thread/BlogsThread/store.ts b/src/containers/thread/BlogsThread/store.ts new file mode 100755 index 000000000..5237f4087 --- /dev/null +++ b/src/containers/thread/BlogsThread/store.ts @@ -0,0 +1,143 @@ +/* + * BlogsThread store + */ + +import { types as T, getParent, Instance } from 'mobx-state-tree' +import { findIndex, propEq, merge, isEmpty, pickBy } from 'ramda' + +import { TYPE, THREAD } from '@/constant' + +import type { + TCommunity, + TRootStore, + TThread, + TRoute, + TBlog, + TAccount, +} from '@/spec' +import { PagedBlogs, Tag, ContentFilter, emptyPagiData } from '@/model' +import { markStates, buildLog, stripMobx, nilOrEmpty, isObject } from '@/utils' + +/* eslint-disable-next-line */ +const log = buildLog('S:BlogsThread') + +const BlogsThread = T.model('BlogsThread', { + pagedBlogs: T.optional(PagedBlogs, emptyPagiData), + filters: T.optional(ContentFilter, {}), + activeTag: T.maybeNull(Tag), + curView: T.optional( + T.enumeration('curView', [ + TYPE.RESULT, + TYPE.LOADING, + TYPE.NOT_FOUND, + TYPE.RESULT_EMPTY, + ]), + TYPE.RESULT, + ), +}) + .views((self) => ({ + get curRoute(): TRoute { + const root = getParent(self) as TRootStore + return root.curRoute + }, + get curCommunity(): TCommunity { + const root = getParent(self) as TRootStore + + return stripMobx(root.viewing.community) + }, + get curThread(): TThread { + const root = getParent(self) as TRootStore + return root.viewing.activeThread + }, + get pagedBlogsData() { + return stripMobx(self.pagedBlogs) + }, + get accountInfo(): TAccount { + const root = getParent(self) as TRootStore + return root.account.accountInfo + }, + get isLogin(): boolean { + const root = getParent(self) as TRootStore + return root.account.isLogin + }, + get filtersData() { + return stripMobx(pickBy((v) => !isEmpty(v), self.filters)) + }, + get activeTagData() { + return stripMobx(self.activeTag) || {} + }, + get tagQuery() { + const curTag = stripMobx(self.activeTag) + if (nilOrEmpty(curTag)) return {} + return { tag: curTag.title } + }, + get activeBlog(): TBlog { + const root = getParent(self) as TRootStore + return stripMobx(root.viewing.blog) + }, + get pageDensity(): number { + const root = getParent(self) as TRootStore + return root.account.pageDensity + }, + get showFilterBar() { + const curFilter = stripMobx(pickBy((v) => !isEmpty(v), self.filters)) + const pagedBlogs = stripMobx(self.pagedBlogs) + + return !isEmpty(curFilter) || !isEmpty(pagedBlogs.entries) + }, + get isCommunityDigestInViewport(): boolean { + const root = getParent(self) as TRootStore + return root.communityDigest.inViewport + }, + })) + .actions((self) => ({ + authWarning(options = {}): void { + const root = getParent(self) as TRootStore + root.authWarning(options) + }, + isMemberOf(type): boolean { + const root = getParent(self) as TRootStore + return root.isMemberOf(type) + }, + selectFilter(option) { + const curfilter = self.filtersData + self.filters = merge(curfilter, option) + }, + selectTag(tag) { + const cur = tag.title === '' ? null : tag + + self.activeTag = cur + }, + setViewing(sobj): void { + const root = getParent(self) as TRootStore + root.setViewing(sobj) + }, + setViewedFlag(id) { + const { entries } = self.pagedBlogsData + const index = findIndex(propEq('id', id), entries) + if (index >= 0) { + self.pagedBlogs.entries[index].viewerHasViewed = true + } + }, + markRoute(target): void { + const query = isObject(target) + ? target + : { + id: target, + preview: THREAD.BLOG, + community: self.curCommunity.raw, + ...self.tagQuery, + ...self.filtersData, + } + + const root = getParent(self) as TRootStore + root.markRoute(query, { onlyDesktop: true }) + }, + mark(sobj: Record): void { + markStates(sobj, self) + }, + })) + +export type TStore = Instance + +export default BlogsThread diff --git a/src/containers/thread/BlogsThread/styles/index.ts b/src/containers/thread/BlogsThread/styles/index.ts new file mode 100755 index 000000000..34ad10fdb --- /dev/null +++ b/src/containers/thread/BlogsThread/styles/index.ts @@ -0,0 +1,45 @@ +import styled from 'styled-components' + +import type { TActive, TTestable } from '@/spec' +import { css, theme } from '@/utils' + +export const Wrapper = styled.div.attrs(({ testid }: TTestable) => ({ + 'data-test-id': testid, +}))` + ${css.flex()}; + width: 100%; +` +export const LeftPart = styled.div` + flex-grow: 1; + width: 100%; + background: ${theme('content.bg')}; + border-radius: 6px; + + padding-top: 15px; + padding-left: 25px; + padding-right: 24px; +` +export const RightPart = styled.div` + min-width: 200px; + max-width: 200px; + padding-top: 20px; + margin-left: 40px; + + ${css.media.tablet`display: none;`}; +` +export const PublisherWrapper = styled.div` + display: ${({ show }) => (show ? 'block' : 'none')}; + width: 160px; + max-width: 180px; + margin-left: 16px; +` +export const BadgeWrapper = styled.div` + display: ${({ show }) => (show ? 'block' : 'none')}; + margin-left: 18px; +` +export const FilterWrapper = styled.div` + ${css.flex('align-center')}; + margin-bottom: 10px; + ${css.media.mobile`margin-bottom: 4px;`}; + margin-left: -5px; +` diff --git a/src/containers/thread/BlogsThread/tests/index.test.js b/src/containers/thread/BlogsThread/tests/index.test.js new file mode 100755 index 000000000..04e62ae65 --- /dev/null +++ b/src/containers/thread/BlogsThread/tests/index.test.js @@ -0,0 +1,10 @@ +// import React from 'react' +// import { shallow } from 'enzyme' + +// import BlogsThread from '../index' + +describe('TODO ', () => { + it('Expect to have unit tests specified', () => { + expect(true).toEqual(true) + }) +}) diff --git a/src/containers/thread/BlogsThread/tests/store.test.js b/src/containers/thread/BlogsThread/tests/store.test.js new file mode 100755 index 000000000..476be0d75 --- /dev/null +++ b/src/containers/thread/BlogsThread/tests/store.test.js @@ -0,0 +1,10 @@ +/* + * BlogsThread store test + * + */ + +// import BlogsThread from '../index' + +it('TODO: store test BlogsThread', () => { + expect(1 + 1).toBe(2) +}) diff --git a/src/spec/article.ts b/src/spec/article.ts index 8913b41b3..22ce9ec42 100644 --- a/src/spec/article.ts +++ b/src/spec/article.ts @@ -28,6 +28,11 @@ export type TPost = TArticle & { linkIcon?: string } +export type TBlog = TArticle & { + digest?: string + linkAddr?: string +} + export type TJob = { id: string title: string diff --git a/src/spec/index.ts b/src/spec/index.ts index a70992115..c6139a39b 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -42,6 +42,7 @@ export type { TGQLError } from './graphql' export type { TArticle, TPost, + TBlog, TJob, TPagedJobs, TComment, diff --git a/src/stores/RootStore/index.ts b/src/stores/RootStore/index.ts index 2152c8a80..3ecddea49 100755 --- a/src/stores/RootStore/index.ts +++ b/src/stores/RootStore/index.ts @@ -94,6 +94,7 @@ import { CoolGuideContentStore, // GEN: IMPORT SUBSTORE + BlogsThreadStore, AbuseReportStore, HelpCenterContentStore, CommunityJoinBadgeStore, @@ -210,6 +211,7 @@ const rootStore = T.model({ coolGuideContent: T.optional(CoolGuideContentStore, {}), // GEN: PLUG SUBSTORE TO ROOTSTORE + blogsThread: T.optional(BlogsThreadStore, {}), abuseReport: T.optional(AbuseReportStore, {}), helpCenterContent: T.optional(HelpCenterContentStore, {}), communityJoinBadge: T.optional(CommunityJoinBadgeStore, {}), diff --git a/src/stores/SharedModel/Blog.ts b/src/stores/SharedModel/Blog.ts new file mode 100755 index 000000000..95fba1008 --- /dev/null +++ b/src/stores/SharedModel/Blog.ts @@ -0,0 +1,50 @@ +import { types as T } from 'mobx-state-tree' + +import { PAGE_SIZE } from '@/config' + +import { User, PagedUsers } from './User' +import { Community } from './Community' +import { Comment } from './Comment' +import { Tag } from './Tag' + +export const Blog = T.model('Blog', { + id: T.maybeNull(T.string), + title: T.optional(T.string, ''), + body: T.maybeNull(T.string), + digest: T.maybeNull(T.string), + author: T.maybeNull(User), + + linkAddr: T.maybeNull(T.string), + + communities: T.optional(T.array(Community), []), + origialCommunity: T.optional(Community, {}), + tags: T.optional(T.array(Tag), []), + comments: T.optional(T.array(Comment), []), + + commentsCount: T.optional(T.number, 0), + commentsParticipatorsCount: T.optional(T.number, 0), + commentsParticipators: T.optional(T.array(User), []), + views: T.optional(T.number, 0), + pin: T.maybeNull(T.boolean), + length: T.optional(T.number, 0), + favoritedCount: T.optional(T.number, 0), + starredCount: T.optional(T.number, 0), + viewerHasFavorited: T.optional(T.boolean, false), + viewerHasStarred: T.optional(T.boolean, false), + favoritedCategoryId: T.maybeNull(T.string), + + pagedCommentsParticipators: T.optional(PagedUsers, {}), + + viewerHasViewed: T.optional(T.boolean, false), + + insertedAt: T.optional(T.string, ''), + updatedAt: T.optional(T.string, ''), +}) + +export const PagedBlogs = T.model('PagedBlogs', { + entries: T.optional(T.array(Blog), []), + pageNumber: T.optional(T.number, 1), + pageSize: T.optional(T.number, PAGE_SIZE.D), + totalCount: T.optional(T.number, 0), + totalPages: T.optional(T.number, 0), +}) diff --git a/src/stores/SharedModel/index.ts b/src/stores/SharedModel/index.ts index a23d6df61..73dae0162 100755 --- a/src/stores/SharedModel/index.ts +++ b/src/stores/SharedModel/index.ts @@ -10,6 +10,7 @@ export { PagedRepoComments, } from './Comment' export { Post, PagedPosts } from './Post' +export { Blog, PagedBlogs } from './Blog' export { Repo, PagedRepos } from './Repo' export { Job, PagedJobs } from './Job' export { Tag, PagedTags } from './Tag' diff --git a/src/stores/ViewingStore/index.ts b/src/stores/ViewingStore/index.ts index 8b1e75d85..55a7885fd 100755 --- a/src/stores/ViewingStore/index.ts +++ b/src/stores/ViewingStore/index.ts @@ -9,7 +9,7 @@ import { values, merge } from 'ramda' import type { TRootStore, TUser, TArticle, TThread, TAccount } from '@/spec' import { THREAD } from '@/constant' import { markStates, buildLog, stripMobx } from '@/utils' -import { User, Community, Post, Job, Repo } from '@/model' +import { User, Community, Post, Blog, Job, Repo } from '@/model' /* eslint-disable-next-line */ const log = buildLog('S:ViewingStore') @@ -20,6 +20,7 @@ const ViewingStore = T.model('ViewingStore', { user: T.optional(User, {}), community: T.optional(Community, {}), post: T.optional(Post, {}), + blog: T.optional(Blog, {}), job: T.optional(Job, {}), repo: T.optional(Repo, {}), activeThread: T.optional( @@ -53,6 +54,8 @@ const ViewingStore = T.model('ViewingStore', { switch (curThread) { case THREAD.JOB: return stripMobx(self.job) + case THREAD.BLOG: + return stripMobx(self.blog) case THREAD.REPO: return stripMobx(self.repo) default: diff --git a/src/stores/index.ts b/src/stores/index.ts index 9faf9f1de..a73cdb029 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -101,6 +101,7 @@ export { default as CommunityEditorStore } from '@/containers/editor/CommunityEd export { default as WorksEditorStore } from '@/containers/editor/WorksEditor/store' // GEN: EXPORT CONTAINERS STORE HERE +export { default as BlogsThreadStore } from '@/containers/thread/BlogsThread/store' export { default as AbuseReportStore } from '@/containers/tool/AbuseReport/store' export { default as HelpCenterContentStore } from '@/containers/content/HelpCenterContent/store' export { default as CommunityJoinBadgeStore } from '@/containers/tool/CommunityJoinBadge/store' diff --git a/utils/constant/type.ts b/utils/constant/type.ts index a8afe6ec2..cc08ed05e 100755 --- a/utils/constant/type.ts +++ b/utils/constant/type.ts @@ -11,6 +11,7 @@ const TYPE = { POST: 'POST', JOB: 'JOB', + BLOG: 'BLOG', REPO: 'REPO', // actions FAVORITE: 'FAVORITE', @@ -39,6 +40,10 @@ const TYPE = { POST_CREATE: 'POST_CREATE', POST_EDIT: 'POST_EDIT', + BLOG_VIEW: 'BLOG_VIEW', + BLOG_CREATE: 'BLOG_CREATE', + BLOG_EDIT: 'BLOG_EDIT', + JOB_VIEW: 'JOB_VIEW', JOB_CREATE: 'JOB_CREATE', JOB_EDIT: 'JOB_EDIT', From 487b433795d6a71e4c202b191537b8f028bbcbad Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 29 Jun 2021 17:14:41 +0800 Subject: [PATCH 5/7] chore(posts): clean up unused thread --- src/components/Switcher/Tabs/LocalIcon.tsx | 24 --- .../Switcher/styles/tabs/local_icon.ts | 8 - src/containers/editor/PostEditor/Header.js | 19 -- src/containers/editor/PostEditor/logic.js | 12 -- src/containers/thread/PostsThread/CityCard.js | 43 ----- src/containers/thread/PostsThread/CityList.js | 42 ----- .../thread/PostsThread/CitySideNote.js | 38 ---- src/containers/thread/PostsThread/index.tsx | 177 +++++++----------- src/containers/thread/PostsThread/logic.ts | 62 +----- src/containers/thread/PostsThread/store.ts | 12 +- .../thread/PostsThread/styles/city_card.ts | 80 -------- .../thread/PostsThread/styles/city_list.ts | 37 ---- .../PostsThread/styles/city_side_note.ts | 33 ---- src/containers/unit/TagsBar/logic.ts | 2 +- utils/constant/index.ts | 2 +- utils/constant/route.ts | 3 - utils/constant/thread.ts | 19 +- 17 files changed, 85 insertions(+), 528 deletions(-) delete mode 100755 src/containers/thread/PostsThread/CityCard.js delete mode 100755 src/containers/thread/PostsThread/CityList.js delete mode 100755 src/containers/thread/PostsThread/CitySideNote.js delete mode 100755 src/containers/thread/PostsThread/styles/city_card.ts delete mode 100755 src/containers/thread/PostsThread/styles/city_list.ts delete mode 100755 src/containers/thread/PostsThread/styles/city_side_note.ts diff --git a/src/components/Switcher/Tabs/LocalIcon.tsx b/src/components/Switcher/Tabs/LocalIcon.tsx index fcce21658..aa431a79f 100644 --- a/src/components/Switcher/Tabs/LocalIcon.tsx +++ b/src/components/Switcher/Tabs/LocalIcon.tsx @@ -1,13 +1,9 @@ import { FC, memo } from 'react' import { TabPostIcon, - TabTechIcon, TabRadarIcon, - TabShareIcon, TabUserIcon, - TabCityIcon, TabJobIcon, - TabWikiIcon, TabRepoIcon, TabCheatsheetIcon, // user @@ -27,21 +23,11 @@ type TProps = { const TabIcon: FC = ({ raw, active, small }) => { switch (raw) { - case 'tech': { - /* @ts-ignore */ - return - } - case 'radar': { /* @ts-ignore */ return } - case 'share': { - /* @ts-ignore */ - return - } - case 'user': { /* @ts-ignore */ return @@ -52,16 +38,6 @@ const TabIcon: FC = ({ raw, active, small }) => { return } - case 'city': { - /* @ts-ignore */ - return - } - - case 'wiki': { - /* @ts-ignore */ - return - } - case 'repo': { /* @ts-ignore */ return diff --git a/src/components/Switcher/styles/tabs/local_icon.ts b/src/components/Switcher/styles/tabs/local_icon.ts index 85dbd2ebb..fd72f7245 100644 --- a/src/components/Switcher/styles/tabs/local_icon.ts +++ b/src/components/Switcher/styles/tabs/local_icon.ts @@ -3,14 +3,10 @@ import styled from 'styled-components' // import Img from '@/Img' import { theme, css } from '@/utils' import TabPostSVG from '@/SvgIcons/TabPostSVG' -import TabTechSVG from '@/SvgIcons/TabTechSVG' import TabRadarSVG from '@/SvgIcons/TabRadarSVG' -import TabShareSVG from '@/SvgIcons/TabShareSVG' import TabUserSVG from '@/SvgIcons/TabUserSVG' -import TabCitySVG from '@/SvgIcons/TabCitySVG' import TabJobSVG from '@/SvgIcons/TabJobSVG' // -import TabWikiSVG from '@/SvgIcons/TabWikiSVG' import TabRepoSVG from '@/SvgIcons/TabRepoSVG' import TabCheatsheetSVG from '@/SvgIcons/TabCheatsheetSVG' @@ -40,13 +36,9 @@ const commonIcon = (comp) => { } export const TabPostIcon = commonIcon(TabPostSVG) -export const TabTechIcon = commonIcon(TabTechSVG) export const TabRadarIcon = commonIcon(TabRadarSVG) -export const TabShareIcon = commonIcon(TabShareSVG) export const TabUserIcon = commonIcon(TabUserSVG) -export const TabCityIcon = commonIcon(TabCitySVG) export const TabJobIcon = commonIcon(TabJobSVG) -export const TabWikiIcon = commonIcon(TabWikiSVG) export const TabRepoIcon = commonIcon(TabRepoSVG) export const TabCheatsheetIcon = commonIcon(TabCheatsheetSVG) diff --git a/src/containers/editor/PostEditor/Header.js b/src/containers/editor/PostEditor/Header.js index a9d612cb7..673719327 100755 --- a/src/containers/editor/PostEditor/Header.js +++ b/src/containers/editor/PostEditor/Header.js @@ -21,25 +21,6 @@ const DoingText = ({ isEdit }) => { return isEdit ? <>更新 : <>发布 } -/* -const ThreadText = ({ thread }) => { - switch (thread) { - case THREAD.JOB: { - return '工作' - } - case THREAD.SHARE: { - return '分享' - } - case THREAD.RADAR: { - return '信息' - } - default: { - return '帖子' - } - } -} -*/ - const Header = ({ isEdit, curView, referUsers }) => { switch (curView) { case 'MARKDOWN_HELP_VIEW': diff --git a/src/containers/editor/PostEditor/logic.js b/src/containers/editor/PostEditor/logic.js index 3d3621177..08c9e3de0 100755 --- a/src/containers/editor/PostEditor/logic.js +++ b/src/containers/editor/PostEditor/logic.js @@ -51,21 +51,9 @@ const getDigest = (body) => { } export const onRadarNoteCLose = () => store.mark({ showRadarNote: false }) -const supportedRadarSource = ['wanqu', 'solidot', 'techcrunch'] -const specCheck = () => { - if (store.activeThread === THREAD.RADAR) { - const domain = parseDomain(store.editPost.linkAddr) - if (!contains(domain, supportedRadarSource)) { - store.mark({ showRadarNote: true }) - return false - } - } - return true -} export const onPublish = () => { if (!store.validator('general')) return false - if (!specCheck()) return false const { body } = store.editData const { isEdit } = store diff --git a/src/containers/thread/PostsThread/CityCard.js b/src/containers/thread/PostsThread/CityCard.js deleted file mode 100755 index 94ff971b1..000000000 --- a/src/containers/thread/PostsThread/CityCard.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react' - -import TrendLine from '@/components/TrendLine' -import { CommunityHolder } from '@/components/LoadingEffects' - -import { prettyNum } from '@/utils' -import { - Wrapper, - CommunityIcon, - CardTitle, - CardDesc, - ActivitySpark, - Divider, - CardFooter, -} from './styles/city_card' - -import { onCommunitySelect } from './logic' - -const CityCard = ({ community }) => { - return ( - onCommunitySelect(community)}> - } - /> - {community.title} - {community.desc} - - - - - - <> - {/* TODO: number color should be different when number grow large */} - {prettyNum(community.subscribersCount)}{' '} - {community.subscribersCount < 1000 ? '人关注' : '关注'} - - - - ) -} - -export default React.memo(CityCard) diff --git a/src/containers/thread/PostsThread/CityList.js b/src/containers/thread/PostsThread/CityList.js deleted file mode 100755 index 95c02ce53..000000000 --- a/src/containers/thread/PostsThread/CityList.js +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' -import { isEmpty } from 'ramda' - -import CityCard from './CityCard' -import CitySideNote from './CitySideNote' - -import { - Wrapper, - ListWrapper, - LoadingWrapper, - LoadingIcon, - LoadingText, - Sidebar, -} from './styles/city_list' - -const Loading = () => ( - - - 正在拉取同城社区,请稍等。 - -) - -const Lists = ({ items }) => ( - <> - {items.map((community) => ( - - ))} - -) - -const CityList = ({ items }) => ( - - - {isEmpty(items) ? : } - - - - - -) - -export default React.memo(CityList) diff --git a/src/containers/thread/PostsThread/CitySideNote.js b/src/containers/thread/PostsThread/CitySideNote.js deleted file mode 100755 index b277dc46a..000000000 --- a/src/containers/thread/PostsThread/CitySideNote.js +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react' - -import { ISSUE_ADDR } from '@/config' -import { Wrapper, Title, Divider, Desc, Linker } from './styles/city_side_note' - -const CitySideNote = () => ( - - 没有你所在的城市? - - - 你可以在 Github 上 - - 参与创建 - - 你的城市。 - -
- 意见与反馈 - - - 你的意见非常重要,欢迎参与 - - 社区讨论 - - 。 - -
-) - -export default React.memo(CitySideNote) diff --git a/src/containers/thread/PostsThread/index.tsx b/src/containers/thread/PostsThread/index.tsx index 2545d9aca..cba4425a0 100755 --- a/src/containers/thread/PostsThread/index.tsx +++ b/src/containers/thread/PostsThread/index.tsx @@ -24,8 +24,6 @@ import ContentFilter from '@/components/ContentFilter' import ConstructingThread from '@/components/ConstructingThread' import PromotionList from '@/components/PromotionList' -import CityList from './CityList' - import type { TStore } from './store' import { @@ -54,32 +52,6 @@ import { /* eslint-disable-next-line */ const log = buildLog('C:PostsThread') -const LabelText = { - radar: '采集信息', - share: '我要分享', - city: '发布同城帖', -} - -const isSpecThread = (community, thread) => { - if (contains(thread, [THREAD.GROUP, THREAD.COMPANY])) { - return true - } - - if (community === ROUTE.HOME && thread === THREAD.CITY) { - return true - } - - return false -} - -const SpecThread = ({ community, thread, cityCommunities }) => { - if (community === ROUTE.HOME && thread === THREAD.CITY) { - return - } - - return -} - type TProps = { postsThread?: TStore } @@ -99,7 +71,6 @@ const PostsThreadContainer: FC = ({ postsThread: store }) => { activeTagData, curCommunity, curThread, - pagedCityCommunitiesData, showFilterBar, accountInfo: { customization: { bannerLayout }, @@ -112,89 +83,79 @@ const PostsThreadContainer: FC = ({ postsThread: store }) => { return ( - {isSpecThread(curCommunity.raw, curThread) ? ( - + + + + + + + + - ) : ( - <> - - - - - - - - - + + {bannerLayout === C11N.DIGEST && ( + + + { + if (key === 'publish') onContentCreate() + }} + > + 发布帖子 + + + + + + + + - - - {bannerLayout === C11N.DIGEST && ( - - - { - if (key === 'publish') onContentCreate() - }} - > - {LabelText[subPath] || '发布帖子'} - - - - - - - - - - - - )} - + + +
)} ) diff --git a/src/containers/thread/PostsThread/logic.ts b/src/containers/thread/PostsThread/logic.ts index 8d7e92cc7..d0a7c0d93 100755 --- a/src/containers/thread/PostsThread/logic.ts +++ b/src/containers/thread/PostsThread/logic.ts @@ -1,23 +1,14 @@ -import { values, contains, pickBy } from 'ramda' +import { pickBy } from 'ramda' import { useEffect } from 'react' -import { - TYPE, - EVENT, - ERR, - THREAD, - ROUTE, - COMMUNITY_SPEC_THREADS, -} from '@/constant' - -import type { TCommunity, TTag } from '@/spec' +import type { TTag } from '@/spec' +import { TYPE, EVENT, ERR, THREAD } from '@/constant' import { asyncSuit, buildLog, send, notEmpty, - thread2Subpath, errRescue, scrollToTabber, } from '@/utils' @@ -41,14 +32,14 @@ const sr71$ = new SR71({ ], }) -let store = null +let store: TStore | undefined let sub$ = null -export const inAnchor = () => { +export const inAnchor = (): void => { if (store) store.showTopModeline(false) } -export const outAnchor = () => { +export const outAnchor = (): void => { if (store) store.showTopModeline(true) } @@ -117,6 +108,7 @@ export const onContentCreate = (): void => { send(EVENT.DRAWER.OPEN, { type: TYPE.DRAWER.POST_CREATE }) } +// TODO: move to rootStore export const onAdsClose = (): void => { log('onAdsClose') if (store.isMemberOf('seniorMember') || store.isMemberOf('sponsorMember')) { @@ -124,26 +116,6 @@ export const onAdsClose = (): void => { } } -const loadCityCommunities = () => { - const { curCommunity, curRoute } = store - if (curCommunity.raw === ROUTE.HOME && curRoute.subPath === THREAD.CITY) { - const args = { filter: { page: 1, size: 30, category: 'city' } } - - sr71$.query(S.pagedCommunities, args) - } -} - -export const onCommunitySelect = (community: TCommunity): void => { - store.setViewing({ community, activeThread: THREAD.POST, post: {} }) - - store.markRoute({ - mainPath: community.raw, - subPath: thread2Subpath(THREAD.POST), - }) - - send(EVENT.COMMUNITY_CHANGE) -} - // toggle FAQ active state export const onFaqChange = (): void => { const { faqActive } = store @@ -186,19 +158,8 @@ const DataSolver = [ action: (res) => { const { data } = res[EVENT.THREAD_CHANGE] - if (contains(data.activeThread, [THREAD.GROUP, THREAD.COMPANY])) { - return false - } - - const { curCommunity, curRoute } = store - if (curCommunity.raw === ROUTE.HOME && curRoute.subPath === THREAD.CITY) { - return loadCityCommunities() - } - - if (!contains(data.activeThread, values(COMMUNITY_SPEC_THREADS))) { - store.mark({ activeTag: null }) - loadPosts() - } + store.mark({ activeTag: null }) + loadPosts() }, }, { @@ -249,11 +210,6 @@ export const useInit = (_store: TStore): void => useEffect(() => { store = _store sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - /* - NOTE: city communities list is not supported by SSR - need load manully - */ - loadCityCommunities() return () => { if (store.curView === TYPE.LOADING || !sub$) return diff --git a/src/containers/thread/PostsThread/store.ts b/src/containers/thread/PostsThread/store.ts index b95148d36..ca7ad90d8 100755 --- a/src/containers/thread/PostsThread/store.ts +++ b/src/containers/thread/PostsThread/store.ts @@ -18,13 +18,7 @@ import type { TThread, } from '@/spec' -import { - PagedPosts, - Tag, - ContentFilter, - emptyPagiData, - PagedCommunities, -} from '@/model' +import { PagedPosts, Tag, ContentFilter, emptyPagiData } from '@/model' /* eslint-disable-next-line */ const log = buildLog('S:PostsThreadStore') @@ -42,7 +36,6 @@ const PostsThreadStore = T.model('PostsThreadStore', { ]), TYPE.RESULT, ), - pagedCityCommunities: T.optional(PagedCommunities, emptyPagiData), faqActive: T.optional(T.boolean, false), }) .views((self) => ({ @@ -84,9 +77,6 @@ const PostsThreadStore = T.model('PostsThreadStore', { const root = getParent(self) as TRootStore return stripMobx(root.viewing.post) }, - get pagedCityCommunitiesData() { - return stripMobx(self.pagedCityCommunities) - }, get pageDensity(): number { const root = getParent(self) as TRootStore return root.account.pageDensity diff --git a/src/containers/thread/PostsThread/styles/city_card.ts b/src/containers/thread/PostsThread/styles/city_card.ts deleted file mode 100755 index 63087ae1e..000000000 --- a/src/containers/thread/PostsThread/styles/city_card.ts +++ /dev/null @@ -1,80 +0,0 @@ -import styled from 'styled-components' - -import Img from '@/Img' -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn('align-center')}; - - position: relative; - padding-top: 12px; - padding: 10px; - padding-bottom: 0; - width: 210px; - height: 220px; - margin-right: 20px; - background: ${theme('content.cardBg')}; - border: 1px solid; - border-color: ${theme('content.cardBorder')}; - border-radius: 3px; - margin-bottom: 50px; - - &:hover { - border: 1px solid; - border-color: ${theme('content.cardBorderHover')}; - cursor: pointer; - } - ${css.media.mobile` - width: 140px; - height: 200px; - margin-right: 8px; - `}; -` - -export const CommunityIcon = styled(Img)<{ nonFill: boolean }>` - ${css.size(54)}; - fill: ${({ nonFill }) => (nonFill ? '' : theme('banner.desc'))}; - margin-bottom: 8px; - margin-top: -35px; - ${Wrapper}:hover & { - fill: ${({ nonFill }) => (nonFill ? '' : theme('banner.title'))}; - } -` - -export const CardTitle = styled.div` - font-size: 1.2em; - font-weight: bold; - margin-top: 5px; - text-align: center; - color: ${theme('thread.articleTitle')}; - - ${Wrapper}:hover & { - color: ${theme('banner.title')}; - } -` -export const CardDesc = styled.div` - font-size: 1em; - text-align: center; - min-height: 50px; - color: ${theme('banner.desc')}; -` -export const ActivitySpark = styled.div` - width: 60%; -` - -export const CardFooter = styled.div` - ${css.flex('justify-around')}; - - width: 100%; - position: absolute; - bottom: 16px; - color: ${theme('banner.desc')}; -` - -export const Divider = styled.div` - width: 90%; - margin-top: 12px; - border-top: 1px solid; - border-top-color: ${theme('content.cardBorder')}; - margin-bottom: 5px; -` diff --git a/src/containers/thread/PostsThread/styles/city_list.ts b/src/containers/thread/PostsThread/styles/city_list.ts deleted file mode 100755 index 77b1491dd..000000000 --- a/src/containers/thread/PostsThread/styles/city_list.ts +++ /dev/null @@ -1,37 +0,0 @@ -import styled from 'styled-components' - -import TabCitySVG from '@/SvgIcons/TabCitySVG' -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - display: flex; - width: 100%; - padding-top: 30px; -` -export const ListWrapper = styled.div` - width: 85%; - display: flex; - flex-wrap: wrap; - margin-top: 10px; - ${css.media.tablet`width: 100%`}; -` -export const LoadingWrapper = styled.div` - ${css.flexColumn('align-both')}; - margin-top: 15%; - height: 100%; - width: 100%; -` -export const LoadingIcon = styled(TabCitySVG)` - fill: ${theme('thread.articleDigest')}; - margin-top: -20%; - width: 200px; - height: 200px; - display: block; -` -export const LoadingText = styled.div` - color: ${theme('thread.articleDigest')}; -` -export const Sidebar = styled.div` - width: 15%; - ${css.media.tablet`display: none`}; -` diff --git a/src/containers/thread/PostsThread/styles/city_side_note.ts b/src/containers/thread/PostsThread/styles/city_side_note.ts deleted file mode 100755 index 79c280f5f..000000000 --- a/src/containers/thread/PostsThread/styles/city_side_note.ts +++ /dev/null @@ -1,33 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn()}; -` -export const Title = styled.div` - font-size: 0.9rem; - color: ${theme('thread.articleTitle')}; -` -export const Divider = styled.div` - border-bottom: 1px solid; - border-color: ${theme('thread.articleTitle')}; - margin-top: 6px; - margin-bottom: 10px; - opacity: 0.4; -` -export const Desc = styled.div` - font-size: 0.8rem; - color: ${theme('thread.articleDigest')}; -` - -export const Linker = styled.a` - color: ${theme('thread.articleDigest')}; - text-decoration: underline; - margin-left: 3px; - &:hover { - text-decoration: underline; - color: ${theme('banner.title')}; - } -` diff --git a/src/containers/unit/TagsBar/logic.ts b/src/containers/unit/TagsBar/logic.ts index 68e2aca5f..c819754ff 100755 --- a/src/containers/unit/TagsBar/logic.ts +++ b/src/containers/unit/TagsBar/logic.ts @@ -22,7 +22,7 @@ let store: TStore | undefined export const onTagSelect = (tag: TTag): void => store.selectTag(tag) -const NO_TAG_THREADS = [THREAD.USER, THREAD.CHEATSHEET, THREAD.WIKI] +const NO_TAG_THREADS = [THREAD.USER] export const loadTags = (): void => { const { curThread } = store diff --git a/utils/constant/index.ts b/utils/constant/index.ts index e60251ef3..816c5a118 100755 --- a/utils/constant/index.ts +++ b/utils/constant/index.ts @@ -5,7 +5,7 @@ export { default as TYPE } from './type' export { default as EVENT } from './event' export { default as ERR } from './err' export { default as ROUTE } from './route' -export { THREAD, COMMUNITY_SPEC_THREADS } from './thread' +export { THREAD } from './thread' export { default as USER_THREAD } from './user_thread' export { default as FILTER } from './filter' export { default as ACTION } from './action' diff --git a/utils/constant/route.ts b/utils/constant/route.ts index 000d8fe02..0c9e043c3 100755 --- a/utils/constant/route.ts +++ b/utils/constant/route.ts @@ -11,9 +11,6 @@ const ROUTE = { USERS: 'users', REPOS: 'repos', WIKI: 'wiki', - SHARE: 'share', - CITY: 'city', - RADAR: 'radar', CHEATSHEET: 'cheatsheet', POST: 'post', diff --git a/utils/constant/thread.ts b/utils/constant/thread.ts index e5022e28b..eec094b48 100755 --- a/utils/constant/thread.ts +++ b/utils/constant/thread.ts @@ -1,21 +1,10 @@ -export const COMMUNITY_SPEC_THREADS = { +export const THREAD = { USER: 'user', - JOB: 'job', REPO: 'repo', - WIKI: 'wiki', - CHEATSHEET: 'cheatsheet', -} - -export const THREAD = { - ...COMMUNITY_SPEC_THREADS, POST: 'post', BLOG: 'blog', - // home spec - TECH: 'tech', - SHARE: 'share', + JOB: 'job', RADAR: 'radar', - CITY: 'city', - // city spec - GROUP: 'group', - COMPANY: 'company', } + +export const holder = 1 From c66256bc9719981a67b4e24df4fe98e5f8662865 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 29 Jun 2021 17:26:01 +0800 Subject: [PATCH 6/7] chore(clean up): remove cheatsheet thread --- src/components/Switcher/Tabs/LocalIcon.tsx | 6 - .../content/CommunityContent/index.tsx | 4 - .../thread/CheatsheetThread/Cheatsheet.js | 73 -- .../thread/CheatsheetThread/Note.js | 57 -- .../thread/CheatsheetThread/fakeusers.js | 28 - .../thread/CheatsheetThread/index.js | 83 -- .../thread/CheatsheetThread/logic.js | 138 ---- .../thread/CheatsheetThread/parser.js | 18 - .../thread/CheatsheetThread/schema.ts | 42 - .../thread/CheatsheetThread/store.js | 79 -- .../styles/CheatsheetMarkStyles.ts | 736 ------------------ .../CheatsheetThread/styles/cheatsheet.ts | 47 -- .../thread/CheatsheetThread/styles/index.ts | 25 - .../thread/CheatsheetThread/styles/note.ts | 40 - .../CheatsheetThread/tests/index.test.ts | 10 - .../CheatsheetThread/tests/store.test.ts | 10 - .../tool/Doraemon/logic/defaultSuggestion.js | 25 +- src/containers/tool/Doraemon/logic/index.js | 14 - src/schemas/pages/cheatsheet.ts | 22 - src/schemas/pages/index.ts | 3 - src/services/github_api/cheatsheet_search.js | 13 - src/services/github_api/index.js | 2 - src/stores/RootStore/index.ts | 2 - src/stores/SharedModel/Cheatsheet.ts | 12 - src/stores/SharedModel/index.ts | 1 - src/stores/index.ts | 1 - utils/constant/route.ts | 2 - utils/i18n/index.js | 1 - utils/ssr.js | 16 - 29 files changed, 1 insertion(+), 1509 deletions(-) delete mode 100755 src/containers/thread/CheatsheetThread/Cheatsheet.js delete mode 100755 src/containers/thread/CheatsheetThread/Note.js delete mode 100755 src/containers/thread/CheatsheetThread/fakeusers.js delete mode 100755 src/containers/thread/CheatsheetThread/index.js delete mode 100755 src/containers/thread/CheatsheetThread/logic.js delete mode 100755 src/containers/thread/CheatsheetThread/parser.js delete mode 100755 src/containers/thread/CheatsheetThread/schema.ts delete mode 100755 src/containers/thread/CheatsheetThread/store.js delete mode 100755 src/containers/thread/CheatsheetThread/styles/CheatsheetMarkStyles.ts delete mode 100755 src/containers/thread/CheatsheetThread/styles/cheatsheet.ts delete mode 100755 src/containers/thread/CheatsheetThread/styles/index.ts delete mode 100755 src/containers/thread/CheatsheetThread/styles/note.ts delete mode 100755 src/containers/thread/CheatsheetThread/tests/index.test.ts delete mode 100755 src/containers/thread/CheatsheetThread/tests/store.test.ts delete mode 100755 src/schemas/pages/cheatsheet.ts delete mode 100755 src/services/github_api/cheatsheet_search.js delete mode 100755 src/stores/SharedModel/Cheatsheet.ts diff --git a/src/components/Switcher/Tabs/LocalIcon.tsx b/src/components/Switcher/Tabs/LocalIcon.tsx index aa431a79f..04f169def 100644 --- a/src/components/Switcher/Tabs/LocalIcon.tsx +++ b/src/components/Switcher/Tabs/LocalIcon.tsx @@ -5,7 +5,6 @@ import { TabUserIcon, TabJobIcon, TabRepoIcon, - TabCheatsheetIcon, // user TabLikesIcon, TabPublishIcon, @@ -43,11 +42,6 @@ const TabIcon: FC = ({ raw, active, small }) => { return } - case 'cheatsheet': { - /* @ts-ignore */ - return - } - case 'favorites': { /* @ts-ignore */ return diff --git a/src/containers/content/CommunityContent/index.tsx b/src/containers/content/CommunityContent/index.tsx index 32befd0da..18d3d378b 100755 --- a/src/containers/content/CommunityContent/index.tsx +++ b/src/containers/content/CommunityContent/index.tsx @@ -16,7 +16,6 @@ import ReposThread from '@/containers/thread/ReposThread' import WikiThread from '@/containers/thread/WikiThread' import JobsThread from '@/containers/thread/JobsThread' import UsersThread from '@/containers/thread/UsersThread' -import CheatsheetThread from '@/containers/thread/CheatsheetThread' import type { TStore } from './store' import { Wrapper, InnerWrapper } from './styles' @@ -43,9 +42,6 @@ const ComunityContent = ({ curRoute }) => { case ROUTE.WIKI: return - case ROUTE.CHEATSHEET: - return - default: return } diff --git a/src/containers/thread/CheatsheetThread/Cheatsheet.js b/src/containers/thread/CheatsheetThread/Cheatsheet.js deleted file mode 100755 index ec1701c98..000000000 --- a/src/containers/thread/CheatsheetThread/Cheatsheet.js +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react' -import Masonry from 'react-masonry-component' -import { Remarkable } from 'remarkable' -// import Prism from 'mastani-codehighlight' - -import { COMMUNITY_CHEATSHEET } from '@/config' -import { uid } from '@/utils' - -import { - Wrapper, - CardWrapper, - ErrorWrapper, - ErrorTitle, - ErrorLink, -} from './styles/cheatsheet' -import parser from './parser' -import CheatSheetStyle from './styles/CheatsheetMarkStyles' - -const md = new Remarkable() - -const Cards = ({ cards }) => - cards.map((item) => ( - - -
- - - )) - -const Cheatsheet = ({ source, communityRaw }) => { - let data = null - try { - data = parser(source) - return ( - - {data.map((item) => ( - -
- - - - - ))} - - ) - } catch (e) { - return ( - - 解析错误 - - 查看: {`${communityRaw}.md`} - - - ) - } -} - -export default Cheatsheet diff --git a/src/containers/thread/CheatsheetThread/Note.js b/src/containers/thread/CheatsheetThread/Note.js deleted file mode 100755 index 2063d20d7..000000000 --- a/src/containers/thread/CheatsheetThread/Note.js +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react' - -import { COMMUNITY_CHEATSHEET } from '@/config' - -import { Button } from '@/components/Buttons' -import DotDivider from '@/components/DotDivider' -import ContributorList from '@/components/ContributorList' - -import { - Wrapper, - Divider, - Text, - Title, - JoinText, - ViewsText, - SyncWrapper, -} from './styles/note' - -// import fakeusers from './fakeusers' -import { syncCheetsheetFromGithub, addContributor } from './logic' - -const Note = ({ isLogin, communityRaw, contributors, views }) => ( - - - - 本页贡献者 {' '} - - 参与编辑 - - {views && 浏览: {views}} - - - - {isLogin && ( - - )} - - -) - -export default React.memo(Note) diff --git a/src/containers/thread/CheatsheetThread/fakeusers.js b/src/containers/thread/CheatsheetThread/fakeusers.js deleted file mode 100755 index 49bc9e8a6..000000000 --- a/src/containers/thread/CheatsheetThread/fakeusers.js +++ /dev/null @@ -1,28 +0,0 @@ -const fakeusers = [ - { - avatar: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - nickname: 'nickname', - bio: 'bio', - company: 'company', - location: 'location', - htmlUrl: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - }, - { - avatar: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - nickname: 'nickname', - bio: 'bio', - company: 'company', - location: 'location', - htmlUrl: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - }, - { - avatar: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - nickname: 'nickname', - bio: 'bio', - company: 'company', - location: 'location', - htmlUrl: 'https://avatars2.githubusercontent.com/u/6184465?v=4', - }, -] - -export default fakeusers diff --git a/src/containers/thread/CheatsheetThread/index.js b/src/containers/thread/CheatsheetThread/index.js deleted file mode 100755 index dcd5ac267..000000000 --- a/src/containers/thread/CheatsheetThread/index.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * CheatsheetThread - * - */ - -import React from 'react' - -import { TYPE } from '@/constant' -import { pluggedIn, buildLog } from '@/utils' - -import EmptyThread from '@/components/EmptyThread' -import { CheatSheetLoading } from '@/components/LoadingEffects' -import GithubSyncWarning from '@/components/GithubSyncWarning' - -import Cheatsheet from './Cheatsheet' -import Note from './Note' - -import { Wrapper, EmptyOffset } from './styles' -import { useInit, syncWarnOnClose } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:CheatsheetThread') - -const renderView = (cheatsheetData, type, communityRaw) => { - switch (type) { - case TYPE.LOADING: { - return - } - case TYPE.RESULT_EMPTY: { - return ( - - - - ) - } - case TYPE.NOT_FOUND: { - return ( - - - - ) - } - default: { - return ( - - ) - } - } -} - -const CheatsheetThreadContainer = ({ cheatsheetThread: store }) => { - useInit(store) - - const { - cheatsheetData, - curView, - curCommunity, - showSyncWarning, - isLogin, - } = store - - const communityRaw = curCommunity.raw - - return ( - - - {renderView(cheatsheetData, curView, communityRaw)} - - - ) -} - -export default pluggedIn(CheatsheetThreadContainer) diff --git a/src/containers/thread/CheatsheetThread/logic.js b/src/containers/thread/CheatsheetThread/logic.js deleted file mode 100755 index 732717ae2..000000000 --- a/src/containers/thread/CheatsheetThread/logic.js +++ /dev/null @@ -1,138 +0,0 @@ -import { useEffect } from 'react' -import Prism from 'mastani-codehighlight' -import { startsWith, isEmpty } from 'ramda' - -import { TYPE, EVENT, ERR, THREAD } from '@/constant' -import { asyncSuit, buildLog, errRescue, BStore, nilOrEmpty } from '@/utils' - -import { githubAPI } from '@/services' -import S from './schema' - -/* eslint-disable-next-line */ -const log = buildLog('L:CheatsheetThread') - -const { SR71, $solver, asyncRes, asyncErr } = asyncSuit -const sr71$ = new SR71({ - receive: [EVENT.COMMUNITY_CHANGE, EVENT.THREAD_CHANGE], -}) - -let sub$ = null -let store = null - -const loadCheatsheet = () => { - const community = store.curCommunity.raw - // const community = 'no-exist' - /* const community = 'elixir' */ - - store.mark({ curView: TYPE.LOADING }) - sr71$.query(S.cheatsheet, { community }) -} - -export const syncCheatsheet = (readme) => { - const args = { - readme, - lastSync: new Date().toISOString(), - communityId: store.curCommunity.id, - } - - sr71$.mutate(S.syncCheatsheet, args) -} - -export const syncWarnOnClose = () => store.mark({ showSyncWarning: false }) - -export const syncCheetsheetFromGithub = () => { - if (nilOrEmpty(BStore.get('github_token'))) { - return store.mark({ showSyncWarning: true }) - } - - githubAPI - .searchCheatsheet(store.curCommunity.raw) - .then((res) => { - if (!res || startsWith('404', res)) { - return store.mark({ curView: TYPE.NOT_FOUND }) - } - - syncCheatsheet(res) - }) - .catch((e) => store.handleError(githubAPI.parseError(e))) -} - -export const addContributor = (user) => { - const args = { - id: store.cheatsheetData.id, - contributor: user, - } - sr71$.mutate(S.addCheatsheetContributor, args) -} - -// ############################### -// Data & Error handlers -// ############################### - -const DataSolver = [ - { - match: asyncRes('cheatsheet'), - action: ({ cheatsheet }) => { - const curView = isEmpty(cheatsheet.readme) - ? TYPE.RESULT_EMPTY - : TYPE.RESULT - store.mark({ cheatsheet, curView }) - }, - }, - { - match: asyncRes('syncCheatsheet'), - action: () => loadCheatsheet(), - }, - { - match: asyncRes('addCheatsheetContributor'), - action: () => loadCheatsheet(), - }, - { - match: asyncRes(EVENT.COMMUNITY_CHANGE), - action: () => loadCheatsheet(), - }, - { - match: asyncRes(EVENT.THREAD_CHANGE), - action: (res) => { - const { data } = res[EVENT.THREAD_CHANGE] - const { activeThread } = data - if (activeThread === THREAD.CHEATSHEET) return loadCheatsheet() - }, - }, -] -const ErrSolver = [ - { - match: asyncErr(ERR.GRAPHQL), - action: () => store.mark({ curView: TYPE.NOT_FOUND }), - }, - { - match: asyncErr(ERR.TIMEOUT), - action: ({ details }) => - errRescue({ type: ERR.TIMEOUT, details, path: 'CheatsheetThread' }), - }, - { - match: asyncErr(ERR.NETWORK), - action: () => errRescue({ type: ERR.NETWORK, path: 'CheatsheetThread' }), - }, -] - -// ############################### -// init & uninit -// ############################### -export const useInit = (_store) => { - useEffect(() => { - store = _store - sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - Prism.highlightAll() - setTimeout(() => { - Prism.highlightAll() - }, 1000) - - return () => { - if (store.curView === TYPE.LOADING || !sub$) return false - log('===== do uninit') - sr71$.stop() - sub$.unsubscribe() - } - }, [_store]) -} diff --git a/src/containers/thread/CheatsheetThread/parser.js b/src/containers/thread/CheatsheetThread/parser.js deleted file mode 100755 index 78f09955a..000000000 --- a/src/containers/thread/CheatsheetThread/parser.js +++ /dev/null @@ -1,18 +0,0 @@ -import { compose, head, trim, split, map, nth } from 'ramda' - -const groupSpliter = '{{ ::group:: }}' -const cardsHeaderSpliter = '{{ ::cards-header:: }}' -const cardItemSpliter = '{{ ::card-item:: }}' - -const getCardHeader = compose(trim, head, split(cardsHeaderSpliter)) -const getCardList = compose(trim, nth(1), split(cardsHeaderSpliter)) - -const getCardItems = compose(map(trim), split(cardItemSpliter), getCardList) -const formatFromer = (v) => ({ - header: getCardHeader(v), - cards: getCardItems(v), -}) - -const parser = compose(map(formatFromer), split(groupSpliter), trim) - -export default parser diff --git a/src/containers/thread/CheatsheetThread/schema.ts b/src/containers/thread/CheatsheetThread/schema.ts deleted file mode 100755 index 4c25b0637..000000000 --- a/src/containers/thread/CheatsheetThread/schema.ts +++ /dev/null @@ -1,42 +0,0 @@ -import gql from 'graphql-tag' -import { P } from '@/schemas' - -const cheatsheet = gql` - ${P.cheatsheet} -` -const syncCheatsheet = gql` - mutation($communityId: ID!, $readme: String!, $lastSync: String!) { - syncCheatsheet( - communityId: $communityId - readme: $readme - lastSync: $lastSync - ) { - id - readme - } - } -` -const addCheatsheetContributor = gql` - mutation($id: ID!, $contributor: GithubContributorInput!) { - addCheatsheetContributor(id: $id, contributor: $contributor) { - id - readme - contributors { - nickname - avatar - bio - company - location - htmlUrl - } - } - } -` - -const schema = { - cheatsheet, - syncCheatsheet, - addCheatsheetContributor, -} - -export default schema diff --git a/src/containers/thread/CheatsheetThread/store.js b/src/containers/thread/CheatsheetThread/store.js deleted file mode 100755 index 6582c57f7..000000000 --- a/src/containers/thread/CheatsheetThread/store.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * CheatsheetThread store - * - */ - -import { types as T, getParent } from 'mobx-state-tree' - -import { TYPE, ERR } from '@/constant' -import { markStates, buildLog, stripMobx } from '@/utils' -import { Cheatsheet } from '@/model' - -/* eslint-disable-next-line */ -const log = buildLog('S:CheatsheetThread') - -const CheatsheetThread = T.model('CheatsheetThread', { - cheatsheet: T.optional(Cheatsheet, { readme: '' }), - current: T.optional(T.string, ''), - curView: T.optional( - T.enumeration('curView', [ - TYPE.RESULT, - TYPE.LOADING, - TYPE.NOT_FOUND, - TYPE.RESULT_EMPTY, - ]), - TYPE.RESULT, - ), - errorType: T.maybeNull(T.string), - showSyncWarning: T.optional(T.boolean, false), -}) - .views((self) => ({ - get root() { - return getParent(self) - }, - get isLogin() { - return self.root.account.isLogin - }, - get curCommunity() { - return stripMobx(self.root.viewing.community) - }, - get cheatsheetData() { - return stripMobx(self.cheatsheet) - }, - })) - .actions((self) => ({ - changesetErr(options) { - self.root.changesetErr(options) - }, - handleError(errorType) { - log(errorType) - self.mark({ errorType, searching: false }) - switch (errorType) { - case ERR.NOT_FOUND: - return self.changesetErr({ - title: 'Cheatsheet 未找到', - msg: '请确认输入的仓库地址', - }) - - case ERR.AUTH: - return self.changesetErr({ - title: 'Github 鉴权出错', - msg: 'token 可能过期,请尝试重新登录', - }) - - case ERR.TIMEOUT: - return self.changesetErr({ - title: 'Github 超时', - msg: '特殊国情,请稍后重试', - }) - - default: - return self.changesetErr({ title: '未知错误', msg: '...' }) - } - }, - mark(sobj) { - markStates(sobj, self) - }, - })) - -export default CheatsheetThread diff --git a/src/containers/thread/CheatsheetThread/styles/CheatsheetMarkStyles.ts b/src/containers/thread/CheatsheetThread/styles/CheatsheetMarkStyles.ts deleted file mode 100755 index e5787561c..000000000 --- a/src/containers/thread/CheatsheetThread/styles/CheatsheetMarkStyles.ts +++ /dev/null @@ -1,736 +0,0 @@ -import styled from 'styled-components' -import { theme } from '@/utils' - -const CheatSheetStyles = styled.div` - margin-bottom: 15px; - @font-face { - font-family: octicons-link; - src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8ihnyxnwaaagtaaaabaaaaaqaboai2dsewyaaafsaaabpaaaazwceq9tagvhzaaaasgaaaa0aaaangh4a91oagvhaaadcaaaaboaaaakca8drghtdhgaaal8aaaadaaaaawgaacfbg9jyqaaasaaaaaiaaaacabiatbtyxhwaaacqaaaabgaaaagaa8asm5hbwuaaatoaaabqgaaalxu73socg9zdaaabiwaaaaeaaaame3qpobwcmvwaaaebaaaahyaaab/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vwy/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7vm1ozezueleaujhadsuxhwvrgvljn1tq7xiuvv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9jos0nbaaydcqfwcj7au3ahj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aued4nd3chd8ndvoltsa2gl8m9podbcl+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9jyda6sl1duyhscm1dyclfoedve4qmydlebfqhf3o/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==); - } - - .cheatsheet-body { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - line-height: 1.5; - color: ${theme('markdown.fg')}; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, - sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - font-size: 16px; - line-height: 1.5; - word-wrap: break-word; - } - - .cheatsheet-body .pl-c { - color: #6a737d; - } - - .cheatsheet-body .pl-c1, - .cheatsheet-body .pl-s .pl-v { - color: #005cc5; - } - - .cheatsheet-body .pl-e, - .cheatsheet-body .pl-en { - color: #6f42c1; - } - - .cheatsheet-body .pl-smi, - .cheatsheet-body .pl-s .pl-s1 { - color: #24292e; - } - - .cheatsheet-body .pl-ent { - color: #22863a; - } - - .cheatsheet-body .pl-k { - color: #d73a49; - } - - .cheatsheet-body .pl-s, - .cheatsheet-body .pl-pds, - .cheatsheet-body .pl-s .pl-pse .pl-s1, - .cheatsheet-body .pl-sr, - .cheatsheet-body .pl-sr .pl-cce, - .cheatsheet-body .pl-sr .pl-sre, - .cheatsheet-body .pl-sr .pl-sra { - color: #032f62; - } - - .cheatsheet-body .pl-v, - .cheatsheet-body .pl-smw { - color: #e36209; - } - - .cheatsheet-body .pl-bu { - color: #b31d28; - } - - .cheatsheet-body .pl-ii { - color: #fafbfc; - background-color: #b31d28; - } - - .cheatsheet-body .pl-c2 { - color: #fafbfc; - background-color: #d73a49; - } - - .cheatsheet-body .pl-c2::before { - content: '^M'; - } - - .cheatsheet-body .pl-sr .pl-cce { - font-weight: bold; - color: #22863a; - } - - .cheatsheet-body .pl-ml { - color: #735c0f; - } - - .cheatsheet-body .pl-mh, - .cheatsheet-body .pl-mh .pl-en, - .cheatsheet-body .pl-ms { - font-weight: bold; - color: #005cc5; - } - - .cheatsheet-body .pl-mi { - font-style: italic; - color: #24292e; - } - - .cheatsheet-body .pl-mb { - font-weight: bold; - color: #24292e; - } - - .cheatsheet-body .pl-md { - color: #b31d28; - background-color: #ffeef0; - } - - .cheatsheet-body .pl-mi1 { - color: #22863a; - background-color: #f0fff4; - } - - .cheatsheet-body .pl-mc { - color: #e36209; - background-color: #ffebda; - } - - .cheatsheet-body .pl-mi2 { - color: #f6f8fa; - background-color: #005cc5; - } - - .cheatsheet-body .pl-mdr { - font-weight: bold; - color: #6f42c1; - } - - .cheatsheet-body .pl-ba { - color: #586069; - } - - .cheatsheet-body .pl-sg { - color: #959da5; - } - - .cheatsheet-body .pl-corl { - text-decoration: underline; - color: #032f62; - } - - .cheatsheet-body .octicon { - display: inline-block; - vertical-align: text-top; - fill: currentColor; - } - - .cheatsheet-body a { - background-color: transparent; - -webkit-text-decoration-skip: objects; - } - - .cheatsheet-body a:active, - .cheatsheet-body a:hover { - outline-width: 0; - } - - .cheatsheet-body strong { - font-weight: inherit; - } - - .cheatsheet-body strong { - font-weight: normal !important; - color: ${theme('markdown.strongFg')}; - background-color: ${theme('markdown.strongBg')}; - } - - .cheatsheet-body h1 { - font-size: 2em; - margin: 0.67em 0; - } - - .cheatsheet-body img { - border-style: none; - } - - .cheatsheet-body svg:not(:root) { - overflow: hidden; - } - - .cheatsheet-body code, - .cheatsheet-body kbd, - .cheatsheet-body pre { - font-family: monospace, monospace; - font-size: 1em; - } - - .cheatsheet-body hr { - box-sizing: content-box; - height: 0; - overflow: visible; - } - - .cheatsheet-body * { - box-sizing: border-box; - } - - .cheatsheet-body a { - color: ${theme('markdown.link')}; - text-decoration: none; - } - - .cheatsheet-body a:hover { - text-decoration: underline; - } - - .cheatsheet-body strong { - font-weight: 600; - } - - .cheatsheet-body hr { - height: 0; - margin: 15px 0; - overflow: hidden; - background: transparent; - border: 0; - border-bottom: 1px solid #dfe2e5; - } - - .cheatsheet-body hr::before { - display: table; - content: ''; - } - - .cheatsheet-body hr::after { - display: table; - clear: both; - content: ''; - } - - .cheatsheet-body table { - border-spacing: 0; - border-collapse: collapse; - } - - .cheatsheet-body td, - .cheatsheet-body th { - padding: 0; - } - - .cheatsheet-body h1, - .cheatsheet-body h2, - .cheatsheet-body h3, - .cheatsheet-body h4, - .cheatsheet-body h5, - .cheatsheet-body h6 { - margin-top: 0; - margin-bottom: 0; - color: ${theme('markdown.title')}; - } - - .cheatsheet-body h1 { - font-size: 32px; - font-weight: 600; - } - - .cheatsheet-body h2 { - font-size: 24px; - font-weight: 600; - margin-left: 10px; - } - - .cheatsheet-body h4 { - font-size: 16px; - font-weight: 600; - } - - .cheatsheet-body h5 { - font-size: 14px; - font-weight: 600; - } - - .cheatsheet-body h6 { - font-size: 12px; - font-weight: 600; - } - - .cheatsheet-body p { - margin-top: 0; - margin-bottom: 10px; - padding-left: 1em; - } - - .cheatsheet-body blockquote { - margin: 0; - } - - .cheatsheet-body ul, - .cheatsheet-body ol { - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - } - - .cheatsheet-body ol ol, - .cheatsheet-body ul ol { - list-style-type: lower-roman; - } - - .cheatsheet-body ul ul ol, - .cheatsheet-body ul ol ol, - .cheatsheet-body ol ul ol, - .cheatsheet-body ol ol ol { - list-style-type: lower-alpha; - } - - .cheatsheet-body dd { - margin-left: 0; - } - - .cheatsheet-body code { - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, - monospace; - font-size: 16px; - } - - .cheatsheet-body pre { - margin-top: 0; - margin-bottom: 0; - font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, - monospace; - font-size: 16px; - } - - .cheatsheet-body .octicon { - vertical-align: text-bottom; - } - - .cheatsheet-body .pl-0 { - padding-left: 0 !important; - } - - .cheatsheet-body .pl-1 { - padding-left: 4px !important; - } - - .cheatsheet-body .pl-2 { - padding-left: 8px !important; - } - - .cheatsheet-body .pl-3 { - padding-left: 16px !important; - } - - .cheatsheet-body .pl-4 { - padding-left: 24px !important; - } - - .cheatsheet-body .pl-5 { - padding-left: 32px !important; - } - - .cheatsheet-body .pl-6 { - padding-left: 40px !important; - } - - .cheatsheet-body::before { - display: table; - content: ''; - } - - .cheatsheet-body::after { - display: table; - clear: both; - content: ''; - } - - .cheatsheet-body > *:first-child { - margin-top: 0 !important; - } - - .cheatsheet-body > *:last-child { - margin-bottom: 0 !important; - } - - .cheatsheet-body a:not([href]) { - color: inherit; - text-decoration: none; - } - - .cheatsheet-body .anchor { - float: left; - padding-right: 4px; - margin-left: -20px; - line-height: 1; - } - - .cheatsheet-body .anchor:focus { - outline: none; - } - - .cheatsheet-body p, - .cheatsheet-body blockquote, - .cheatsheet-body ul, - .cheatsheet-body ol, - .cheatsheet-body dl, - .cheatsheet-body table, - .cheatsheet-body pre { - margin-top: 0; - margin-bottom: 16px; - } - - .cheatsheet-body hr { - height: 0.25em; - padding: 0; - margin: 24px 0; - background-color: #e1e4e8; - border: 0; - } - - .cheatsheet-body blockquote { - padding: 0 1em; - color: ${theme('markdown.blockquoteFg')}; - border-left: ${theme('markdown.blockquoteBorder')}; - font-style: italic; - } - - .cheatsheet-body blockquote > :first-child { - margin-top: 0; - } - - .cheatsheet-body blockquote > :last-child { - margin-bottom: 0; - } - - .cheatsheet-body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #444d56; - vertical-align: middle; - background-color: #fafbfc; - border: solid 1px #c6cbd1; - border-bottom-color: #959da5; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #959da5; - } - - .cheatsheet-body h1, - .cheatsheet-body h2, - .cheatsheet-body h3, - .cheatsheet-body h4, - .cheatsheet-body h5, - .cheatsheet-body h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; - } - - .cheatsheet-body h1 .octicon-link, - .cheatsheet-body h2 .octicon-link, - .cheatsheet-body h3 .octicon-link, - .cheatsheet-body h4 .octicon-link, - .cheatsheet-body h5 .octicon-link, - .cheatsheet-body h6 .octicon-link { - color: #1b1f23; - vertical-align: middle; - visibility: hidden; - } - - .cheatsheet-body h1:hover .anchor, - .cheatsheet-body h2:hover .anchor, - .cheatsheet-body h3:hover .anchor, - .cheatsheet-body h4:hover .anchor, - .cheatsheet-body h5:hover .anchor, - .cheatsheet-body h6:hover .anchor { - text-decoration: none; - } - - .cheatsheet-body h1:hover .anchor .octicon-link, - .cheatsheet-body h2:hover .anchor .octicon-link, - .cheatsheet-body h3:hover .anchor .octicon-link, - .cheatsheet-body h4:hover .anchor .octicon-link, - .cheatsheet-body h5:hover .anchor .octicon-link, - .cheatsheet-body h6:hover .anchor .octicon-link { - visibility: visible; - } - - .cheatsheet-body h1 { - padding-bottom: 0.3em; - font-size: 2em; - border-bottom: 1px solid; - border-bottom-color: ${theme('markdown.titleBottom')}; - } - - .cheatsheet-body h2 { - padding-bottom: 0.3em; - font-size: 1.5em; - border-bottom: 1px solid; - border-bottom-color: ${theme('markdown.titleBottom')}; - } - - .cheatsheet-body h3 { - font-size: 1.25em; - font-weight: 600; - background: ${theme('content.bg')}; - margin-top: 0; - margin-bottom: 0; - padding-top: 10px; - padding-bottom: 10px; - padding-left: 0.1em; - color: ${theme('font')}; - } - - .cheatsheet-body h4 { - font-size: 1em; - margin-left: 1em; - color: ${theme('font')}; - } - - .cheatsheet-body h5 { - font-size: 0.875em; - } - - .cheatsheet-body h6 { - font-size: 0.85em; - color: ${theme('markdown.title')}; - } - - .cheatsheet-body ul, - .cheatsheet-body ol { - padding-left: 2em !important; - } - - .cheatsheet-body ol { - display: block; - list-style-type: decimal; - -webkit-margin-before: 1em; - -webkit-margin-after: 1em; - -webkit-margin-start: 0px; - -webkit-margin-end: 0px; - -webkit-padding-start: 40px; - } - - .cheatsheet-body ul { - display: block; - list-style-type: disc; - -webkit-margin-before: 1em; - -webkit-margin-after: 1em; - -webkit-margin-start: 0px; - -webkit-margin-end: 0px; - -webkit-padding-start: 40px; - } - - .cheatsheet-body ul ul, - .cheatsheet-body ul ol, - .cheatsheet-body ol ol, - .cheatsheet-body ol ul { - margin-top: 0; - margin-bottom: 0; - } - - .cheatsheet-body li > p { - margin-top: 16px; - } - - .cheatsheet-body li + li { - margin-top: 0.25em; - } - - .cheatsheet-body dl { - padding: 0; - } - - .cheatsheet-body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 600; - } - - .cheatsheet-body dl dd { - padding: 0 16px; - margin-bottom: 16px; - } - - .cheatsheet-body table { - display: block; - width: 100%; - overflow: auto; - } - - .cheatsheet-body table th { - font-weight: 600; - } - - .cheatsheet-body table th, - .cheatsheet-body table td { - padding: 6px 13px; - border: ${theme('markdown.tableborder')}; - width: 100%; - } - - .cheatsheet-body table tr { - background-color: ${theme('markdown.tableBg')}; - border-top: ${theme('markdown.tableborder')}; - } - - .cheatsheet-body table tr:nth-child(2n) { - background-color: ${theme('markdown.tableBg2n')}; - } - - .cheatsheet-body code { - padding: 0; - padding-top: 0.2em; - padding-bottom: 0.2em; - margin: 0; - font-size: 85%; - background-color: ${theme('code.bg')}; - border-radius: 3px; - } - - .cheatsheet-body code::before, - .cheatsheet-body code::after { - letter-spacing: -0.2em; - content: '\00a0'; - } - - .cheatsheet-body pre { - word-wrap: normal; - } - - .cheatsheet-body pre > code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; - } - - .cheatsheet-body .highlight { - margin-bottom: 16px; - } - - .cheatsheet-body .highlight pre { - margin-bottom: 0; - word-break: normal; - } - - .cheatsheet-body pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: ${theme('code.bg')}; - border-radius: 3px; - } - - .cheatsheet-body pre code { - display: inline; - max-width: auto; - padding: 0; - margin: 0; - overflow: visible; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; - } - - .cheatsheet-body pre code::before, - .cheatsheet-body pre code::after { - content: normal; - } - - .cheatsheet-body .full-commit .btn-outline:not(:disabled):hover { - color: #005cc5; - border-color: #005cc5; - } - - .cheatsheet-body kbd { - display: inline-block; - padding: 3px 5px; - font: 11px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, - monospace; - line-height: 10px; - color: #444d56; - vertical-align: middle; - background-color: #fafbfc; - border: solid 1px #d1d5da; - border-bottom-color: #c6cbd1; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #c6cbd1; - } - - .cheatsheet-body .task-list-item { - list-style-type: none; - } - - .cheatsheet-body .task-list-item + .task-list-item { - margin-top: 3px; - } - - .cheatsheet-body .task-list-item input { - margin: 0 0.2em 0.25em -1.6em; - vertical-align: middle; - } - - .cheatsheet-body hr { - border-bottom-color: ${theme('markdown.hrColor')}; - } - - .cheatsheet-body .task-done { - margin-left: -1.2em; - list-style-type: none; - - &:before { - content: '[o]'; - color: ${theme('markdown.taskDone')}; - margin-right: 0.5em; - } - } - - .cheatsheet-body .task-pending { - margin-left: -1.2em; - list-style-type: none; - - &:before { - content: '[-]'; - color: ${theme('markdown.taskPeding')}; - margin-right: 0.5em; - } - } -` - -export default CheatSheetStyles diff --git a/src/containers/thread/CheatsheetThread/styles/cheatsheet.ts b/src/containers/thread/CheatsheetThread/styles/cheatsheet.ts deleted file mode 100755 index 57e3f0266..000000000 --- a/src/containers/thread/CheatsheetThread/styles/cheatsheet.ts +++ /dev/null @@ -1,47 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn()}; -` -// width: 550px; -export const CardWrapper = styled.div` - width: 450px; - height: auto; - background: ${theme('code.bg')}; - margin: 10px; - margin-right: 20px; - overflow-y: scroll; - - ${css.media.mobile` - width: 95%; - `}; -` -export const ErrorWrapper = styled.div` - ${css.flexColumn()}; - padding: 20px 40px; - border: 1px solid; - border-radius: 5px; - border-top: 3px solid; - border-color: ${theme('baseColor.red')}; - min-height: 100px; - margin-bottom: 30px; - background: ${theme('baseColor.redBg')}; -` -export const ErrorTitle = styled.div` - font-size: 1.2rem; - color: ${theme('baseColor.red')}; - margin-bottom: 20px; -` -export const ErrorLink = styled.a` - transition: color 0.3s; - color: ${theme('baseColor.red')}; - font-size: 1rem; - - &:hover { - cursor: pointer; - color: ${theme('baseColor.red')}; - text-decoration: underline; - } -` diff --git a/src/containers/thread/CheatsheetThread/styles/index.ts b/src/containers/thread/CheatsheetThread/styles/index.ts deleted file mode 100755 index 214cf440c..000000000 --- a/src/containers/thread/CheatsheetThread/styles/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn()}; - width: 100%; - padding: 20px; -` -export const CardWrapper = styled.div` - width: 550px; - height: auto; - background: ${theme('code.bg')}; - margin: 10px; - margin-right: 20px; - overflow-y: scroll; - - ${css.media.mobile` - width: 95%; - `}; -` - -export const EmptyOffset = styled.div` - margin-left: -5%; -` diff --git a/src/containers/thread/CheatsheetThread/styles/note.ts b/src/containers/thread/CheatsheetThread/styles/note.ts deleted file mode 100755 index 8027dc8df..000000000 --- a/src/containers/thread/CheatsheetThread/styles/note.ts +++ /dev/null @@ -1,40 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn()}; -` -export const Divider = styled.div` - width: 100%; - border-top: 1px solid; - border-color: ${theme('thread.articleDigest')}; - opacity: 0.5; - margin-top: 10px; - margin-bottom: 10px; -` - -export const Text = styled.div` - ${css.flex('align-center')}; - font-size: 0.9rem; -` -export const Title = styled.div` - color: ${theme('thread.articleDigest')}; -` -export const JoinText = styled.a` - flex-grow: 1; - color: ${theme('thread.articleDigest')}; - &:hover { - color: ${theme('thread.articleTitle')}; - cursor: pointer; - font-weight: bold; - } -` -export const ViewsText = styled.div` - color: ${theme('thread.articleDigest')}; - margin-right: 2%; - font-size: 0.8rem; -` -export const SyncWrapper = styled.div` - margin-top: 15px; -` diff --git a/src/containers/thread/CheatsheetThread/tests/index.test.ts b/src/containers/thread/CheatsheetThread/tests/index.test.ts deleted file mode 100755 index 6e121c1d0..000000000 --- a/src/containers/thread/CheatsheetThread/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import CheatsheetThread from '../index' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/containers/thread/CheatsheetThread/tests/store.test.ts b/src/containers/thread/CheatsheetThread/tests/store.test.ts deleted file mode 100755 index d32082a14..000000000 --- a/src/containers/thread/CheatsheetThread/tests/store.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * CheatsheetThread store test - * - */ - -// import CheatsheetThread from '../index' - -it('TODO: store test CheatsheetThread', () => { - expect(1 + 1).toBe(2) -}) diff --git a/src/containers/tool/Doraemon/logic/defaultSuggestion.js b/src/containers/tool/Doraemon/logic/defaultSuggestion.js index a2c772222..43c630eed 100755 --- a/src/containers/tool/Doraemon/logic/defaultSuggestion.js +++ b/src/containers/tool/Doraemon/logic/defaultSuggestion.js @@ -2,10 +2,9 @@ those are the default cmd theme -- user -- - cheatsheet -- TODO login -- */ -import { ICON_CMD, ICON_BASE } from '@/config' +import { ICON_CMD } from '@/config' import { themeMeta } from '@/utils' const cmds = { @@ -23,28 +22,6 @@ const cmds = { raw: 'user', logo: `${ICON_CMD}/users.svg`, }, - cheatsheet: { - title: 'cheatsheet', - desc: 'Cheatsheet desc', - raw: 'cheatsheet', - logo: `${ICON_CMD}/cheatsheet.svg`, - threads: { - react: { - title: 'javascript', - desc: 'javascript cheatsheet', - raw: 'javascript', - logo: `${ICON_BASE}/pl/javascript.svg`, - threads: { - react2: { - title: 'javascript2', - desc: 'javascript2 cheatsheet', - raw: 'javascript2', - logo: `${ICON_BASE}/pl/javascript.svg`, - }, - }, - }, - }, - }, login: { title: 'login', desc: '第三方账号登录', diff --git a/src/containers/tool/Doraemon/logic/index.js b/src/containers/tool/Doraemon/logic/index.js index 6ec014d18..bd83a5325 100755 --- a/src/containers/tool/Doraemon/logic/index.js +++ b/src/containers/tool/Doraemon/logic/index.js @@ -348,20 +348,6 @@ const initSpecCmdResolver = () => { log('SAK.stepOneCmd hbackward') }, }, - { - match: SAK.stepOneCmd('cheatsheet'), - action: () => { - log('SAK.stepOneCmd cheatsheet') - Router.push( - { - pathname: '/', - query: { main: 'cheatsheet' }, - }, - '/cheatsheet', - ) - hidePanel() - }, - }, { match: SAK.stepOneCmd('discovery'), action: () => { diff --git a/src/schemas/pages/cheatsheet.ts b/src/schemas/pages/cheatsheet.ts deleted file mode 100755 index d4e740b7d..000000000 --- a/src/schemas/pages/cheatsheet.ts +++ /dev/null @@ -1,22 +0,0 @@ -// import F from '../fragments' - -const cheatsheet = ` - query($community: String!) { - cheatsheet(community: $community) { - id - views - readme - lastSync - contributors { - avatar - nickname - htmlUrl - bio - location - company - } - } - } -` - -export default cheatsheet diff --git a/src/schemas/pages/index.ts b/src/schemas/pages/index.ts index 13925eafd..d266fac7c 100755 --- a/src/schemas/pages/index.ts +++ b/src/schemas/pages/index.ts @@ -5,7 +5,6 @@ import { user, sessionState } from './user' import { community, subscribedCommunities, pagedCommunities } from './community' import { pagedComments } from './comment' import { pagedCategories, partialTags } from './misc' -import cheatsheet from './cheatsheet' import wiki from './wiki' import { mentions } from './mail' @@ -40,8 +39,6 @@ const P = { // user user, sessionState, - // cheatsheet - cheatsheet, // wiki wiki, // action diff --git a/src/services/github_api/cheatsheet_search.js b/src/services/github_api/cheatsheet_search.js deleted file mode 100755 index 92e73ef68..000000000 --- a/src/services/github_api/cheatsheet_search.js +++ /dev/null @@ -1,13 +0,0 @@ -import { timeout } from 'promise-timeout' - -import { TIMEOUT_SEC, contentEndpoint } from './config' -import { restClient } from './client' - -export const searchCheatsheeetPromise = (raw) => { - // /javascript_wiki.md - const api = `${contentEndpoint}/cps_cheatsheets/master/${raw}.md` - - return timeout(restClient(`${api}`), TIMEOUT_SEC) -} - -export const holder = 1 diff --git a/src/services/github_api/index.js b/src/services/github_api/index.js index b1dc5cca2..bd70bd85d 100755 --- a/src/services/github_api/index.js +++ b/src/services/github_api/index.js @@ -5,7 +5,6 @@ import { ERR } from '@/constant' import { searchRepoPromise, transformRepo } from './repo_search' import { searchUserPromise, ransformUser } from './user_search' import { searchWikiPromise } from './wiki_search' -import { searchCheatsheeetPromise } from './cheatsheet_search' const githubAPI = { // search repo @@ -16,7 +15,6 @@ const githubAPI = { transformUser: (res) => ransformUser(res), // search wiki searchWiki: (raw) => searchWikiPromise(raw), - searchCheatsheet: (raw) => searchCheatsheeetPromise(raw), parseError: (e) => { if (e instanceof TimeoutError) return ERR.TIMEOUT diff --git a/src/stores/RootStore/index.ts b/src/stores/RootStore/index.ts index 3ecddea49..ba22667c8 100755 --- a/src/stores/RootStore/index.ts +++ b/src/stores/RootStore/index.ts @@ -39,7 +39,6 @@ import { WikiThreadStore, JobsThreadStore, UsersThreadStore, - CheatsheetThreadStore, // banners ArticleDigestStore, CommunityDigestStore, @@ -179,7 +178,6 @@ const rootStore = T.model({ wikiThread: T.optional(WikiThreadStore, {}), jobsThread: T.optional(JobsThreadStore, {}), usersThread: T.optional(UsersThreadStore, {}), - cheatsheetThread: T.optional(CheatsheetThreadStore, {}), tagsBar: T.optional(TagsBarStore, {}), userLister: T.optional(UserListerStore, {}), diff --git a/src/stores/SharedModel/Cheatsheet.ts b/src/stores/SharedModel/Cheatsheet.ts deleted file mode 100755 index 0a040424d..000000000 --- a/src/stores/SharedModel/Cheatsheet.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { types as T } from 'mobx-state-tree' -import { GithubUser } from './GithubUser' - -const Cheatsheet = T.model('Cheatsheet', { - id: T.maybeNull(T.string), - readme: T.maybeNull(T.string), - lastSync: T.maybeNull(T.string), - views: T.maybeNull(T.number), - contributors: T.optional(T.array(GithubUser), []), -}) - -export default Cheatsheet diff --git a/src/stores/SharedModel/index.ts b/src/stores/SharedModel/index.ts index 73dae0162..dd4b235c5 100755 --- a/src/stores/SharedModel/index.ts +++ b/src/stores/SharedModel/index.ts @@ -19,7 +19,6 @@ export { FavoriteCategory, PagedFavoriteCategories } from './FavoriteCategory' export { GithubUser } from './GithubUser' export { default as Wiki } from './Wiki' -export { default as Cheatsheet } from './Cheatsheet' export { EmptyUser, diff --git a/src/stores/index.ts b/src/stores/index.ts index a73cdb029..09368f38c 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -57,7 +57,6 @@ export { default as ReposThreadStore } from '@/containers/thread/ReposThread/sto export { default as WikiThreadStore } from '@/containers/thread/WikiThread/store' export { default as JobsThreadStore } from '@/containers/thread/JobsThread/store' export { default as UsersThreadStore } from '@/containers/thread/UsersThread/store' -export { default as CheatsheetThreadStore } from '@/containers/thread/CheatsheetThread/store' export { default as RoadmapThreadStore } from '@/containers/thread/RoadmapThread/store' export { default as TagsBarStore } from '@/containers/unit/TagsBar/store' diff --git a/utils/constant/route.ts b/utils/constant/route.ts index 0c9e043c3..3d5e95ca6 100755 --- a/utils/constant/route.ts +++ b/utils/constant/route.ts @@ -4,14 +4,12 @@ const ROUTE = { // this page is not exist on url, but serves default community page COMMUNITY: 'community', DISCOVERY: 'discovery', - CHEATSHEETS: 'cheatsheets', POSTS: 'posts', BLOGS: 'blogs', JOBS: 'jobs', USERS: 'users', REPOS: 'repos', WIKI: 'wiki', - CHEATSHEET: 'cheatsheet', POST: 'post', BLOG: 'blog', diff --git a/utils/i18n/index.js b/utils/i18n/index.js index ae11a41dd..245438d08 100755 --- a/utils/i18n/index.js +++ b/utils/i18n/index.js @@ -5,7 +5,6 @@ const I18nDict = { posts: '帖子', post: '帖子', map: '地图', - cheatsheet: 'cheatsheet', radar: '雷达', city: '同城', share: '分享', diff --git a/utils/ssr.js b/utils/ssr.js index ff3234e9b..0d9119784 100755 --- a/utils/ssr.js +++ b/utils/ssr.js @@ -37,9 +37,6 @@ export const ssrPagedSchema = (thread) => { case THREAD.REPO: return P.pagedRepos - case THREAD.CHEATSHEET: - return P.cheatsheet - case THREAD.WIKI: return P.wiki @@ -50,9 +47,6 @@ export const ssrPagedSchema = (thread) => { export const ssrPagedFilter = (community, thread, filter, userHasLogin) => { thread = toLower(thread) - if (thread === THREAD.CHEATSHEET || thread === THREAD.WIKI) { - return { community } - } if (community === HCN && thread === THREAD.JOB) { filter = omit(['community'], filter) @@ -99,16 +93,6 @@ export const ssrContentsThread = (resp, thread, filters = {}) => { }, } - case THREAD.CHEATSHEET: - return { - cheatsheetThread: { - cheatsheet: resp.cheatsheet, - curView: isEmpty(resp.cheatsheet.readme) - ? TYPE.NOT_FOUND - : TYPE.RESULT, - }, - } - case THREAD.WIKI: return { wikiThread: { From 26ffa37df62fdc344321799d7f8ed6be512357e9 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 29 Jun 2021 17:38:36 +0800 Subject: [PATCH 7/7] chore(clean up): remove wiki thread --- config/config.json | 2 - config/index.ts | 2 - .../content/CommunityContent/index.tsx | 4 - .../Content/FakeBrowser/Content.js | 1 - .../Content/communityIntros.js | 8 +- .../thread/WikiThread/Contributors.js | 70 --------- src/containers/thread/WikiThread/index.js | 91 ------------ src/containers/thread/WikiThread/logic.js | 136 ------------------ src/containers/thread/WikiThread/schema.ts | 38 ----- src/containers/thread/WikiThread/store.js | 79 ---------- .../thread/WikiThread/styles/contributors.js | 52 ------- .../thread/WikiThread/styles/index.js | 32 ----- .../thread/WikiThread/tests/index.test.ts | 10 -- .../thread/WikiThread/tests/store.test.ts | 10 -- src/schemas/pages/index.ts | 3 - src/schemas/pages/wiki.ts | 20 --- src/services/github_api/index.js | 4 - src/services/github_api/wiki_search.js | 13 -- src/stores/RootStore/index.ts | 2 - src/stores/index.ts | 1 - utils/constant/route.ts | 1 - utils/route.js | 1 - utils/ssr.js | 11 -- 23 files changed, 4 insertions(+), 587 deletions(-) delete mode 100755 src/containers/thread/WikiThread/Contributors.js delete mode 100755 src/containers/thread/WikiThread/index.js delete mode 100755 src/containers/thread/WikiThread/logic.js delete mode 100755 src/containers/thread/WikiThread/schema.ts delete mode 100755 src/containers/thread/WikiThread/store.js delete mode 100755 src/containers/thread/WikiThread/styles/contributors.js delete mode 100755 src/containers/thread/WikiThread/styles/index.js delete mode 100755 src/containers/thread/WikiThread/tests/index.test.ts delete mode 100755 src/containers/thread/WikiThread/tests/store.test.ts delete mode 100755 src/schemas/pages/wiki.ts delete mode 100755 src/services/github_api/wiki_search.js diff --git a/config/config.json b/config/config.json index f242b2061..0b9af18f0 100755 --- a/config/config.json +++ b/config/config.json @@ -61,8 +61,6 @@ "GITHUB_CPS_TEAM": "https://github.com/orgs/coderplanets/people", "ISSUE_ADDR": "https://github.com/coderplanets/coderplanets_web/issues", "MENTION_USER_ADDR": "https://coderplanets.com/users/", - "COMMUNITY_WIKI": "https://github.com/coderplanets/cps_wiki/blob/master", - "COMMUNITY_CHEATSHEET": "https://github.com/coderplanets/cps_cheatsheets/blob/master", "//--- contact configs ---//": "", "EMAIL_CLUB": "club@group.coderplanets.com", "EMAIL_SUPPORT": "support@group.coderplanets.com", diff --git a/config/index.ts b/config/index.ts index 17ed31803..3b24f00bf 100755 --- a/config/index.ts +++ b/config/index.ts @@ -31,8 +31,6 @@ export const { GITHUB_CPS_TEAM, ISSUE_ADDR, MENTION_USER_ADDR, - COMMUNITY_WIKI, - COMMUNITY_CHEATSHEET, EMAIL_CLUB, EMAIL_SUPPORT, EMAIL_HELLO, diff --git a/src/containers/content/CommunityContent/index.tsx b/src/containers/content/CommunityContent/index.tsx index 18d3d378b..c5d4ea016 100755 --- a/src/containers/content/CommunityContent/index.tsx +++ b/src/containers/content/CommunityContent/index.tsx @@ -13,7 +13,6 @@ import { pluggedIn, buildLog } from '@/utils' import PostsThread from '@/containers//thread/PostsThread' import BlogsThread from '@/containers//thread/BlogsThread' import ReposThread from '@/containers/thread/ReposThread' -import WikiThread from '@/containers/thread/WikiThread' import JobsThread from '@/containers/thread/JobsThread' import UsersThread from '@/containers/thread/UsersThread' @@ -39,9 +38,6 @@ const ComunityContent = ({ curRoute }) => { case ROUTE.JOBS: return - case ROUTE.WIKI: - return - default: return } diff --git a/src/containers/editor/CommunityEditor/Content/FakeBrowser/Content.js b/src/containers/editor/CommunityEditor/Content/FakeBrowser/Content.js index a9c108d2d..5c5a50c2c 100755 --- a/src/containers/editor/CommunityEditor/Content/FakeBrowser/Content.js +++ b/src/containers/editor/CommunityEditor/Content/FakeBrowser/Content.js @@ -28,7 +28,6 @@ const Content = ({ title, desc }) => { 周报 导航 小技巧 - wiki 地图 酷团队 工作 diff --git a/src/containers/editor/CommunityEditor/Content/communityIntros.js b/src/containers/editor/CommunityEditor/Content/communityIntros.js index 0a7d894b9..9b9687a92 100755 --- a/src/containers/editor/CommunityEditor/Content/communityIntros.js +++ b/src/containers/editor/CommunityEditor/Content/communityIntros.js @@ -2,7 +2,7 @@ const COMMUNITY_INTRO = { STANDER: { title: '什么是标准型社区?', desc: - '编程语言,编程框架,基础设施等通用等领域的社区,包含帖子,周报,导航,小技巧,wiki,地图,酷团队,招聘等频道。社区成员共同管理。', + '编程语言,编程框架,基础设施等通用等领域的社区,包含帖子,周报,导航,小技巧,地图,酷团队,招聘等频道。社区成员共同管理。', demos: [ { title: 'javascript', @@ -26,7 +26,7 @@ const COMMUNITY_INTRO = { CITY: { title: '什么事同城类社区?', desc: - '以城市为单元的社区,包含帖子,周报,导航,小技巧,wiki,地图,酷团队,招聘等频道。社区成员共同管理。', + '以城市为单元的社区,包含帖子,周报,导航,小技巧,地图,酷团队,招聘等频道。社区成员共同管理。', demos: [ { title: 'beijing', @@ -53,7 +53,7 @@ const COMMUNITY_INTRO = { WORK: { title: '作品类社区', desc: - '作品分享讨论,收集反馈等,包含帖子,周报,导航,小技巧,wiki,地图,酷团队,招聘等频道。社区成员共同管理。', + '作品分享讨论,收集反馈等,包含帖子,周报,导航,小技巧,地图,酷团队,招聘等频道。社区成员共同管理。', demos: [ { title: 'beijing', @@ -64,7 +64,7 @@ const COMMUNITY_INTRO = { TEAM: { title: '团队型社区', desc: - '团队动态,知识分享,招人等,包含帖子,周报,导航,小技巧,wiki,地图,酷团队,招聘等频道。社区成员共同管理。', + '团队动态,知识分享,招人等,包含帖子,周报,导航,小技巧,地图,酷团队,招聘等频道。社区成员共同管理。', demos: [ { title: 'nanjing', diff --git a/src/containers/thread/WikiThread/Contributors.js b/src/containers/thread/WikiThread/Contributors.js deleted file mode 100755 index 4762d9914..000000000 --- a/src/containers/thread/WikiThread/Contributors.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react' -import TimeAgo from 'timeago-react' - -import { COMMUNITY_WIKI } from '@/config' - -import { Button } from '@/components/Buttons' -import DotDivider from '@/components/DotDivider' -import ContributorList from '@/components/ContributorList' - -import { - Wrapper, - NoteWrapper, - NoteTitle, - NoteDivider, - NoteDesc, - FootNote, - SycNote, - JoinText, -} from './styles/contributors' - -import { addContributor, syncWikiFromGithub } from './logic' - -const Note = ({ communityRaw }) => ( - - 本页贡献者 - - - - 参与编辑 - - 后你的 GitHub 头像会同步在这里, 特此感谢. - - -) - -const Contributors = ({ isLogin, users, views, lastSync, communityRaw }) => ( - - - - - - {views && ( - - 浏览: {views} - - 最后同步:  - - - )} - -
- {isLogin && ( - - )} -
-
-) - -export default React.memo(Contributors) diff --git a/src/containers/thread/WikiThread/index.js b/src/containers/thread/WikiThread/index.js deleted file mode 100755 index e331c6b7e..000000000 --- a/src/containers/thread/WikiThread/index.js +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * WikiThread - * - */ - -import React from 'react' - -import { ICON_CMD, COMMUNITY_WIKI } from '@/config' -import { TYPE } from '@/constant' -import { pluggedIn, buildLog } from '@/utils' - -import EmptyThread from '@/components/EmptyThread' -import { PublishButton } from '@/components/Buttons' -import MarkDownRender from '@/components/MarkDownRender' -import { ArticleContentLoading } from '@/components/LoadingEffects' -import GithubSyncWarning from '@/components/GithubSyncWarning' -import Contributors from './Contributors' - -import { - Wrapper, - LeftPart, - WikiWrapper, - RightPart, - PublisherWrapper, -} from './styles' -import { useInit, syncWarnOnClose } from './logic' - -/* eslint-disable-next-line */ -const log = buildLog('C:WikiThread') - -const renderView = (wikiData, type, communityRaw) => { - switch (type) { - case TYPE.LOADING: - return - - case TYPE.NOT_FOUND: - return - - case TYPE.RESULT_EMPTY: - return - - default: - return - } -} - -const WikiThreadContainer = ({ wikiThread }) => { - useInit(wikiThread) - - const { - wikiData, - curView, - curCommunity, - showSyncWarning, - isLogin, - } = wikiThread - - const communityRaw = curCommunity.raw - - return ( - - - - {renderView(wikiData, curView, communityRaw)} - - - <> - - - alert(`goto ${COMMUNITY_WIKI}/${communityRaw}_wiki.md`) - } - /> - - - - - - ) -} - -export default pluggedIn(WikiThreadContainer) diff --git a/src/containers/thread/WikiThread/logic.js b/src/containers/thread/WikiThread/logic.js deleted file mode 100755 index 8051c33d0..000000000 --- a/src/containers/thread/WikiThread/logic.js +++ /dev/null @@ -1,136 +0,0 @@ -import { useEffect } from 'react' -import { isEmpty, startsWith } from 'ramda' - -import { TYPE, EVENT, ERR, THREAD } from '@/constant' -import { asyncSuit, buildLog, errRescue, BStore, nilOrEmpty } from '@/utils' -import { githubAPI } from '@/services' - -import S from './schema' - -/* eslint-disable-next-line */ -const log = buildLog('L:WikiThread') - -const { SR71, $solver, asyncRes, asyncErr } = asyncSuit -const sr71$ = new SR71({ - receive: [EVENT.COMMUNITY_CHANGE, EVENT.THREAD_CHANGE], -}) - -let sub$ = null -let store = null - -const loadWiki = () => { - const community = store.curCommunity.raw - - store.mark({ curView: TYPE.LOADING }) - sr71$.query(S.wiki, { community }) -} - -const syncWiki = (readme) => { - const args = { - readme, - lastSync: new Date().toISOString(), - communityId: store.curCommunity.id, - } - - store.mark({ curView: TYPE.LOADING }) - sr71$.mutate(S.syncWiki, args) -} - -export const syncWarnOnClose = () => store.mark({ showSyncWarning: false }) - -export const syncWikiFromGithub = () => { - if (nilOrEmpty(BStore.get('github_token'))) { - return store.mark({ showSyncWarning: true }) - } - - githubAPI - .searchWiki(store.curCommunity.raw) - .then((res) => { - if (!res || startsWith('404', res)) { - return store.mark({ curView: TYPE.NOT_FOUND }) - } - syncWiki(res) - }) - .catch((e) => store.handleError(githubAPI.parseError(e))) -} - -export const addContributor = (user) => { - const args = { - id: store.wikiData.id, - contributor: user, - } - sr71$.mutate(S.addWikiContributor, args) -} - -// ############################### -// Data & Error handlers -// ############################### - -const DataSolver = [ - { - match: asyncRes('wiki'), - action: ({ wiki }) => { - const curView = isEmpty(wiki.readme) ? TYPE.RESULT_EMPTY : TYPE.RESULT - store.mark({ wiki, curView }) - }, - }, - { - match: asyncRes('syncWiki'), - action: () => loadWiki(), - }, - { - match: asyncRes('addWikiContributor'), - action: () => loadWiki(), - }, - { - match: asyncRes(EVENT.COMMUNITY_CHANGE), - action: () => loadWiki(), - }, - { - match: asyncRes(EVENT.THREAD_CHANGE), - action: (res) => { - const { data } = res[EVENT.THREAD_CHANGE] - const { activeThread } = data - if (activeThread === THREAD.WIKI) return loadWiki() - }, - }, -] -const ErrSolver = [ - { - match: asyncErr(ERR.GRAPHQL), - action: () => { - store.mark({ curView: TYPE.NOT_FOUND }) - }, - }, - { - match: asyncErr(ERR.TIMEOUT), - action: ({ details }) => { - errRescue({ type: ERR.TIMEOUT, details, path: 'WikiThread' }) - }, - }, - { - match: asyncErr(ERR.NETWORK), - action: () => { - errRescue({ type: ERR.NETWORK, path: 'WikiThread' }) - }, - }, -] - -// ############################### -// init & uninit -// ############################### -export const useInit = (_store) => { - useEffect(() => { - store = _store - // log('effect init') - sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver)) - - return () => { - // log('effect uninit') - if (store.curView === TYPE.LOADING || !sub$) return false - log('===== do uninit') - sub$.unsubscribe() - sub$ = null - } - }, [_store]) -} diff --git a/src/containers/thread/WikiThread/schema.ts b/src/containers/thread/WikiThread/schema.ts deleted file mode 100755 index 5f91f8fe3..000000000 --- a/src/containers/thread/WikiThread/schema.ts +++ /dev/null @@ -1,38 +0,0 @@ -import gql from 'graphql-tag' -import { P } from '@/schemas' - -const wiki = gql` - ${P.wiki} -` -const syncWiki = gql` - mutation($communityId: ID!, $readme: String!, $lastSync: String!) { - syncWiki(communityId: $communityId, readme: $readme, lastSync: $lastSync) { - id - readme - } - } -` -const addWikiContributor = gql` - mutation($id: ID!, $contributor: GithubContributorInput!) { - addWikiContributor(id: $id, contributor: $contributor) { - id - readme - contributors { - nickname - avatar - bio - company - location - htmlUrl - } - } - } -` - -const schema = { - wiki, - syncWiki, - addWikiContributor, -} - -export default schema diff --git a/src/containers/thread/WikiThread/store.js b/src/containers/thread/WikiThread/store.js deleted file mode 100755 index 015a27113..000000000 --- a/src/containers/thread/WikiThread/store.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * WikiThread store - * - */ - -import { types as T, getParent } from 'mobx-state-tree' - -import { TYPE, ERR } from '@/constant' -import { markStates, buildLog, stripMobx } from '@/utils' -import { Wiki } from '@/model' - -/* eslint-disable-next-line */ -const log = buildLog('S:WikiThread') - -const WikiThread = T.model('WikiThread', { - wiki: T.optional(Wiki, { readme: '' }), - curView: T.optional( - T.enumeration('curView', [ - TYPE.RESULT, - TYPE.LOADING, - TYPE.NOT_FOUND, - TYPE.RESULT_EMPTY, - ]), - TYPE.RESULT, - ), - // errorType - errorType: T.maybeNull(T.string), - showSyncWarning: T.optional(T.boolean, false), -}) - .views((self) => ({ - get root() { - return getParent(self) - }, - get isLogin() { - return self.root.account.isLogin - }, - get curCommunity() { - return stripMobx(self.root.viewing.community) - }, - get wikiData() { - return stripMobx(self.wiki) - }, - })) - .actions((self) => ({ - changesetErr(options) { - self.root.changesetErr(options) - }, - handleError(errorType) { - log(errorType) - self.mark({ errorType, searching: false }) - switch (errorType) { - case ERR.NOT_FOUND: - return self.changesetErr({ - title: '仓库未找到', - msg: '请确认输入的仓库地址', - }) - - case ERR.AUTH: - return self.changesetErr({ - title: 'Github 鉴权出错', - msg: 'token 可能过期,请尝试重新登录', - }) - - case ERR.TIMEOUT: - return self.changesetErr({ - title: 'Github 超时', - msg: '特殊国情,请稍后重试', - }) - - default: - return self.changesetErr({ title: '未知错误', msg: '...' }) - } - }, - mark(sobj) { - markStates(sobj, self) - }, - })) - -export default WikiThread diff --git a/src/containers/thread/WikiThread/styles/contributors.js b/src/containers/thread/WikiThread/styles/contributors.js deleted file mode 100755 index 793c638f1..000000000 --- a/src/containers/thread/WikiThread/styles/contributors.js +++ /dev/null @@ -1,52 +0,0 @@ -import styled from 'styled-components' - -// import Img from '@/Img' -import { theme, css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flexColumn()}; -` -export const NoteWrapper = styled.div` - ${css.flexColumn()}; - margin-top: 20px; -` -export const NoteTitle = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 1rem; - font-weight: bold; -` -export const NoteDivider = styled.div` - border-bottom-color: ${theme('banner.desc')}; - border-bottom: 1px solid; - margin-top: 6px; - margin-bottom: 6px; - width: 90%; - opacity: 0.4; -` -export const NoteDesc = styled.div` - color: ${theme('thread.articleDigest')}; - font-size: 0.8rem; -` -export const FootNote = styled.div` - margin-top: 15px; -` -export const SycNote = styled.div` - ${css.flex('align-center')}; - - color: ${theme('thread.articleDigest')}; - opacity: 0.8; - font-size: 0.8rem; -` - -export const JoinText = styled.a` - color: ${theme('thread.articleDigest')}; - text-decoration: underline; - margin-right: 3px; - - &:hover { - color: ${theme('thread.articleTitle')}; - text-decoration: underline; - cursor: pointer; - font-weight: bold; - } -` diff --git a/src/containers/thread/WikiThread/styles/index.js b/src/containers/thread/WikiThread/styles/index.js deleted file mode 100755 index cefa65cbb..000000000 --- a/src/containers/thread/WikiThread/styles/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import styled from 'styled-components' - -import { css } from '@/utils' - -export const Wrapper = styled.div` - ${css.flex()}; - width: 100%; -` -export const LeftPart = styled.div` - flex-grow: 1; - width: 100%; -` -export const WikiWrapper = styled.div` - width: 90%; -` -export const RightPart = styled.div` - ${css.flexColumn('align-start')}; - width: 280px; - margin-left: 50px; - padding-top: 5px; - ${css.media.tablet`display: none;`}; -` -export const PublisherWrapper = styled.div` - width: 100%; - max-width: 220px; - margin-top: 10px; -` - -export const MobileBottom = styled.div` - display: none; - ${css.media.tablet`display: block;`}; -` diff --git a/src/containers/thread/WikiThread/tests/index.test.ts b/src/containers/thread/WikiThread/tests/index.test.ts deleted file mode 100755 index 3ec549962..000000000 --- a/src/containers/thread/WikiThread/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import WikiThread from '../index' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/containers/thread/WikiThread/tests/store.test.ts b/src/containers/thread/WikiThread/tests/store.test.ts deleted file mode 100755 index 06b64c99e..000000000 --- a/src/containers/thread/WikiThread/tests/store.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * WikiThread store test - * - */ - -// import WikiThread from '../index' - -it('TODO: store test WikiThread', () => { - expect(1 + 1).toBe(2) -}) diff --git a/src/schemas/pages/index.ts b/src/schemas/pages/index.ts index d266fac7c..890e9f90c 100755 --- a/src/schemas/pages/index.ts +++ b/src/schemas/pages/index.ts @@ -5,7 +5,6 @@ import { user, sessionState } from './user' import { community, subscribedCommunities, pagedCommunities } from './community' import { pagedComments } from './comment' import { pagedCategories, partialTags } from './misc' -import wiki from './wiki' import { mentions } from './mail' import { @@ -39,8 +38,6 @@ const P = { // user user, sessionState, - // wiki - wiki, // action // mentions mentions, diff --git a/src/schemas/pages/wiki.ts b/src/schemas/pages/wiki.ts deleted file mode 100755 index 62a642510..000000000 --- a/src/schemas/pages/wiki.ts +++ /dev/null @@ -1,20 +0,0 @@ -const wiki = ` - query($community: String!) { - wiki(community: $community) { - id - views - readme - lastSync - contributors { - avatar - nickname - htmlUrl - bio - location - company - } - } - } -` - -export default wiki diff --git a/src/services/github_api/index.js b/src/services/github_api/index.js index bd70bd85d..c984dfbeb 100755 --- a/src/services/github_api/index.js +++ b/src/services/github_api/index.js @@ -4,7 +4,6 @@ import { ERR } from '@/constant' import { searchRepoPromise, transformRepo } from './repo_search' import { searchUserPromise, ransformUser } from './user_search' -import { searchWikiPromise } from './wiki_search' const githubAPI = { // search repo @@ -13,9 +12,6 @@ const githubAPI = { // search user searchUser: (login) => searchUserPromise(login), transformUser: (res) => ransformUser(res), - // search wiki - searchWiki: (raw) => searchWikiPromise(raw), - parseError: (e) => { if (e instanceof TimeoutError) return ERR.TIMEOUT if (!e || !e.response) return ERR.UNKOWN diff --git a/src/services/github_api/wiki_search.js b/src/services/github_api/wiki_search.js deleted file mode 100755 index ee2bfdfe5..000000000 --- a/src/services/github_api/wiki_search.js +++ /dev/null @@ -1,13 +0,0 @@ -import { timeout } from 'promise-timeout' -import { TIMEOUT_SEC, contentEndpoint } from './config' - -import { restClient } from './client' - -export const searchWikiPromise = (raw) => { - // /javascript_wiki.md - const api = `${contentEndpoint}/cps_wiki/master/${raw}_wiki.md` - - return timeout(restClient(`${api}`), TIMEOUT_SEC) -} - -export const holder = 1 diff --git a/src/stores/RootStore/index.ts b/src/stores/RootStore/index.ts index ba22667c8..62864660e 100755 --- a/src/stores/RootStore/index.ts +++ b/src/stores/RootStore/index.ts @@ -36,7 +36,6 @@ import { // threads PostsThreadStore, ReposThreadStore, - WikiThreadStore, JobsThreadStore, UsersThreadStore, // banners @@ -175,7 +174,6 @@ const rootStore = T.model({ // threads postsThread: T.optional(PostsThreadStore, {}), reposThread: T.optional(ReposThreadStore, {}), - wikiThread: T.optional(WikiThreadStore, {}), jobsThread: T.optional(JobsThreadStore, {}), usersThread: T.optional(UsersThreadStore, {}), diff --git a/src/stores/index.ts b/src/stores/index.ts index 09368f38c..ac2918dbb 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -54,7 +54,6 @@ export { default as FooterStore } from '@/containers/unit/Footer/store' // threads store export { default as PostsThreadStore } from '@/containers/thread/PostsThread/store' export { default as ReposThreadStore } from '@/containers/thread/ReposThread/store' -export { default as WikiThreadStore } from '@/containers/thread/WikiThread/store' export { default as JobsThreadStore } from '@/containers/thread/JobsThread/store' export { default as UsersThreadStore } from '@/containers/thread/UsersThread/store' export { default as RoadmapThreadStore } from '@/containers/thread/RoadmapThread/store' diff --git a/utils/constant/route.ts b/utils/constant/route.ts index 3d5e95ca6..ae6c341e6 100755 --- a/utils/constant/route.ts +++ b/utils/constant/route.ts @@ -9,7 +9,6 @@ const ROUTE = { JOBS: 'jobs', USERS: 'users', REPOS: 'repos', - WIKI: 'wiki', POST: 'post', BLOG: 'blog', diff --git a/utils/route.js b/utils/route.js index ad5cfb392..a401b681d 100755 --- a/utils/route.js +++ b/utils/route.js @@ -333,7 +333,6 @@ const TR_MAP = { job: 'jobs', repo: 'repos', - /* wiki: 'wiki', */ /* map: 'map', */ } diff --git a/utils/ssr.js b/utils/ssr.js index 0d9119784..9d820b536 100755 --- a/utils/ssr.js +++ b/utils/ssr.js @@ -37,9 +37,6 @@ export const ssrPagedSchema = (thread) => { case THREAD.REPO: return P.pagedRepos - case THREAD.WIKI: - return P.wiki - default: return P.pagedPosts } @@ -93,14 +90,6 @@ export const ssrContentsThread = (resp, thread, filters = {}) => { }, } - case THREAD.WIKI: - return { - wikiThread: { - wiki: resp.wiki, - curView: isEmpty(resp.wiki.readme) ? TYPE.NOT_FOUND : TYPE.RESULT, - }, - } - default: return { postsThread: {