2022-10-23 19:52:32 +02:00
|
|
|
import Worker from 'web-worker'
|
2022-08-24 12:07:08 -05:00
|
|
|
import fileSaver from 'file-saver'
|
2022-08-29 08:29:55 +02:00
|
|
|
import { themePlugin } from '@freesewing/plugin-theme'
|
2023-03-09 08:59:03 -06:00
|
|
|
import { pluginI18n } from '@freesewing/plugin-i18n'
|
2023-03-15 12:48:46 -05:00
|
|
|
import { pagesPlugin, fabricPlugin } from '../layout/plugin-layout-part.mjs'
|
|
|
|
import { pluginCutlist } from '@freesewing/plugin-cutlist'
|
|
|
|
import { cutLayoutPlugin } from '../layout/cut/plugin-cut-layout.mjs'
|
|
|
|
import { fabricSettingsOrDefault } from '../layout/cut/index.mjs'
|
|
|
|
import { useFabricLength } from '../layout/cut/settings.mjs'
|
|
|
|
import { capitalize, formatFraction128, formatMm } from 'shared/utils.mjs'
|
|
|
|
import get from 'lodash.get'
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
export const exportTypes = {
|
|
|
|
exportForPrinting: ['a4', 'a3', 'a2', 'a1', 'a0', 'letter', 'tabloid'],
|
|
|
|
exportForEditing: ['svg', 'pdf'],
|
|
|
|
exportAsData: ['json', 'yaml', 'github gist'],
|
|
|
|
}
|
|
|
|
|
|
|
|
export const defaultPdfSettings = {
|
|
|
|
size: 'a4',
|
|
|
|
orientation: 'portrait',
|
|
|
|
margin: 10,
|
2022-10-23 19:52:32 +02:00
|
|
|
coverPage: true,
|
2023-03-15 12:48:46 -05:00
|
|
|
cutlist: true,
|
2022-08-24 12:07:08 -05:00
|
|
|
}
|
|
|
|
|
2023-03-15 12:48:46 -05:00
|
|
|
const themedPattern = (design, gist, overwrite, format, t) => {
|
|
|
|
const pattern = new design({ ...gist, ...overwrite })
|
|
|
|
|
|
|
|
// add the theme and translation to the pattern
|
|
|
|
pattern.use(themePlugin, { stripped: format !== 'svg', skipGrid: ['pages'] })
|
|
|
|
pattern.use(pluginI18n, { t })
|
|
|
|
pattern.use(pluginCutlist)
|
|
|
|
|
|
|
|
return pattern
|
|
|
|
}
|
|
|
|
const generateCutLayouts = (pattern, design, gist, format, t) => {
|
|
|
|
const fabrics = pattern.setStores[pattern.activeSet].cutlist.getCutFabrics(
|
|
|
|
pattern.settings[0]
|
|
|
|
) || ['fabric']
|
|
|
|
if (!fabrics.length) return
|
|
|
|
|
|
|
|
const isImperial = gist.units === 'imperial'
|
|
|
|
const cutLayouts = {}
|
|
|
|
fabrics.forEach((f) => {
|
|
|
|
const fabricSettings = fabricSettingsOrDefault(gist, f)
|
|
|
|
const fabricLayout = get(gist, ['layouts', 'cuttingLayout', f], true)
|
|
|
|
const fabricPattern = themedPattern(design, gist, { layout: fabricLayout }, format, t)
|
|
|
|
.use(cutLayoutPlugin(f, fabricSettings.grainDirection))
|
|
|
|
.use(fabricPlugin({ ...fabricSettings, printStyle: true, setPatternSize: 'width' }))
|
|
|
|
|
|
|
|
fabricPattern.draft()
|
|
|
|
const svg = fabricPattern.render()
|
|
|
|
cutLayouts[f] = {
|
|
|
|
svg,
|
|
|
|
title: t('plugin:' + f),
|
|
|
|
dimensions: t('plugin:fabricSize', {
|
|
|
|
width: formatMm(fabricSettings.sheetWidth, gist.units, 'notags'),
|
|
|
|
length: useFabricLength(isImperial, fabricPattern.height, 'notags'),
|
|
|
|
interpolation: { escapeValue: false },
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return cutLayouts
|
|
|
|
}
|
2022-08-24 12:07:08 -05:00
|
|
|
/**
|
|
|
|
* Handle exporting the draft or gist
|
|
|
|
* format: format to export to
|
|
|
|
* gist: the gist
|
|
|
|
* design: the pattern constructor for the design to be exported
|
|
|
|
* t: a translation function to attach to the draft
|
|
|
|
* app: an app instance
|
|
|
|
* onComplete: business to perform after a successful export
|
|
|
|
* onError: business to perform on error
|
|
|
|
* */
|
2022-10-23 19:52:32 +02:00
|
|
|
export const handleExport = async (format, gist, design, t, app, onComplete, onError) => {
|
2022-08-24 12:07:08 -05:00
|
|
|
// start the loading indicator
|
2022-10-23 19:52:32 +02:00
|
|
|
app.startLoading()
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// get a worker going
|
2022-11-14 16:53:31 -06:00
|
|
|
const worker = new Worker(new URL('./export-worker.js', import.meta.url), { type: 'module' })
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// listen for the worker's message back
|
2022-10-23 19:52:32 +02:00
|
|
|
worker.addEventListener('message', (e) => {
|
2022-08-24 12:07:08 -05:00
|
|
|
// on success
|
|
|
|
if (e.data.success) {
|
|
|
|
// save it out
|
|
|
|
if (e.data.blob) {
|
|
|
|
const fileType = exportTypes.exportForPrinting.indexOf(format) === -1 ? format : 'pdf'
|
|
|
|
fileSaver.saveAs(e.data.blob, `freesewing-${gist.design || 'gist'}.${fileType}`)
|
|
|
|
}
|
|
|
|
// do additional business
|
|
|
|
onComplete && onComplete(e)
|
|
|
|
}
|
|
|
|
// on error
|
|
|
|
else {
|
|
|
|
console.log(e.data.error)
|
|
|
|
onError && onError(e)
|
|
|
|
}
|
|
|
|
|
|
|
|
// stop the loader
|
|
|
|
app.stopLoading()
|
|
|
|
})
|
|
|
|
|
|
|
|
// pdf settings
|
|
|
|
const settings = {
|
|
|
|
...defaultPdfSettings,
|
2022-10-23 19:52:32 +02:00
|
|
|
...(gist._state.layout?.forPrinting?.page || {}),
|
2022-08-24 12:07:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// arguments to pass to the worker
|
2022-10-23 19:52:32 +02:00
|
|
|
const workerArgs = { format, gist, settings }
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// data passed to the worker must be JSON serializable, so we can't pass functions or prototypes
|
|
|
|
// that means if it's not a data export there's more work to do before we can hand off to the worker
|
|
|
|
if (exportTypes.exportAsData.indexOf(format) === -1) {
|
2022-10-23 19:52:32 +02:00
|
|
|
gist.embed = false
|
2022-08-24 12:07:08 -05:00
|
|
|
// make a pattern instance for export rendering
|
|
|
|
const layout = gist.layouts?.printingLayout || gist.layout || true
|
2023-03-15 12:48:46 -05:00
|
|
|
let pattern = themedPattern(design, gist, { layout }, format, t)
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// a specified size should override the gist one
|
|
|
|
if (format !== 'pdf') {
|
|
|
|
settings.size = format
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
// add pages to pdf exports
|
|
|
|
if (format !== 'svg') {
|
2022-10-23 19:52:32 +02:00
|
|
|
pattern.use(
|
|
|
|
pagesPlugin({
|
|
|
|
...settings,
|
|
|
|
printStyle: true,
|
|
|
|
renderBlanks: false,
|
|
|
|
setPatternSize: true,
|
|
|
|
})
|
|
|
|
)
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// add the strings that are used on the cover page
|
|
|
|
workerArgs.strings = {
|
2022-11-14 14:02:11 -06:00
|
|
|
design: capitalize(pattern.designConfig.data.name.replace('@freesewing/', '')),
|
2022-08-24 12:07:08 -05:00
|
|
|
tagline: t('common:sloganCome') + '. ' + t('common:sloganStay'),
|
2022-10-23 19:52:32 +02:00
|
|
|
url: window.location.href,
|
2023-03-15 12:48:46 -05:00
|
|
|
cuttingLayout: t('plugin:cuttingLayout'),
|
2022-08-24 12:07:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// draft and render the pattern
|
2022-10-23 19:52:32 +02:00
|
|
|
pattern.draft()
|
2022-11-14 14:02:11 -06:00
|
|
|
workerArgs.svg = pattern.render()
|
2022-08-24 12:07:08 -05:00
|
|
|
|
|
|
|
// add the svg and pages data to the worker args
|
2022-11-14 14:02:11 -06:00
|
|
|
workerArgs.pages = pattern.setStores[pattern.activeSet].get('pages')
|
2022-12-13 11:55:50 -06:00
|
|
|
|
2023-03-15 12:48:46 -05:00
|
|
|
// add cutting layouts if requested
|
|
|
|
if (format !== 'svg' && settings.cutlist) {
|
|
|
|
workerArgs.cutLayouts = generateCutLayouts(pattern, design, gist, format, t)
|
|
|
|
}
|
|
|
|
|
2022-12-13 11:55:50 -06:00
|
|
|
// post a message to the worker with all needed data
|
|
|
|
worker.postMessage(workerArgs)
|
2022-10-23 19:52:32 +02:00
|
|
|
} catch (err) {
|
2022-08-24 12:07:08 -05:00
|
|
|
console.log(err)
|
2022-10-23 19:52:32 +02:00
|
|
|
app.stopLoading()
|
2022-08-24 12:07:08 -05:00
|
|
|
onError && onError(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|