Skip to content

Commit

Permalink
feat(article): revise republication logic
Browse files Browse the repository at this point in the history
  • Loading branch information
robertu7 committed Feb 29, 2024
1 parent f072e17 commit 766f4f7
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 196 deletions.
1 change: 0 additions & 1 deletion src/common/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export const MAX_ARTICLE_SUPPORT_LENGTH = 140
export const MAX_ARTICLE_COMMENT_LENGTH = 1200

export const MAX_ARTICLE_REVISION_COUNT = 4
export const MAX_ARTICLE_REVISION_DIFF = 50
export const MAX_ARTICLE_TAG_LENGTH = 3
export const MAX_ARTICLE_COLLECT_LENGTH = 3

Expand Down
12 changes: 3 additions & 9 deletions src/components/Editor/Article/Summary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { LanguageContext } from '~/components'
* <EditorSummary
* devalutValue="Default summary"
* enable={true}
* readOnly={false}
* texts={{}}
* update={() => func({ summary: '' })}
* />
Expand All @@ -22,14 +21,12 @@ import { LanguageContext } from '~/components'
interface Props {
defaultValue?: string
enable?: boolean
readOnly?: boolean
update: (params: { summary: any }) => void
}

const EditorSummary: React.FC<Props> = ({
defaultValue = '',
enable,
readOnly,
update,
}) => {
const { lang } = useContext(LanguageContext)
Expand Down Expand Up @@ -65,7 +62,6 @@ const EditorSummary: React.FC<Props> = ({

const classes = classNames({
'editor-summary': true,
'u-area-disable': readOnly,
})
const counterClasses = classNames({
counter: true,
Expand Down Expand Up @@ -94,11 +90,9 @@ const EditorSummary: React.FC<Props> = ({
onChange={handleChange}
onKeyDown={handleKeyDown}
/>
{!readOnly && (
<section className={counterClasses}>
({length}/{MAX_ARTICE_SUMMARY_LENGTH})
</section>
)}
<section className={counterClasses}>
({length}/{MAX_ARTICE_SUMMARY_LENGTH})
</section>
</section>
)
}
Expand Down
12 changes: 2 additions & 10 deletions src/components/Editor/Article/Title/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,12 @@ import styles from './styles.module.css'

interface Props {
defaultValue?: string
readOnly?: boolean
update: (params: { title: any }) => void
}

const EditorTitle: React.FC<Props> = ({
defaultValue = '',
readOnly,
update,
}) => {
const EditorTitle: React.FC<Props> = ({ defaultValue = '', update }) => {
const { lang } = useContext(LanguageContext)
const classes = classNames(
[styles.editorTitle],
readOnly ? 'u-area-disable' : ''
)
const classes = classNames([styles.editorTitle])

const [value, setValue] = React.useState(defaultValue)

Expand Down
67 changes: 1 addition & 66 deletions src/components/Editor/Article/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { useApolloClient } from '@apollo/react-hooks'
import {
EditorContent,
useArticleEdtor,
useEditArticleEdtor,
} from '@matters/matters-editor'
import { EditorContent, useArticleEdtor } from '@matters/matters-editor'
import classNames from 'classnames'
import { useContext } from 'react'
import { useDebouncedCallback } from 'use-debounce'
Expand Down Expand Up @@ -104,64 +100,3 @@ export const ArticleEditor: React.FC<ArticleEditorProps> = ({
</div>
)
}

export const EditArticleEditor: React.FC<ArticleEditorProps> = ({
draft,

update,
upload,
}) => {
const { lang } = useContext(LanguageContext)
const client = useApolloClient()

const { content, publishState, summary, summaryCustomized, title } = draft
const isPending = publishState === 'pending'
const isReadOnly = isPending

const editor = useEditArticleEdtor({
editable: !isReadOnly,
placeholder: translate({
zh_hant: '請輸入正文…',
zh_hans: '请输入正文…',
en: 'Enter content…',
lang,
}),
content: content || '',
onUpdate: async ({ editor, transaction }) => {
const content = editor.getHTML()
update({ content })
},
mentionSuggestion: makeMentionSuggestion({ client }),
extensions: [
FigureEmbedLinkInput,
FigurePlaceholder.configure({
placeholder: translate({
zh_hant: '添加說明文字…',
zh_hans: '添加说明文字…',
en: 'Add caption…',
lang,
}),
}),
],
})

return (
<div
className={classNames({
[styles.articleEditor]: true,
[styles.revisedMode]: true,
})}
>
<EditorTitle defaultValue={title || ''} readOnly update={update} />

<EditorSummary
defaultValue={summaryCustomized && summary ? summary : ''}
readOnly
update={update}
enable
/>

<EditorContent editor={editor} />
</div>
)
}
4 changes: 4 additions & 0 deletions src/views/ArticleDetail/Edit/Header/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import articleFragments from '~/components/GQL/fragments/article'
export const EDIT_ARTICLE = gql`
mutation EditArticle(
$id: ID!
$title: String
$summary: String
$content: String
$cover: ID
$tags: [String!]
Expand All @@ -24,6 +26,8 @@ export const EDIT_ARTICLE = gql`
editArticle(
input: {
id: $id
# title: $title
# summary: $summary
content: $content
cover: $cover
tags: $tags
Expand Down
134 changes: 63 additions & 71 deletions src/views/ArticleDetail/Edit/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
import { normalizeArticleHTML } from '@matters/matters-editor'
import { useContext, useEffect, useRef } from 'react'
import _isEqual from 'lodash/isEqual'
import { FormattedMessage } from 'react-intl'

import {
MAX_ARTICLE_CONTENT_LENGTH,
MAX_ARTICLE_REVISION_DIFF,
} from '~/common/enums'
import { measureDiffs, stripHtml } from '~/common/utils'
import {
Button,
TextIcon,
toast,
Translate,
useMutation,
ViewerContext,
} from '~/components'
import { MAX_ARTICLE_CONTENT_LENGTH } from '~/common/enums'
import { toPath } from '~/common/utils'
import { Button, TextIcon, toast, Translate, useMutation } from '~/components'
import {
ConfirmStepContentProps,
EditorSettingsDialog,
EditorSettingsDialogProps,
} from '~/components/Editor/SettingsDialog'
import { EditArticleMutation } from '~/gql/graphql'
import { VIEWER_ARTICLES } from '~/views/User/Articles/gql'
import {
AssetFragment,
EditArticleMutation,
QueryEditArticleQuery,
} from '~/gql/graphql'

import ConfirmRevisedPublishDialogContent from './ConfirmRevisedPublishDialogContent'
import { EDIT_ARTICLE } from './gql'
import styles from './styles.module.css'

type EditModeHeaderProps = {
article: {
id: string
replyToDonator?: string | null
requestForDonation?: string | null
}
lastContent: string
editContent?: string
coverId?: string
article: NonNullable<
QueryEditArticleQuery['article'] & {
__typename: 'Article'
}
>

revisedTitle?: string
revisedSummary?: string
revisedContent?: string
revisedCover?: AssetFragment

revisionCountLeft: number
isOverRevisionLimit: boolean
isEditDisabled: boolean

onSaved: () => any
onPublish: () => any
} & Omit<
EditorSettingsDialogProps,
Expand All @@ -57,44 +50,50 @@ type EditModeHeaderProps = {
const EditModeHeader = ({
article,

lastContent,
editContent,
coverId,
revisedTitle,
revisedSummary,
revisedContent,
revisedCover,

revisionCountLeft,
isOverRevisionLimit,
isEditDisabled,

onSaved,
onPublish,

...restProps
}: EditModeHeaderProps) => {
const viewer = useContext(ViewerContext)

const initContent = useRef<string>()
useEffect(() => {
initContent.current = lastContent || ''
}, [])

const currContent = editContent || ''
const diff =
measureDiffs(
stripHtml(normalizeArticleHTML(initContent.current || '')),
stripHtml(normalizeArticleHTML(currContent || ''))
) || 0
const diffCount = `${diff}`.padStart(2, '0')
const isOverDiffLimit = diff > MAX_ARTICLE_REVISION_DIFF
const isContentRevised = diff > 0

// save or republish
const { tags, collection, circle, accessType, license } = restProps
const [editArticle, { loading }] =
useMutation<EditArticleMutation>(EDIT_ARTICLE)

const isTitleRevised = revisedTitle !== article.title
const isSummaryRevised = revisedSummary !== article.summary
const isContentRevised = revisedContent !== article.contents.html
const isTagRevised = !_isEqual(
tags.map((tag) => tag.id).sort(),
article.tags?.map((tag) => tag.id).sort()
)
const isCollectionRevised = !_isEqual(
collection.map((collection) => collection.id).sort(),
article.collection.edges?.map(({ node }) => node.id).sort()
)
const isCoverRevised = article.cover
? revisedCover?.path !== article.cover
: !!revisedCover?.path
const needRepublish =
isTitleRevised ||
isSummaryRevised ||
isContentRevised ||
isTagRevised ||
isCollectionRevised ||
isCoverRevised

const onSave = async () => {
// check content length
const contentCount = editContent?.length || 0
if (isContentRevised && contentCount > MAX_ARTICLE_CONTENT_LENGTH) {
const contentCount = revisedContent?.length || 0

if (needRepublish && contentCount > MAX_ARTICLE_CONTENT_LENGTH) {
toast.error({
message: (
<FormattedMessage
Expand All @@ -111,35 +110,31 @@ const EditModeHeader = ({
await editArticle({
variables: {
id: article.id,
cover: coverId || null,
tags: tags.map((tag) => tag.content),
collection: collection.map(({ id: articleId }) => articleId),
...(isTitleRevised ? { title: revisedTitle } : {}),
...(isSummaryRevised ? { summary: revisedSummary } : {}),
...(isContentRevised ? { content: revisedContent } : {}),
...(isTagRevised ? { tags: tags.map((tag) => tag.content) } : {}),
...(isCollectionRevised
? { collection: collection.map(({ id }) => id) }
: {}),
...(isCoverRevised ? { cover: revisedCover?.id || null } : {}),
circle: circle ? circle.id : null,
accessType,
license,
...(isContentRevised ? { content: editContent } : {}),
first: null,
iscnPublish: restProps.iscnPublish,
canComment: restProps.canComment,
sensitive: restProps.contentSensitive,
},
refetchQueries: [
{
query: VIEWER_ARTICLES,
variables: { userName: viewer.userName },
},
],
})
if (isContentRevised) {
if (needRepublish) {
onPublish()
}

if (!isContentRevised) {
onSaved()
} else {
const path = toPath({ page: 'articleDetail', article })
window.location.href = path.href
}
} catch (e) {
toast.error({
message: isContentRevised ? (
message: needRepublish ? (
<Translate
zh_hant="發布失敗"
zh_hans="發布失敗"
Expand Down Expand Up @@ -173,9 +168,6 @@ const EditModeHeader = ({
zh_hans=" 次修订"
en=" revisions remaining"
/>
<span className={isOverDiffLimit ? styles.red : styles.green}>
&nbsp;{diffCount}/50&nbsp;&nbsp;&nbsp;
</span>
</>
)

Expand Down Expand Up @@ -224,7 +216,7 @@ const EditModeHeader = ({
bgColor="green"
onClick={openEditorSettingsDialog}
aria-haspopup="dialog"
disabled={isEditDisabled || isOverDiffLimit}
disabled={isEditDisabled}
>
<TextIcon color="white" size="md" weight="md">
<FormattedMessage defaultMessage="Next Step" id="8cv9D4" />
Expand Down
5 changes: 1 addition & 4 deletions src/views/ArticleDetail/Edit/PublishState/PublishedState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ const BasePublishedState = ({
}

const PublishedState = ({ article }: PublishedStateProps) => {
const path = toPath({
page: 'articleDetail',
article: { ...article },
})
const path = toPath({ page: 'articleDetail', article })

return (
<ShareDialog
Expand Down
Loading

0 comments on commit 766f4f7

Please sign in to comment.