Skip to content

Commit

Permalink
feat(campaign): normalize and serialize description
Browse files Browse the repository at this point in the history
  • Loading branch information
robertu7 committed Jul 16, 2024
1 parent 7c3b7cb commit 27e2f09
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 31 deletions.
129 changes: 107 additions & 22 deletions src/components/Campaign/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import * as React from 'react'
import { Mutation } from 'react-apollo'
import { Button, DatePicker, Input, message } from 'antd'
import gql from 'graphql-tag'
import moment from 'moment'

import Uploader from './Uploader'
import Section from '../../../components/DescriptionList'
import Divider from '../../../components/Divider'
import { CampaignDetail } from '../../../definitions'
import { PATH } from '../../../constants'

const PUT_CAMPAIGN = gql`
mutation PutWritingChallenge($input: PutWritingChallengeInput!) {
Expand All @@ -28,6 +30,37 @@ type DetailState = {
error: any
} & CampaignDetail

const normalizeDescription = (description: string) => {
// remove leading and trailing <p></p>
description = description.replace(/^(<p>(<br class=\"smart\">)?<\/p>)+/, '')
description = description.replace(/(<p>(<br class=\"smart\">)?<\/p>)+$/, '')

// replace </p><p> or <br class=\"smart\"> with \n
description = description.replace(/<\/p>/g, '\n')
description = description.replace(/<p><br class=\"smart\"><\/p>/g, '\n')

// remove HTML tags
description = description.replace(/<[^>]*>/g, '')

// remove trailing \n
description = description.replace(/\n+$/, '')

return description
}

const serializeDescription = (description: string) => {
description = description
.trim()
.split('\n')
.map((line) => `<p>${line.trim()}</p>`)
.join('')

// replace <p></p> with <br>
description = description.replace(/<p><\/p>/g, '<p><br class="smart"></p>')

return description
}

class CampaignEditor extends React.Component<DetailProps, DetailState> {
state = {
...this.props.campaign,
Expand All @@ -53,20 +86,54 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
const {
id,
name,
cover,
nameEn,
nameZhHans,
description,
descriptionEn,
descriptionZhHans,
writingPeriod,
applicationPeriod,
coverId,
link,
} = this.state
const result = await putCampaign({

await putCampaign({
variables: {
input: {
id,
name,
name: [
{
language: 'zh_hant',
text: name,
},
{
language: 'en',
text: nameEn,
},
{
language: 'zh_hans',
text: nameZhHans,
},
],
cover: coverId,
description,
applicationPeriod,
writingPeriod,
description: [
{
language: 'zh_hant',
text: serializeDescription(normalizeDescription(description)),
},
{
language: 'en',
text: serializeDescription(normalizeDescription(descriptionEn)),
},
{
language: 'zh_hans',
text: serializeDescription(
normalizeDescription(descriptionZhHans)
),
},
],
link,
},
},
Expand All @@ -76,6 +143,10 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
(prev) => ({ ...prev, loading: false, error: null }),
() => {
message.success('儲存成功')
window.location.href = PATH.CAMPAIGN_DETAIL.replace(
':id',
this.state.shortHash
)
}
)
} catch (error) {
Expand All @@ -92,9 +163,12 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
const {
id,
name,
nameEn,
nameZhHans,
cover,
coverId,
description,
descriptionEn,
descriptionZhHans,
link,
applicationPeriod,
writingPeriod,
Expand All @@ -117,17 +191,17 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
</Section.Description>
<Section.Description term="英文">
<Input
value={name}
value={nameEn}
onChange={(e) => {
this.setState({ name: e.target.value })
this.setState({ nameEn: e.target.value })
}}
/>
</Section.Description>
<Section.Description term="簡體">
<Input
value={name}
value={nameZhHans}
onChange={(e) => {
this.setState({ name: e.target.value })
this.setState({ nameZhHans: e.target.value })
}}
/>
</Section.Description>
Expand All @@ -137,34 +211,37 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
<Section title="簡介" col={1}>
<Section.Description term="繁體">
<Input.TextArea
value={description}
value={normalizeDescription(description)}
autoSize={{ minRows: 5 }}
style={{ verticalAlign: 'middle' }}
onChange={(e) => {
// TODO: replace /n to <br>
this.setState({ description: e.target.value })
this.setState({
description: e.target.value,
})
}}
/>
</Section.Description>
<Section.Description term="英文">
<Input.TextArea
value={description}
value={normalizeDescription(descriptionEn)}
autoSize={{ minRows: 5 }}
style={{ verticalAlign: 'middle' }}
onChange={(e) => {
// TODO: replace /n to <br>
this.setState({ description: e.target.value })
this.setState({
descriptionEn: e.target.value,
})
}}
/>
</Section.Description>
<Section.Description term="簡體">
<Input.TextArea
value={description}
value={normalizeDescription(descriptionZhHans)}
autoSize={{ minRows: 5 }}
style={{ verticalAlign: 'middle' }}
onChange={(e) => {
// TODO: replace /n to <br>
this.setState({ description: e.target.value })
this.setState({
descriptionZhHans: e.target.value,
})
}}
/>
</Section.Description>
Expand Down Expand Up @@ -199,7 +276,9 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
<Section title="報名期" col={2}>
<Section.Description term="開始">
<DatePicker
value={applicationPeriod?.start}
value={
moment(applicationPeriod?.start, 'YYYY-MM-DD') || undefined
}
onChange={(date, dateStr) => {
this.setState({
applicationPeriod: {
Expand All @@ -212,7 +291,9 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
</Section.Description>
<Section.Description term="結束">
<DatePicker
value={applicationPeriod?.end}
value={
moment(applicationPeriod?.end, 'YYYY-MM-DD') || undefined
}
onChange={(date, dateStr) => {
this.setState({
applicationPeriod: {
Expand All @@ -229,7 +310,9 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {
<Section title="活動期" col={2}>
<Section.Description term="開始">
<DatePicker
value={writingPeriod?.start}
value={
moment(writingPeriod?.start, 'YYYY-MM-DD') || undefined
}
onChange={(date, dateStr) => {
this.setState({
writingPeriod: {
Expand All @@ -243,7 +326,9 @@ class CampaignEditor extends React.Component<DetailProps, DetailState> {

<Section.Description term="結束">
<DatePicker
value={writingPeriod?.end}
value={
moment(applicationPeriod?.end, 'YYYY-MM-DD') || undefined
}
onChange={(date, dateStr) => {
this.setState({
writingPeriod: {
Expand Down
4 changes: 4 additions & 0 deletions src/components/DateTime/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class DateTime extends React.Component<DateTimeProps> {
render() {
const { date, ...props } = this.props

if (!date) {
return <span></span>
}

return (
<span>
{timeFormat.en.render(new Date(date))} (
Expand Down
14 changes: 5 additions & 9 deletions src/pages/CampaignDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ const sharedStyles = {
}

const Cover = ({ cover }: { cover?: string }) => {
return cover ? (
<img src={cover} style={sharedStyles} />
) : (
<div style={sharedStyles}>未上傳</div>
)
return cover ? <img src={cover} style={sharedStyles} /> : <div></div>
}

class CampaignDetail extends React.Component<CampaignDetailChildProps> {
Expand Down Expand Up @@ -66,12 +62,12 @@ class CampaignDetail extends React.Component<CampaignDetailChildProps> {

<DescriptionList size="large" title="簡介" col={2}>
<Description term="報名期">
<DateTime date={campaign.applicationPeriod.start} /> ~{' '}
<DateTime date={campaign.applicationPeriod.end} />
<DateTime date={campaign.applicationPeriod?.start} /> ~{' '}
<DateTime date={campaign.applicationPeriod?.end} />
</Description>
<Description term="活動期">
<DateTime date={campaign.writingPeriod.start} /> ~{' '}
<DateTime date={campaign.writingPeriod.end} />
<DateTime date={campaign.writingPeriod?.start} /> ~{' '}
<DateTime date={campaign.writingPeriod?.end} />
</Description>

<Description term="活動公告">
Expand Down

0 comments on commit 27e2f09

Please sign in to comment.