mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Template Gallery: migration to 6.1.0
enable menu for editor redisign move frontend code to modules
This commit is contained in:
@@ -32,8 +32,18 @@ const TemplatesManager = {
|
|||||||
templateVersionId,
|
templateVersionId,
|
||||||
userId,
|
userId,
|
||||||
imageName,
|
imageName,
|
||||||
language
|
spellCheckLanguage
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
compiler = ProjectOptionsHandler.normalizeCompiler(compiler || 'pdflatex')
|
||||||
|
|
||||||
|
try {
|
||||||
|
imageName = ProjectOptionsHandler.normalizeImageName(imageName)
|
||||||
|
} catch {
|
||||||
|
logger.warn( { templateId, imageName }, 'cannot use the image required by the template, using the default image')
|
||||||
|
imageName = null
|
||||||
|
}
|
||||||
|
|
||||||
const zipUrl = `${settings.apis.filestore.url}/template/${templateId}/v/${templateVersionId}/zip`
|
const zipUrl = `${settings.apis.filestore.url}/template/${templateId}/v/${templateVersionId}/zip`
|
||||||
const zipReq = await fetchStreamWithResponse(zipUrl, {
|
const zipReq = await fetchStreamWithResponse(zipUrl, {
|
||||||
signal: AbortSignal.timeout(TIMEOUT),
|
signal: AbortSignal.timeout(TIMEOUT),
|
||||||
@@ -42,8 +52,15 @@ const TemplatesManager = {
|
|||||||
const projectName = ProjectDetailsHandler.fixProjectName(templateName)
|
const projectName = ProjectDetailsHandler.fixProjectName(templateName)
|
||||||
const dumpPath = `${settings.path.dumpFolder}/${crypto.randomUUID()}_templates-manager`
|
const dumpPath = `${settings.path.dumpFolder}/${crypto.randomUUID()}_templates-manager`
|
||||||
const writeStream = fs.createWriteStream(dumpPath)
|
const writeStream = fs.createWriteStream(dumpPath)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const attributes = {}
|
const attributes = {
|
||||||
|
compiler,
|
||||||
|
imageName,
|
||||||
|
spellCheckLanguage,
|
||||||
|
}
|
||||||
|
if (brandVariationId) attributes.brandVariationId = brandVariationId
|
||||||
|
|
||||||
await pipeline(zipReq.stream, writeStream)
|
await pipeline(zipReq.stream, writeStream)
|
||||||
|
|
||||||
if (zipReq.response.status !== 200) {
|
if (zipReq.response.status !== 200) {
|
||||||
@@ -73,13 +90,22 @@ const TemplatesManager = {
|
|||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
await TemplatesManager._setCompiler(project._id, compiler)
|
await TemplatesManager._setMainFile(project, mainFile)
|
||||||
await TemplatesManager._setImage(project._id, imageName)
|
|
||||||
await TemplatesManager._setMainFile(project._id, mainFile)
|
|
||||||
await TemplatesManager._setSpellCheckLanguage(project._id, language)
|
|
||||||
await TemplatesManager._setBrandVariationId(project._id, brandVariationId)
|
|
||||||
|
|
||||||
await prepareClsiCacheInBackground
|
const found = await prepareClsiCacheInBackground
|
||||||
|
if (found === false && project.rootDoc_id) {
|
||||||
|
ClsiCacheManager.createTemplateClsiCache({
|
||||||
|
templateVersionId,
|
||||||
|
project,
|
||||||
|
fileEntries,
|
||||||
|
docEntries,
|
||||||
|
}).catch(err => {
|
||||||
|
logger.error(
|
||||||
|
{ err, templateVersionId },
|
||||||
|
'failed to create template clsi-cache'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return project
|
return project
|
||||||
} finally {
|
} finally {
|
||||||
@@ -87,41 +113,15 @@ const TemplatesManager = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async _setCompiler(projectId, compiler) {
|
async _setMainFile(project, mainFile) {
|
||||||
if (compiler == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await ProjectOptionsHandler.setCompiler(projectId, compiler)
|
|
||||||
},
|
|
||||||
|
|
||||||
async _setImage(projectId, imageName) {
|
|
||||||
try {
|
|
||||||
await ProjectOptionsHandler.setImageName(projectId, imageName)
|
|
||||||
} catch {
|
|
||||||
logger.warn({ imageName: imageName }, 'not available')
|
|
||||||
await ProjectOptionsHandler.setImageName(projectId, settings.currentImageName)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async _setMainFile(projectId, mainFile) {
|
|
||||||
if (mainFile == null) {
|
if (mainFile == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await ProjectRootDocManager.setRootDocFromName(projectId, mainFile)
|
const rootDocId = await ProjectRootDocManager.setRootDocFromName(
|
||||||
},
|
project._id,
|
||||||
|
mainFile
|
||||||
async _setSpellCheckLanguage(projectId, language) {
|
)
|
||||||
if (language == null) {
|
if (rootDocId) project.rootDoc_id = rootDocId
|
||||||
return
|
|
||||||
}
|
|
||||||
await ProjectOptionsHandler.setSpellCheckLanguage(projectId, language)
|
|
||||||
},
|
|
||||||
|
|
||||||
async _setBrandVariationId(projectId, brandVariationId) {
|
|
||||||
if (brandVariationId == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await ProjectOptionsHandler.setBrandVariationId(projectId, brandVariationId)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchFromV1(templateId) {
|
async fetchFromV1(templateId) {
|
||||||
|
|||||||
@@ -309,6 +309,8 @@ async function initialize(webRouter, privateApiRouter, publicApiRouter) {
|
|||||||
TokenAccessRouter.apply(webRouter)
|
TokenAccessRouter.apply(webRouter)
|
||||||
HistoryRouter.apply(webRouter, privateApiRouter)
|
HistoryRouter.apply(webRouter, privateApiRouter)
|
||||||
|
|
||||||
|
await Modules.applyRouter(webRouter, privateApiRouter, publicApiRouter)
|
||||||
|
|
||||||
if (Settings.enableSubscriptions) {
|
if (Settings.enableSubscriptions) {
|
||||||
webRouter.get(
|
webRouter.get(
|
||||||
'/user/bonus',
|
'/user/bonus',
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
extends ../layout-react
|
|
||||||
|
|
||||||
block entrypointVar
|
|
||||||
- entrypoint = 'pages/template-gallery'
|
|
||||||
|
|
||||||
block vars
|
|
||||||
block vars
|
|
||||||
- const suppressNavContentLinks = true
|
|
||||||
- const suppressNavbar = true
|
|
||||||
- const suppressFooter = true
|
|
||||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
|
||||||
- isWebsiteRedesign = false
|
|
||||||
|
|
||||||
block append meta
|
|
||||||
meta(name="ol-templateCategory" data-type="string" content=category)
|
|
||||||
|
|
||||||
block content
|
|
||||||
#template-gallery-root
|
|
||||||
@@ -1041,8 +1041,18 @@ module.exports = {
|
|||||||
importProjectFromGithubModalWrapper: [],
|
importProjectFromGithubModalWrapper: [],
|
||||||
importProjectFromGithubMenu: [],
|
importProjectFromGithubMenu: [],
|
||||||
editorLeftMenuSync: [],
|
editorLeftMenuSync: [],
|
||||||
editorLeftMenuManageTemplate: ['@/features/editor-left-menu/components/actions-manage-template'],
|
editorLeftMenuManageTemplate: [
|
||||||
menubarExtraComponents: [],
|
Path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../modules/template-gallery/frontend/js/features/template/components/actions-manage-template'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
menubarExtraComponents: [
|
||||||
|
Path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../modules/template-gallery/frontend/js/features/template/components/menubar-manage-template'
|
||||||
|
),
|
||||||
|
],
|
||||||
oauth2Server: [],
|
oauth2Server: [],
|
||||||
managedGroupSubscriptionEnrollmentNotification: [],
|
managedGroupSubscriptionEnrollmentNotification: [],
|
||||||
managedGroupEnrollmentInvite: [],
|
managedGroupEnrollmentInvite: [],
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.gallery-header-sort-btn {
|
.gallery-header-sort-btn {
|
||||||
font-size: var(--font-size-02);
|
font-size: var(--font-size-02);
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
|
import Path from 'node:path'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
import logger from '@overleaf/logger'
|
import logger from '@overleaf/logger'
|
||||||
import ErrorController from '../../../../app/src/Features/Errors/ErrorController.mjs'
|
import ErrorController from '../../../../app/src/Features/Errors/ErrorController.mjs'
|
||||||
import Errors from '../../../../app/src/Features/Errors/Errors.js'
|
import Errors from '../../../../app/src/Features/Errors/Errors.js'
|
||||||
import SessionManager from '../../../../app/src/Features/Authentication/SessionManager.js'
|
import SessionManager from '../../../../app/src/Features/Authentication/SessionManager.mjs'
|
||||||
import TemplateGalleryManager from'./TemplateGalleryManager.mjs'
|
import TemplateGalleryManager from'./TemplateGalleryManager.mjs'
|
||||||
import { getUserName } from './TemplateGalleryHelper.mjs'
|
import { getUserName } from './TemplateGalleryHelper.mjs'
|
||||||
import { TemplateNameConflictError, RecompileRequiredError } from './TemplateErrors.mjs'
|
import { TemplateNameConflictError, RecompileRequiredError } from './TemplateErrors.mjs'
|
||||||
import Settings from '@overleaf/settings'
|
import Settings from '@overleaf/settings'
|
||||||
|
|
||||||
|
const __dirname = Path.dirname(fileURLToPath(import.meta.url))
|
||||||
|
|
||||||
async function createTemplateFromProject(req, res, next) {
|
async function createTemplateFromProject(req, res, next) {
|
||||||
const t = req.i18n.translate
|
const t = req.i18n.translate
|
||||||
try {
|
try {
|
||||||
@@ -108,7 +112,7 @@ async function templatesCategoryPage(req, res, next) {
|
|||||||
category = null
|
category = null
|
||||||
title = t('templates_page_title')
|
title = t('templates_page_title')
|
||||||
}
|
}
|
||||||
res.render('template_gallery/template-gallery', {
|
res.render(Path.resolve(__dirname, '../views/template_gallery/template-gallery'), {
|
||||||
title,
|
title,
|
||||||
category,
|
category,
|
||||||
})
|
})
|
||||||
@@ -121,7 +125,7 @@ async function templateDetailsPage(req, res, next) {
|
|||||||
const t = req.i18n.translate
|
const t = req.i18n.translate
|
||||||
try {
|
try {
|
||||||
const template = await TemplateGalleryManager.getTemplate('_id', req.params.template_id)
|
const template = await TemplateGalleryManager.getTemplate('_id', req.params.template_id)
|
||||||
res.render('template_gallery/template', {
|
res.render(Path.resolve(__dirname, '../views/template_gallery/template'), {
|
||||||
title: `${t('template')}: ${template.name}`,
|
title: `${t('template')}: ${template.name}`,
|
||||||
template: JSON.stringify(template),
|
template: JSON.stringify(template),
|
||||||
languages: Settings.languages,
|
languages: Settings.languages,
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import ProjectZipStreamManager from '../../../../app/src/Features/Downloads/Proj
|
|||||||
import DocumentUpdaterHandler from '../../../../app/src/Features/DocumentUpdater/DocumentUpdaterHandler.mjs'
|
import DocumentUpdaterHandler from '../../../../app/src/Features/DocumentUpdater/DocumentUpdaterHandler.mjs'
|
||||||
import ClsiManager from '../../../../app/src/Features/Compile/ClsiManager.mjs'
|
import ClsiManager from '../../../../app/src/Features/Compile/ClsiManager.mjs'
|
||||||
import CompileManager from '../../../../app/src/Features/Compile/CompileManager.mjs'
|
import CompileManager from '../../../../app/src/Features/Compile/CompileManager.mjs'
|
||||||
import UserGetter from '../../../../app/src/Features/User/UserGetter.js'
|
import UserGetter from '../../../../app/src/Features/User/UserGetter.mjs'
|
||||||
import { fetchStreamWithResponse } from '@overleaf/fetch-utils'
|
import { fetchStreamWithResponse } from '@overleaf/fetch-utils'
|
||||||
import { Template } from './models/Template.js'
|
import { Template } from './models/Template.mjs'
|
||||||
import { RecompileRequiredError } from './TemplateErrors.mjs'
|
import { RecompileRequiredError } from './TemplateErrors.mjs'
|
||||||
import { cleanHtml } from './CleanHtml.mjs'
|
import { cleanHtml } from './CleanHtml.mjs'
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import logger from '@overleaf/logger'
|
|||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
import settings from '@overleaf/settings'
|
import settings from '@overleaf/settings'
|
||||||
import { OError } from '../../../../app/src/Features/Errors/Errors.js'
|
import { OError } from '../../../../app/src/Features/Errors/Errors.js'
|
||||||
import { Template } from './models/Template.js'
|
import { Template } from './models/Template.mjs'
|
||||||
import {
|
import {
|
||||||
validateTemplateInput,
|
validateTemplateInput,
|
||||||
renderTemplateHtmlFields,
|
renderTemplateHtmlFields,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logger from '@overleaf/logger'
|
|||||||
|
|
||||||
import AuthenticationController from '../../../../app/src/Features/Authentication/AuthenticationController.mjs'
|
import AuthenticationController from '../../../../app/src/Features/Authentication/AuthenticationController.mjs'
|
||||||
import RateLimiterMiddleware from '../../../../app/src/Features/Security/RateLimiterMiddleware.mjs'
|
import RateLimiterMiddleware from '../../../../app/src/Features/Security/RateLimiterMiddleware.mjs'
|
||||||
import { RateLimiter } from '../../../../app/src/infrastructure/RateLimiter.js'
|
import { RateLimiter } from '../../../../app/src/infrastructure/RateLimiter.mjs'
|
||||||
import TemplateGalleryController from './TemplateGalleryController.mjs'
|
import TemplateGalleryController from './TemplateGalleryController.mjs'
|
||||||
|
|
||||||
const rateLimiterNewTemplate = new RateLimiter('create-template-from-project', {
|
const rateLimiterNewTemplate = new RateLimiter('create-template-from-project', {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const mongoose = require('../../../../../app/src/infrastructure/Mongoose')
|
import mongoose from '../../../../../app/src/infrastructure/Mongoose.mjs'
|
||||||
|
|
||||||
const { Schema } = mongoose
|
const { Schema } = mongoose
|
||||||
const { ObjectId } = Schema
|
const { ObjectId } = Schema
|
||||||
|
|
||||||
const TemplateSchema = new Schema(
|
export const TemplateSchema = new Schema(
|
||||||
{
|
{
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
category: { type: String, required: true },
|
category: { type: String, required: true },
|
||||||
@@ -29,5 +29,4 @@ const TemplateSchema = new Schema(
|
|||||||
{ minimize: false }
|
{ minimize: false }
|
||||||
)
|
)
|
||||||
|
|
||||||
exports.Template = mongoose.model('Template', TemplateSchema)
|
export const Template = mongoose.model('Template', TemplateSchema)
|
||||||
exports.TemplateSchema = TemplateSchema
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
extends ../../../../../app/views/layout-react
|
||||||
|
|
||||||
|
block entrypointVar
|
||||||
|
- entrypoint = 'modules/template-gallery/pages/template-gallery'
|
||||||
|
|
||||||
|
block vars
|
||||||
|
- const suppressFooter = true
|
||||||
|
- const suppressPugCookieBanner = true
|
||||||
|
- isWebsiteRedesign = true
|
||||||
|
|
||||||
|
block append meta
|
||||||
|
meta(name="ol-templateCategory" data-type="string" content=category)
|
||||||
|
|
||||||
|
block content
|
||||||
|
#template-gallery-root
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
extends ../layout-react
|
extends ../../../../../app/views/layout-react
|
||||||
|
|
||||||
block entrypointVar
|
block entrypointVar
|
||||||
- entrypoint = 'pages/template'
|
- entrypoint = 'modules/template-gallery/pages/template'
|
||||||
|
|
||||||
block vars
|
block vars
|
||||||
- const suppressNavContentLinks = true
|
|
||||||
- const suppressNavbar = true
|
- const suppressNavbar = true
|
||||||
- const suppressFooter = true
|
- const suppressFooter = true
|
||||||
- bootstrap5PageStatus = 'enabled' // One of 'disabled', 'enabled', and 'queryStringOnly'
|
- isWebsiteRedesign = true
|
||||||
- isWebsiteRedesign = false
|
|
||||||
|
|
||||||
block append meta
|
block append meta
|
||||||
meta(name="ol-template" data-type="json" content=template)
|
meta(name="ol-template" data-type="json" content=template)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { MergeAndOverride } from '../../../../../types/utils'
|
import { MergeAndOverride } from '../../../../../../../types/utils'
|
||||||
import OLForm from '@/shared/components/ol/ol-form'
|
import OLForm from '@/shared/components/ol/ol-form'
|
||||||
import OLFormControl from '@/shared/components/ol/ol-form-control'
|
import OLFormControl from '@/shared/components/ol/ol-form-control'
|
||||||
import MaterialIcon from '@/shared/components/material-icon'
|
import MaterialIcon from '@/shared/components/material-icon'
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { memo } from 'react'
|
import { memo } from 'react'
|
||||||
import { cleanHtml } from '../../../../../modules/template-gallery/app/src/CleanHtml.mjs'
|
import { cleanHtml } from '../../../../../app/src/CleanHtml.mjs'
|
||||||
|
|
||||||
function TemplateGalleryEntry({ template }) {
|
function TemplateGalleryEntry({ template }) {
|
||||||
return (
|
return (
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { TemplateGalleryProvider } from '../context/template-gallery-context'
|
import { TemplateGalleryProvider } from '../context/template-gallery-context'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
|
import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n'
|
||||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
import withErrorBoundary from '@/infrastructure/error-boundary'
|
||||||
import { GenericErrorBoundaryFallback } from '@/shared/components/generic-error-boundary-fallback'
|
import { GenericErrorBoundaryFallback } from '@/shared/components/generic-error-boundary-fallback'
|
||||||
import getMeta from '@/utils/meta'
|
import getMeta from '@/utils/meta'
|
||||||
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
|
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
|
||||||
@@ -9,8 +9,8 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { Template } from '../../../../../types/template'
|
import { Template } from '../../../../../types/template'
|
||||||
import { GetTemplatesResponseBody, Sort } from '../types/api'
|
import { GetTemplatesResponseBody, Sort } from '../types/api'
|
||||||
import getMeta from '../../../utils/meta'
|
import getMeta from '@/utils/meta'
|
||||||
import useAsync from '../../../shared/hooks/use-async'
|
import useAsync from '@/shared/hooks/use-async'
|
||||||
import { getTemplates } from '../util/api'
|
import { getTemplates } from '../util/api'
|
||||||
import sortTemplates from '../util/sort-templates'
|
import sortTemplates from '../util/sort-templates'
|
||||||
import { debugConsole } from '@/utils/debugging'
|
import { debugConsole } from '@/utils/debugging'
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTemplateGalleryContext } from '../context/template-gallery-context'
|
import { useTemplateGalleryContext } from '../context/template-gallery-context'
|
||||||
import { Sort } from '../types/api'
|
import { Sort } from '../types/api'
|
||||||
import { SortingOrder } from '../../../../../types/sorting-order'
|
import { SortingOrder } from '../../../../../../../types/sorting-order'
|
||||||
|
|
||||||
const toggleSort = (order: SortingOrder): SortingOrder => {
|
const toggleSort = (order: SortingOrder): SortingOrder => {
|
||||||
return order === 'asc' ? 'desc' : 'asc'
|
return order === 'asc' ? 'desc' : 'asc'
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SortingOrder } from '../../../../../types/sorting-order'
|
import { SortingOrder } from '../../../../../../../types/sorting-order'
|
||||||
import { Template } from '../../../../../types/template'
|
import { Template } from '../../../../../types/template'
|
||||||
|
|
||||||
export type Sort = {
|
export type Sort = {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GetTemplatesResponseBody, Sort } from '../types/api'
|
import { GetTemplatesResponseBody, Sort } from '../types/api'
|
||||||
import { getJSON } from '../../../infrastructure/fetch-json'
|
import { getJSON } from '@/infrastructure/fetch-json'
|
||||||
|
|
||||||
export function getTemplates(sortBy: Sort, category: string): Promise<GetTemplatesResponseBody> {
|
export function getTemplates(sortBy: Sort, category: string): Promise<GetTemplatesResponseBody> {
|
||||||
const queryParams = new URLSearchParams({
|
const queryParams = new URLSearchParams({
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Sort } from '../types/api'
|
import { Sort } from '../types/api'
|
||||||
import { Template } from '../../../../../types/template'
|
import { Template } from '../../../../../types/template'
|
||||||
import { SortingOrder } from '../../../../../types/sorting-order'
|
import { SortingOrder } from '../../../../../../../types/sorting-order'
|
||||||
import { Compare } from '../../../../../types/helpers/array/sort'
|
import { Compare } from '../../../../../../../types/helpers/array/sort'
|
||||||
|
|
||||||
const order = (order: SortingOrder, templates: Template[]) => {
|
const order = (order: SortingOrder, templates: Template[]) => {
|
||||||
return order === 'asc' ? [...templates] : templates.reverse()
|
return order === 'asc' ? [...templates] : templates.reverse()
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useCallback, useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
import * as eventTracking from '@/infrastructure/event-tracking'
|
||||||
import getMeta from '../../../utils/meta'
|
import getMeta from '@/utils/meta'
|
||||||
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||||
import { useDetachCompileContext } from '../../../shared/context/detach-compile-context'
|
import { useDetachCompileContext } from '@/shared/context/detach-compile-context'
|
||||||
import EditorManageTemplateModalWrapper from '../../template/components/manage-template-modal/editor-manage-template-modal-wrapper'
|
import EditorManageTemplateModalWrapper from './manage-template-modal/editor-manage-template-modal-wrapper'
|
||||||
import LeftMenuButton from './left-menu-button'
|
import LeftMenuButton from '@/features/editor-left-menu/components/left-menu-button'
|
||||||
|
|
||||||
type TemplateManageResponse = {
|
type TemplateManageResponse = {
|
||||||
template_id: string
|
template_id: string
|
||||||
@@ -31,7 +31,7 @@ export default function ActionsManageTemplate() {
|
|||||||
({ template_id: templateId }: TemplateManageResponse) => {
|
({ template_id: templateId }: TemplateManageResponse) => {
|
||||||
location.assign(`/template/${templateId}`)
|
location.assign(`/template/${templateId}`)
|
||||||
},
|
},
|
||||||
[location]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { useCallback, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import getMeta from '@/utils/meta'
|
||||||
|
import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
|
||||||
|
import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
|
||||||
|
import EditorManageTemplateModalWrapper from './manage-template-modal/editor-manage-template-modal-wrapper'
|
||||||
|
|
||||||
|
type TemplateManageResponse = {
|
||||||
|
template_id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const MenubarManageTemplate = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { pdfUrl } = useCompileContext()
|
||||||
|
|
||||||
|
const [showManageTemplateModal, setShowManageTemplateModal] = useState(false)
|
||||||
|
|
||||||
|
const publishAsTemplateEnabled =
|
||||||
|
getMeta('ol-showTemplatesServerPro') && pdfUrl
|
||||||
|
|
||||||
|
useCommandProvider(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
type: 'command',
|
||||||
|
id: 'manage-template',
|
||||||
|
label: t('publish_as_template'),
|
||||||
|
disabled: !publishAsTemplateEnabled,
|
||||||
|
handler: () => {
|
||||||
|
setShowManageTemplateModal(true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t, publishAsTemplateEnabled]
|
||||||
|
)
|
||||||
|
|
||||||
|
const openTemplate = useCallback(
|
||||||
|
({ template_id: templateId }: TemplateManageResponse) => {
|
||||||
|
location.assign(`/template/${templateId}`)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditorManageTemplateModalWrapper
|
||||||
|
show={showManageTemplateModal}
|
||||||
|
handleHide={() => setShowManageTemplateModal(false)}
|
||||||
|
openTemplate={openTemplate}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenubarManageTemplate
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import getMeta from '../../../../utils/meta'
|
import getMeta from '@/utils/meta'
|
||||||
import SettingsMenuSelect from './settings-menu-select'
|
import SettingsMenuSelect from './settings-menu-select'
|
||||||
import type { Optgroup } from './settings-menu-select'
|
import type { Optgroup } from './settings-menu-select'
|
||||||
|
|
||||||
@@ -3,8 +3,8 @@ import getMeta from '@/utils/meta'
|
|||||||
import OLCol from '@/shared/components/ol/ol-col'
|
import OLCol from '@/shared/components/ol/ol-col'
|
||||||
import OLRow from '@/shared/components/ol/ol-row'
|
import OLRow from '@/shared/components/ol/ol-row'
|
||||||
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||||
import { formatDate, fromNowDate } from '../../../utils/dates'
|
import { formatDate, fromNowDate } from '@/utils/dates'
|
||||||
import { cleanHtml } from '../../../../../modules/template-gallery/app/src/CleanHtml.mjs'
|
import { cleanHtml } from '../../../../../app/src/CleanHtml.mjs'
|
||||||
import { useTemplateContext } from '../context/template-context'
|
import { useTemplateContext } from '../context/template-context'
|
||||||
import DeleteTemplateButton from './delete-template-button'
|
import DeleteTemplateButton from './delete-template-button'
|
||||||
import EditTemplateButton from './edit-template-button'
|
import EditTemplateButton from './edit-template-button'
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import useWaitForI18n from '../../../shared/hooks/use-wait-for-i18n'
|
import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n'
|
||||||
import withErrorBoundary from '../../../infrastructure/error-boundary'
|
import withErrorBoundary from '@/infrastructure/error-boundary'
|
||||||
import { GenericErrorBoundaryFallback } from '@/shared/components/generic-error-boundary-fallback'
|
import { GenericErrorBoundaryFallback } from '@/shared/components/generic-error-boundary-fallback'
|
||||||
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
|
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
|
||||||
import Footer from '@/shared/components/footer/footer'
|
import Footer from '@/shared/components/footer/footer'
|
||||||
@@ -1,10 +1,3 @@
|
|||||||
import './../utils/meta'
|
|
||||||
import '../utils/webpack-public-path'
|
|
||||||
import './../infrastructure/error-reporter'
|
|
||||||
import '@/i18n'
|
|
||||||
import '../features/event-tracking'
|
|
||||||
import '../features/cookie-banner'
|
|
||||||
import '../features/link-helpers/slow-link'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import TemplateGalleryRoot from '../features/template-gallery/components/template-gallery-root'
|
import TemplateGalleryRoot from '../features/template-gallery/components/template-gallery-root'
|
||||||
|
|
||||||
@@ -1,10 +1,3 @@
|
|||||||
import './../utils/meta'
|
|
||||||
import '../utils/webpack-public-path'
|
|
||||||
import './../infrastructure/error-reporter'
|
|
||||||
import '@/i18n'
|
|
||||||
import '../features/event-tracking'
|
|
||||||
import '../features/cookie-banner'
|
|
||||||
import '../features/link-helpers/slow-link'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import TemplateRoot from '../features/template/components/template-root'
|
import TemplateRoot from '../features/template/components/template-root'
|
||||||
|
|
||||||
Reference in New Issue
Block a user