Skip to content

Commit

Permalink
Add editor page
Browse files Browse the repository at this point in the history
  • Loading branch information
mruwnik committed Jul 9, 2024
1 parent bf3c1d5 commit f0c2d19
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
117 changes: 117 additions & 0 deletions app/routes/editors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import {useState} from 'react'
import Page from '~/components/Page'
import Button from '~/components/Button'
import '~/components/Chatbot/widgit.css'
import {Question} from '~/server-utils/stampy'
import {downloadZip} from 'client-zip'
import {fetchAllQuestionsOnSite} from './questions.allQuestionsOnSite'

const SINGLE_FILE_HTML = 'singleFileHtml'
const SINGLE_FILE_MARKDOWN = 'singleFileMarkdown'
const MULTI_FILE_HTML = 'multipleFilesMarkdown'
const MULTI_FILE_MARKDOWN = 'multipleFileHtml'

const downloadOptions = {
[SINGLE_FILE_HTML]: 'Single HTML file',
[MULTI_FILE_HTML]: 'Multiple HTML files',
[SINGLE_FILE_MARKDOWN]: 'Single markdown file',
[MULTI_FILE_MARKDOWN]: 'Multiple markdown files',
}

const makeZipFile = async (questions: Question[], extention: string) =>
downloadZip(
questions.map((q) => ({
name: `${q.title}.${extention}`,
lastModified: q.updatedAt,
input: (extention === 'md' ? q.markdown : q.text) || '',
}))
).blob()

const downloadBlob = async (filename: string, blob: Blob) => {
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
link.click()
link.remove()
}

const makeFilename = (selectedOption: string) => {
switch (selectedOption) {
case SINGLE_FILE_HTML:
return 'questions.html'
case SINGLE_FILE_MARKDOWN:
return 'questions.md'
case MULTI_FILE_HTML:
case MULTI_FILE_MARKDOWN:
return 'questions.zip'
default:
return 'questions'
}
}

const toHtmlChunk = ({title, text}: Question) =>
[
' <div>',
` <h2>${title}</h2>`,
` <div>${text}</div>`,
' </div>',
].join('\n')

const toMarkdownChunk = ({title, markdown}: Question) => `# ${title}\n\n${markdown}`

const htmlFile = (contents: string) => {
const html = ['<!DOCTYPE html>', '<html>', ' <body>', contents, ' </body>', '/html>'].join(
'\n'
)
return new Blob([html], {type: 'text/html'})
}

const getData = async (questions: Question[], selectedOption: string) => {
switch (selectedOption) {
case SINGLE_FILE_HTML:
return htmlFile(questions.map(toHtmlChunk).join('\n\n\n'))
case MULTI_FILE_HTML:
return makeZipFile(questions, 'html')
case SINGLE_FILE_MARKDOWN:
return new Blob([questions.map(toMarkdownChunk).join('\n\n\n')], {type: 'text/markdown'})
case MULTI_FILE_MARKDOWN:
return makeZipFile(questions, 'md')
}
}

const DownloadQuestions = () => {
const [selectedOption, setSelectedOption] = useState(SINGLE_FILE_HTML)

const download = async () => {
const {data} = await fetchAllQuestionsOnSite()
const blob = await getData(data, selectedOption)
blob && (await downloadBlob(makeFilename(selectedOption), blob))
}
return (
<div className="page-body full-height padding-top-32">
<h4>Download all questions</h4>
{Object.entries(downloadOptions).map(([id, label]) => (
<div key={id}>
<input
type="radio"
id={id}
checked={id === selectedOption}
name="download-format"
value={id}
onChange={(e) => setSelectedOption(e.target.id)}
/>
<label htmlFor={id}>{label}</label>
</div>
))}
<Button action={download}>Download</Button>
</div>
)
}

export default function EditorHelpers() {
return (
<Page noFooter>
<DownloadQuestions />
</Page>
)
}
File renamed without changes.
2 changes: 2 additions & 0 deletions app/server-utils/stampy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type Question = {
title: string
pageid: string
text: string | null
markdown: string | null
answerEditLink: string | null
relatedQuestions: RelatedQuestion[]
questionState?: QuestionState
Expand Down Expand Up @@ -288,6 +289,7 @@ const convertToQuestion = ({name, values, updatedAt} = {} as AnswersRow): Questi
title: name,
pageid: extractText(values['UI ID']),
text: renderText(extractText(values['UI ID']), values['Rich Text']),
markdown: extractText(values['Rich Text']),
answerEditLink: extractLink(values['Edit Answer']).replace(/\?.*$/, ''),
tags: extractJoined(values['Tags'] || [], allTags).map((t) => t.name),
banners: extractJoined(values['Banners'] || [], allBanners),
Expand Down
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@remix-run/cloudflare-workers": "^2.6.0",
"@remix-run/css-bundle": "^1.19.3",
"@remix-run/react": "^2.6.0",
"client-zip": "^2.4.5",
"copy-to-clipboard": "^3.3.3",
"isbot": "^4",
"lodash": "^4.17.21",
Expand Down

0 comments on commit f0c2d19

Please sign in to comment.