adding web changes of Export HTML (#34117)
GitOrigin-RevId: 804c576faefebfc6683a0363b45372e66a43d8fc
This commit is contained in:
@@ -19,6 +19,7 @@ const { z, zz, parseReq } = Validation
|
||||
const SUPPORTED_CONVERSION_TYPES = new Map([
|
||||
['docx', 'docx'],
|
||||
['markdown', 'zip'],
|
||||
['html', 'zip'],
|
||||
])
|
||||
|
||||
const exportProjectConversionSchema = z.object({
|
||||
|
||||
@@ -483,6 +483,7 @@ const _ProjectController = {
|
||||
'export-docx',
|
||||
'sharing-updates',
|
||||
'export-markdown',
|
||||
'export-html',
|
||||
'command-palette',
|
||||
'overleaf-library',
|
||||
'compile-timeout-cta',
|
||||
|
||||
@@ -654,6 +654,7 @@
|
||||
"expires_on": "",
|
||||
"explore_plans": "",
|
||||
"export_as_docx": "",
|
||||
"export_as_html": "",
|
||||
"export_as_markdown": "",
|
||||
"export_csv": "",
|
||||
"export_project_to_github": "",
|
||||
@@ -916,6 +917,7 @@
|
||||
"how_to_insert_images": "",
|
||||
"how_we_use_your_data": "",
|
||||
"how_we_use_your_data_explanation": "",
|
||||
"html_export_feedback_message": "",
|
||||
"i_confirm_am_student": "",
|
||||
"i_want_to_add_a_po_number": "",
|
||||
"i_want_to_stay": "",
|
||||
|
||||
+17
-1
@@ -71,6 +71,20 @@ const ExportDocumentSuccessToast = ({ data }: { data?: any }) => {
|
||||
]}
|
||||
/>
|
||||
)
|
||||
} else if (type === 'html') {
|
||||
return (
|
||||
<Trans
|
||||
i18nKey="html_export_feedback_message"
|
||||
components={[
|
||||
// eslint-disable-next-line react/jsx-key, jsx-a11y/anchor-has-content
|
||||
<a
|
||||
href="https://forms.gle/nBUVGqPYwLcWHSmt5"
|
||||
target="_BLANK"
|
||||
rel="noopener noreferrer"
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Trans
|
||||
@@ -160,7 +174,9 @@ export const hidePreparingExportToast = (handle: string) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const showExportDocumentSuccess = (type: 'docx' | 'markdown') => {
|
||||
export const showExportDocumentSuccess = (
|
||||
type: 'docx' | 'markdown' | 'html'
|
||||
) => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('ide:show-toast', {
|
||||
detail: { key: 'export-document:success', type },
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { useEditorManagerContext } from '@/features/ide-react/context/editor-man
|
||||
|
||||
type ExportProjectWithConversionProps = {
|
||||
featureFlag?: string
|
||||
conversionType: 'docx' | 'markdown'
|
||||
conversionType: 'docx' | 'markdown' | 'html'
|
||||
label: string
|
||||
menuBarId: string
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ export const ToolbarMenuBar = () => {
|
||||
'download-pdf',
|
||||
'export-as-docx',
|
||||
'export-as-markdown',
|
||||
'export-as-html',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -89,6 +89,12 @@ export const ToolbarProjectTitle = () => {
|
||||
label={t('export_as_markdown')}
|
||||
menuBarId="export-as-markdown"
|
||||
/>
|
||||
<ExportProjectWithConversionButton
|
||||
featureFlag="export-html"
|
||||
conversionType="html"
|
||||
label={t('export_as_html')}
|
||||
menuBarId="export-as-html"
|
||||
/>
|
||||
<DropdownDivider />
|
||||
<DuplicateProject />
|
||||
<OLDropdownMenuItem
|
||||
|
||||
@@ -16,7 +16,7 @@ import { OpenDocuments } from '../editor/open-documents'
|
||||
const SLOW_CONVERSION_THRESHOLD = 2000
|
||||
|
||||
export default function useConvertProject(
|
||||
type: 'docx' | 'markdown',
|
||||
type: 'docx' | 'markdown' | 'html',
|
||||
openDocs: OpenDocuments,
|
||||
getRootDocInfo: () => RootDocInfo
|
||||
) {
|
||||
|
||||
@@ -859,6 +859,7 @@
|
||||
"explore_all_plans": "Explore all plans",
|
||||
"explore_plans": "Explore plans",
|
||||
"export_as_docx": "Export as Word document (.docx)",
|
||||
"export_as_html": "Export as HTML (.html)",
|
||||
"export_as_markdown": "Export as Markdown (.md)",
|
||||
"export_csv": "Export CSV",
|
||||
"export_project_to_github": "Export Project to GitHub",
|
||||
@@ -1181,6 +1182,7 @@
|
||||
"how_to_insert_images": "How to insert images",
|
||||
"how_we_use_your_data": "How we use your data",
|
||||
"how_we_use_your_data_explanation": "<0>Please help us continue to improve Overleaf by answering a few quick questions. Your answers will help us and our corporate group understand more about our user base. We may use this information to improve your Overleaf experience, for example by providing personalized onboarding, upgrade prompts, help suggestions, and tailored marketing communications (if you’ve opted-in to receive them).</0><1>For more details on how we use your personal data, please see our <0>Privacy Notice</0>.</1>",
|
||||
"html_export_feedback_message": "Exporting as HTML is a new feature. <0>Let us know what you think</0>",
|
||||
"hundreds_templates_info": "Produce beautiful documents starting from our gallery of LaTeX templates for journals, conferences, theses, reports, CVs and much more.",
|
||||
"i_confirm_am_student": "I confirm that I am currently a student.",
|
||||
"i_want_to_add_a_po_number": "I want to add a PO number",
|
||||
|
||||
@@ -541,6 +541,81 @@ describe('ProjectDownloadsController', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('with type=html', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.projectId = '5e9b1c2a3b4c5d6e7f8a9b0c'
|
||||
ctx.userId = 'test-user-id'
|
||||
ctx.projectName = 'My Test Project'
|
||||
ctx.exportStream = { pipe: sinon.stub() }
|
||||
ctx.contentLength = 9876
|
||||
|
||||
ctx.req.params = { Project_id: ctx.projectId, type: 'html' }
|
||||
ctx.req.session = { user: { _id: ctx.userId } }
|
||||
ctx.req.query = {}
|
||||
ctx.req.ip = '192.168.1.1'
|
||||
|
||||
ctx.res.attachment = sinon.stub().returns(ctx.res)
|
||||
|
||||
ctx.SessionManager.getLoggedInUserId.returns(ctx.userId)
|
||||
ctx.ProjectGetter.promises.getProject.resolves({
|
||||
name: ctx.projectName,
|
||||
})
|
||||
ctx.DocumentConversionManager.promises.convertProjectToDocument.resolves(
|
||||
{
|
||||
conversionId: '12345678-1234-4234-8234-123456789012',
|
||||
buildId: '0123456789a-0123456789abcdef',
|
||||
clsiServerId: 'clsi-server-1',
|
||||
file: 'output.zip',
|
||||
}
|
||||
)
|
||||
ctx.DocumentConversionManager.promises.streamConvertedProjectDocument.resolves(
|
||||
{
|
||||
stream: ctx.exportStream,
|
||||
contentLength: ctx.contentLength,
|
||||
}
|
||||
)
|
||||
|
||||
await ctx.ProjectDownloadsController.exportProjectConversion(
|
||||
ctx.req,
|
||||
ctx.res,
|
||||
ctx.next
|
||||
)
|
||||
})
|
||||
|
||||
it('should call convertProjectToDocument with the html type', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.DocumentConversionManager.promises.convertProjectToDocument,
|
||||
ctx.projectId,
|
||||
ctx.userId,
|
||||
'html'
|
||||
)
|
||||
})
|
||||
|
||||
it('should set the attachment filename with .zip extension', function (ctx) {
|
||||
sinon.assert.calledWith(ctx.res.attachment, 'My_Test_Project.zip')
|
||||
})
|
||||
|
||||
it('should add an audit log entry for html export', function (ctx) {
|
||||
sinon.assert.calledWith(
|
||||
ctx.ProjectAuditLogHandler.addEntryInBackground,
|
||||
ctx.projectId,
|
||||
'project-exported-html',
|
||||
ctx.userId,
|
||||
ctx.req.ip
|
||||
)
|
||||
})
|
||||
|
||||
it('should record the action via Metrics with html type', function (ctx) {
|
||||
ctx.Metrics.inc
|
||||
.calledWith('document-exports', 1, { type: 'html' })
|
||||
.should.equal(true)
|
||||
})
|
||||
|
||||
it('should stream the document to the response', function (ctx) {
|
||||
sinon.assert.calledWith(ctx.pipeline, ctx.exportStream, ctx.res)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when conversion fails with a DocumentConversionError', function () {
|
||||
beforeEach(async function (ctx) {
|
||||
ctx.projectId = '5e9b1c2a3b4c5d6e7f8a9b0c'
|
||||
|
||||
Reference in New Issue
Block a user