diff --git a/src/containers/thread/DashboardThread/Footer/Editors/LinkEditor.tsx b/src/containers/thread/DashboardThread/Footer/Editors/LinkEditor.tsx index 95d1f6808..5daae94b8 100644 --- a/src/containers/thread/DashboardThread/Footer/Editors/LinkEditor.tsx +++ b/src/containers/thread/DashboardThread/Footer/Editors/LinkEditor.tsx @@ -147,6 +147,7 @@ const LinkEditor: FC = ({ {isTouched ? ( = ({ settings, touched }) => {

+ + + + ) } diff --git a/src/containers/thread/DashboardThread/Header/index.tsx b/src/containers/thread/DashboardThread/Header/index.tsx index 9d32033a7..57c637830 100644 --- a/src/containers/thread/DashboardThread/Header/index.tsx +++ b/src/containers/thread/DashboardThread/Header/index.tsx @@ -2,10 +2,14 @@ import { FC } from 'react' import type { THeaderSettings, TTouched } from '../spec' +import { SETTING_FIELD } from '../constant' + +import SavingBar from '../SavingBar' + import Templates from './Templates' import Editor from './Editors' -import { Wrapper } from '../styles/header' +import { Wrapper, SavingWrapper } from '../styles/header' type TProps = { settings: THeaderSettings @@ -19,6 +23,15 @@ const Header: FC = ({ settings, touched }) => {

+ + + + ) } diff --git a/src/containers/thread/DashboardThread/constant.tsx b/src/containers/thread/DashboardThread/constant.tsx index 2426ec1ba..6facfade7 100755 --- a/src/containers/thread/DashboardThread/constant.tsx +++ b/src/containers/thread/DashboardThread/constant.tsx @@ -47,6 +47,8 @@ export const SETTING_FIELD = { MEDIA_REPORTS: 'mediaReports', SEO: 'seo', SOCIAL_LINKS: 'socialLinks', + HEADER_LINKS: 'headerLinks', + FOOTER_LINKS: 'footerLinks', TAG: 'tag', TAG_INDEX: 'tagIndex', FAQ_SECTIONS: 'faqSections', diff --git a/src/containers/thread/DashboardThread/logic/index.ts b/src/containers/thread/DashboardThread/logic/index.ts index 7ba189189..6a3b9693d 100644 --- a/src/containers/thread/DashboardThread/logic/index.ts +++ b/src/containers/thread/DashboardThread/logic/index.ts @@ -176,6 +176,22 @@ const _doMutation = (field: string, e: TEditValue): void => { return } + if (field === SETTING_FIELD.HEADER_LINKS) { + const { headerSettings } = store + const { headerLinks } = headerSettings + + sr71$.mutate(S.updateDashboardHeaderLinks, { community, headerLinks }) + return + } + + if (field === SETTING_FIELD.FOOTER_LINKS) { + const { footerSettings } = store + const { footerLinks } = footerSettings + + sr71$.mutate(S.updateDashboardFooterLinks, { community, footerLinks }) + return + } + if (field === SETTING_FIELD.BASE_INFO) { const { baseInfoTab } = store @@ -538,6 +554,14 @@ const DataSolver = [ match: asyncRes('reindexTagsInGroup'), action: () => _handleDone(), }, + { + match: asyncRes('updateDashboardHeaderLinks'), + action: () => _handleDone(), + }, + { + match: asyncRes('updateDashboardFooterLinks'), + action: () => _handleDone(), + }, { match: asyncRes('pagedPosts'), action: ({ pagedPosts }) => { diff --git a/src/containers/thread/DashboardThread/logic/links.ts b/src/containers/thread/DashboardThread/logic/links.ts index 827886f94..f11e1df96 100644 --- a/src/containers/thread/DashboardThread/logic/links.ts +++ b/src/containers/thread/DashboardThread/logic/links.ts @@ -5,6 +5,7 @@ import { CHANGE_MODE } from '@/constant/mode' import { ROUTE } from '@/constant/route' import { ONE_LINK_GROUP, MORE_GROUP } from '@/constant/dashboard' import { sortByIndex, groupByKey } from '@/utils/helper' +import { toJS } from '@/utils/mobx' import type { TMoveLinkDir } from '../spec' import { EMPTY_LINK_ITEM } from '../constant' @@ -83,7 +84,7 @@ const _emptyLinksIfNedd = (links: TLinkItem[]): TLinkItem[] => { } export const cancelLinkEditing = (): void => { - const { curPageLinksKey, editingLink, editingLinkMode } = store + const { curPageLinksKey, editingLink, editingLinkMode, initSettings } = store const links = store[curPageLinksKey.settings][curPageLinksKey.links] if (editingLinkMode === CHANGE_MODE.UPDATE) { @@ -98,7 +99,11 @@ export const cancelLinkEditing = (): void => { linksAfter = _emptyLinksIfNedd(linksAfter) - store.mark({ [curPageLinksKey.links]: linksAfter, editingLink: null }) + store.mark({ + [curPageLinksKey.links]: linksAfter, + editingLink: null, + initSettings: { ...toJS(initSettings), [curPageLinksKey.links]: linksAfter }, + }) } export const confirmLinkEditing = (): void => { diff --git a/src/containers/thread/DashboardThread/schema.ts b/src/containers/thread/DashboardThread/schema.ts index 6b8f42ef1..52d5205d2 100755 --- a/src/containers/thread/DashboardThread/schema.ts +++ b/src/containers/thread/DashboardThread/schema.ts @@ -287,6 +287,31 @@ const communityOverview = gql` } ` +const updateDashboardHeaderLinks = gql` + mutation ($community: String!, $headerLinks: [dashboardLinkMap]) { + updateDashboardHeaderLinks(community: $community, headerLinks: $headerLinks) { + slug + dashboard { + headerLinks { + ${F.customLink} + } + } + } + } +` +const updateDashboardFooterLinks = gql` + mutation ($community: String!, $footerLinks: [dashboardLinkMap]) { + updateDashboardFooterLinks(community: $community, footerLinks: $footerLinks) { + slug + dashboard { + footerLinks { + ${F.customLink} + } + } + } + } +` + const openGraphInfo = gql` query ($url: String!) { openGraphInfo(url: $url) { @@ -318,6 +343,8 @@ const schema = { updateModerators, communityOverview, openGraphInfo, + updateDashboardHeaderLinks, + updateDashboardFooterLinks, } export default schema diff --git a/src/containers/thread/DashboardThread/spec.d.ts b/src/containers/thread/DashboardThread/spec.d.ts index 8732fa8db..a88dc425a 100755 --- a/src/containers/thread/DashboardThread/spec.d.ts +++ b/src/containers/thread/DashboardThread/spec.d.ts @@ -216,6 +216,9 @@ export type TTouched = { tags: boolean tagsIndex: boolean + headerLinks: boolean + footerLinks: boolean + faqSections: boolean socialLinks: boolean @@ -260,6 +263,8 @@ export type TSettingField = | 'glowType' | 'glowFixed' | 'glowOpacity' + | 'headerLinks' + | 'footerLinks' | 'docLayout' | 'docFaqLayout' | 'topbarLayout' diff --git a/src/containers/thread/DashboardThread/store/Models.ts b/src/containers/thread/DashboardThread/store/Models.ts index a60ab34bc..c7557c286 100644 --- a/src/containers/thread/DashboardThread/store/Models.ts +++ b/src/containers/thread/DashboardThread/store/Models.ts @@ -190,7 +190,8 @@ export const settingsModalFields = { headerLayout: T.opt(T.enum(values(HEADER_LAYOUT)), HEADER_LAYOUT.CENTER), footerLayout: T.opt(T.enum(values(FOOTER_LAYOUT)), FOOTER_LAYOUT.GROUP), - footerLinks: T.opt(T.array(LinkItem), DEFAULT_LINK_ITEMS), + // footerLinks: T.opt(T.array(LinkItem), DEFAULT_LINK_ITEMS), + footerLinks: T.opt(T.array(LinkItem), []), headerLinks: T.opt(T.array(LinkItem), []), // moderators diff --git a/src/containers/thread/DashboardThread/store/index.ts b/src/containers/thread/DashboardThread/store/index.ts index b59e7a59a..ae46a3a74 100644 --- a/src/containers/thread/DashboardThread/store/index.ts +++ b/src/containers/thread/DashboardThread/store/index.ts @@ -265,12 +265,12 @@ const DashboardThread = T.model('DashboardThread', { _tagsIndexTouched, _socialLinksTouched, _mediaReportsTouched, + editingLink, } = slf const _isChanged = (field: TSettingField): boolean => !equals(toJS(slf[field]), toJS(init[field])) const _anyChanged = (fields: TSettingField[]): boolean => any(_isChanged)(fields) - const _mapArrayChanged = (key: string): boolean => { return JSON.stringify(toJS(self[key])) !== JSON.stringify(toJS(self.initSettings[key])) } @@ -286,6 +286,9 @@ const DashboardThread = T.model('DashboardThread', { const docLayoutTouched = _isChanged('docLayout') const docFaqLayoutTouched = _isChanged('docFaqLayout') + const headerLinksChanged = _isChanged('headerLinks') && editingLink === null + const footerLinksChanged = _isChanged('footerLinks') && editingLink === null + const broadcastLayoutTouched = _isChanged('broadcastLayout') const broadcastBgTouched = _isChanged('broadcastBg') @@ -339,6 +342,8 @@ const DashboardThread = T.model('DashboardThread', { socialLinks: _socialLinksTouched, mediaReports: _mediaReportsTouched, + headerLinks: headerLinksChanged, + footerLinks: footerLinksChanged, faqSections: faqSectionsTouched, glowFixed: glowFixedTouched, @@ -471,10 +476,10 @@ const DashboardThread = T.model('DashboardThread', { } = slf return { + saving: slf.saving, headerLayout: toJS(headerLayout), headerLinks: toJS(headerLinks), editingLink: toJS(editingLink), - saving: slf.saving, editingLinkMode: editingLinkMode as TChangeMode, editingGroup, editingGroupIndex, @@ -500,10 +505,11 @@ const DashboardThread = T.model('DashboardThread', { } = slf return { + saving: slf.saving, footerLayout: toJS(footerLayout), + // footerLinks: reject((item) => isEmpty(item.title), toJS(footerLinks)), footerLinks: toJS(footerLinks), editingLink: toJS(editingLink), - saving: slf.saving, editingLinkMode: editingLinkMode as TChangeMode, editingGroup, editingGroupIndex, diff --git a/src/containers/thread/DashboardThread/styles/footer/index.ts b/src/containers/thread/DashboardThread/styles/footer/index.ts index 495d0efbe..f7eea8189 100644 --- a/src/containers/thread/DashboardThread/styles/footer/index.ts +++ b/src/containers/thread/DashboardThread/styles/footer/index.ts @@ -6,4 +6,6 @@ export const Wrapper = styled.div` ${css.column()}; ` -export const Title = styled.div`` +export const SavingWrapper = styled.div` + width: 98%; +` diff --git a/src/containers/thread/DashboardThread/styles/footer/templates/group.ts b/src/containers/thread/DashboardThread/styles/footer/templates/group.ts index 20db4115e..3c529c487 100644 --- a/src/containers/thread/DashboardThread/styles/footer/templates/group.ts +++ b/src/containers/thread/DashboardThread/styles/footer/templates/group.ts @@ -6,7 +6,7 @@ import { TemplateBlock } from '.' export const Wrapper = styled(TemplateBlock)` ${css.row('align-start', 'justify-between')}; - padding: 12px 20px; + padding: 18px 20px; height: auto; min-height: 150px !important; background: ${theme('alphaBg')}; @@ -41,7 +41,7 @@ export const Desc = styled.div` ` export const CenterWrapper = styled.div` ${css.column()}; - gap: 5px 0; + gap: 8px 0; ` export const GroupTitle = styled.div` @@ -53,7 +53,7 @@ export const GroupTitle = styled.div` export const LinkItem = styled.a` ${css.cutRest('80px')}; color: ${theme('article.digest')}; - font-size: 11px; + font-size: 12px; text-decoration: none; &:hover { diff --git a/src/containers/thread/DashboardThread/styles/footer/templates/simple.ts b/src/containers/thread/DashboardThread/styles/footer/templates/simple.ts index ee5e79d1b..d8864c007 100644 --- a/src/containers/thread/DashboardThread/styles/footer/templates/simple.ts +++ b/src/containers/thread/DashboardThread/styles/footer/templates/simple.ts @@ -24,7 +24,7 @@ export const BrandText = styled.div` export const CenterWrapper = styled.div` ${css.row('align-center')}; - gap: 0 14px; + gap: 0 20px; ` export const LinkItem = styled.a` diff --git a/src/containers/thread/DashboardThread/styles/header/index.ts b/src/containers/thread/DashboardThread/styles/header/index.ts index 495d0efbe..1335f0d91 100644 --- a/src/containers/thread/DashboardThread/styles/header/index.ts +++ b/src/containers/thread/DashboardThread/styles/header/index.ts @@ -6,4 +6,6 @@ export const Wrapper = styled.div` ${css.column()}; ` -export const Title = styled.div`` +export const SavingWrapper = styled.div` + width: 97%; +` diff --git a/src/containers/thread/DashboardThread/styles/side_menu/group.ts b/src/containers/thread/DashboardThread/styles/side_menu/group.ts index cf3cf9484..0ed9edc58 100755 --- a/src/containers/thread/DashboardThread/styles/side_menu/group.ts +++ b/src/containers/thread/DashboardThread/styles/side_menu/group.ts @@ -12,6 +12,7 @@ export const Wrapper = styled.div` export const Folder = styled.div` ${css.row('align-center', 'justify-between')}; cursor: pointer; + margin-bottom: 12px; ` export const IconWrapper = styled.div` ${css.size(18)}; @@ -47,7 +48,7 @@ export const MenuWrapper = styled.div` border-left: 1px solid transparent; border-image: linear-gradient( - 0.55turn, + 0.48turn, ${theme('divider')}, ${theme('divider')}, ${theme('divider')}, @@ -67,7 +68,6 @@ export const Item = styled(Link)` width: 160px; padding: 3px 5px; margin-top: 5px; - margin-bottom: 5px; padding-left: 20px; border-radius: 10px; font-size: 13.5px; @@ -83,7 +83,7 @@ export const Item = styled(Link)` display: ${({ $active }) => ($active ? 'block' : 'none')}; position: absolute; top: 8px; - left: -2px; + left: -3px; width: 4px; height: 13px; border-radius: 8px; diff --git a/src/schemas/fragments/base.ts b/src/schemas/fragments/base.ts index 02308973a..c584477ec 100755 --- a/src/schemas/fragments/base.ts +++ b/src/schemas/fragments/base.ts @@ -24,6 +24,13 @@ export const community = ` insertedAt updatedAt ` +export const customLink = ` + title + link + group + groupIndex + index +` export const tag = ` id title diff --git a/src/schemas/fragments/index.ts b/src/schemas/fragments/index.ts index fe7d1420d..dc9e51b1a 100755 --- a/src/schemas/fragments/index.ts +++ b/src/schemas/fragments/index.ts @@ -28,6 +28,7 @@ import { pagi, getUpvoteSchema, getUndoUpvoteSchema, + customLink, } from './base' import { pagedPosts } from './paged' @@ -38,9 +39,9 @@ const F = { articleDetail, pageArticleMeta, author, + customLink, tag, pagedPosts, - user, userSocial, c11n, diff --git a/src/schemas/pages/community.ts b/src/schemas/pages/community.ts index a61b3e1ef..a478e90d9 100755 --- a/src/schemas/pages/community.ts +++ b/src/schemas/pages/community.ts @@ -45,6 +45,12 @@ export const community = ` logo desc } + headerLinks { + ${F.customLink} + } + footerLinks { + ${F.customLink} + } socialLinks { type diff --git a/src/widgets/ExtraLinks/styles/simple_layout.ts b/src/widgets/ExtraLinks/styles/simple_layout.ts index 7a3e32cef..a30fd39a3 100644 --- a/src/widgets/ExtraLinks/styles/simple_layout.ts +++ b/src/widgets/ExtraLinks/styles/simple_layout.ts @@ -8,7 +8,7 @@ import { Wrapper as WrapperBase, LinkItem as LinkItemBase, ArrowIcon as ArrowIco export { MenuPanel } from '.' export const Wrapper = styled(WrapperBase)` - gap: 0 32px; + gap: 0 16px; ` export const LinkItem = styled(LinkItemBase)` font-size: 14px; diff --git a/src/widgets/Footer/DesktopView/GroupLayout.tsx b/src/widgets/Footer/DesktopView/GroupLayout.tsx index 813816924..f8939e830 100644 --- a/src/widgets/Footer/DesktopView/GroupLayout.tsx +++ b/src/widgets/Footer/DesktopView/GroupLayout.tsx @@ -4,6 +4,7 @@ import { keys } from 'ramda' import type { TThemeMap, TMetric, TLinkItem } from '@/spec' import { DEME_SOCIALS } from '@/constant/social' +import useCurCommunity from '@/hooks/useCurCommunity' import { sortByIndex, groupByKey } from '@/utils/helper' @@ -29,6 +30,7 @@ type TProps = { const GroupLayout: FC = ({ metric, links }) => { const theme = useTheme() as TThemeMap + const curCommunity = useCurCommunity() const linkColors = { color: theme.footer.text, @@ -43,11 +45,11 @@ const GroupLayout: FC = ({ metric, links }) => { - - 让你的产品聆听用户的声音 + + {curCommunity.desc} - + {groupKeys.map((groupTitle: string) => { diff --git a/src/widgets/Footer/styles/desktop_view/group_layout.ts b/src/widgets/Footer/styles/desktop_view/group_layout.ts index 49ceef65a..82b3ec15b 100644 --- a/src/widgets/Footer/styles/desktop_view/group_layout.ts +++ b/src/widgets/Footer/styles/desktop_view/group_layout.ts @@ -89,6 +89,7 @@ export const LinkItem = styled(Link)` text-decoration: none; &:hover { + text-decoration: underline; color: ${theme('article.title')}; cursor: pointer; } diff --git a/utils/ssr.js b/utils/ssr.js index 63c249bc8..f8fb68441 100755 --- a/utils/ssr.js +++ b/utils/ssr.js @@ -238,7 +238,18 @@ const parseDashboardAlias = (nameAlias) => { export const ssrParseDashboard = (community) => { const { dashboard, moderators } = community - const { enable, nameAlias, socialLinks, faqs, seo, layout, rss, baseInfo } = dashboard + const { + enable, + nameAlias, + socialLinks, + faqs, + seo, + layout, + rss, + baseInfo, + headerLinks, + footerLinks, + } = dashboard const fieldsObj = removeEmptyValuesFromObject({ enable, @@ -249,6 +260,8 @@ export const ssrParseDashboard = (community) => { ...seo, ...layout, ...rss, + headerLinks, + footerLinks, moderators, })