add cutting instructions to title. ensure translation on drafts
This commit is contained in:
parent
6f6b3a2b8a
commit
bf51065cc8
11 changed files with 88 additions and 66 deletions
|
@ -182,13 +182,6 @@ function draftCarltonCollar({
|
||||||
paths.seam = paths.saBase.clone().line(points.standTop).close().attr('class', 'fabric')
|
paths.seam = paths.saBase.clone().line(points.standTop).close().attr('class', 'fabric')
|
||||||
|
|
||||||
if (complete) {
|
if (complete) {
|
||||||
points.title = points.standTopCp.clone()
|
|
||||||
macro('title', {
|
|
||||||
at: points.title,
|
|
||||||
nr: 8,
|
|
||||||
title: 'collar',
|
|
||||||
})
|
|
||||||
|
|
||||||
// Remove grainline from collarstand part
|
// Remove grainline from collarstand part
|
||||||
delete paths.grainline
|
delete paths.grainline
|
||||||
macro('cutonfold', {
|
macro('cutonfold', {
|
||||||
|
@ -204,6 +197,13 @@ function draftCarltonCollar({
|
||||||
addCut(2, 'lining')
|
addCut(2, 'lining')
|
||||||
setCutOnFold(false, undefined, 'lining')
|
setCutOnFold(false, undefined, 'lining')
|
||||||
setGrain(defaultGrain + 45, 'lining')
|
setGrain(defaultGrain + 45, 'lining')
|
||||||
|
|
||||||
|
points.title = points.standTopCp.clone()
|
||||||
|
macro('title', {
|
||||||
|
at: points.title,
|
||||||
|
nr: 8,
|
||||||
|
title: 'collar',
|
||||||
|
})
|
||||||
if (sa) {
|
if (sa) {
|
||||||
paths.sa = paths.saBase.offset(sa)
|
paths.sa = paths.saBase.offset(sa)
|
||||||
paths.sa = paths.sa
|
paths.sa = paths.sa
|
||||||
|
|
|
@ -9,6 +9,7 @@ import cutonfold from './plugins/cutonfold.yaml'
|
||||||
import grainline from './plugins/grainline.yaml'
|
import grainline from './plugins/grainline.yaml'
|
||||||
import scalebox from './plugins/scalebox.yaml'
|
import scalebox from './plugins/scalebox.yaml'
|
||||||
import title from './plugins/title.yaml'
|
import title from './plugins/title.yaml'
|
||||||
|
import cutlist from './plugins/cutlist/yaml'
|
||||||
|
|
||||||
const files = {
|
const files = {
|
||||||
brian,
|
brian,
|
||||||
|
@ -22,6 +23,7 @@ const files = {
|
||||||
grainline,
|
grainline,
|
||||||
scalebox,
|
scalebox,
|
||||||
title,
|
title,
|
||||||
|
cutlist,
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages = {}
|
const messages = {}
|
||||||
|
|
7
packages/i18n/src/locales/en/plugin/plugins/cutlist.yaml
Normal file
7
packages/i18n/src/locales/en/plugin/plugins/cutlist.yaml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
lmhCanvas: Light to Medium Hair Canvas
|
||||||
|
fabric: Main Fabric
|
||||||
|
lining: Lining
|
||||||
|
cut: Cut
|
||||||
|
paired: paired
|
||||||
|
onFoldLower: on the fold
|
||||||
|
onBias: on the bias
|
|
@ -9,6 +9,7 @@ export const plugin = {
|
||||||
['removeCut', removeCut],
|
['removeCut', removeCut],
|
||||||
['setGrain', setGrain],
|
['setGrain', setGrain],
|
||||||
['setCutOnFold', setCutOnFold],
|
['setCutOnFold', setCutOnFold],
|
||||||
|
['getCutOnFold', getCutOnFold],
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,3 +72,10 @@ function setCutOnFold(store, partName, p1, p2, material = false) {
|
||||||
|
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCutOnFold(store, partName, material = false) {
|
||||||
|
if (!material) return store.get(['cutlist', partName, 'cutOnFold'])
|
||||||
|
|
||||||
|
const matFold = store.get(['cutlist', partName, 'materials', material, 'cutOnFold'])
|
||||||
|
return matFold === undefined ? store.get(['cutlist', partName, 'cutOnFold']) : matFold
|
||||||
|
}
|
||||||
|
|
|
@ -31,20 +31,17 @@ export const plugin = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
macros: {
|
macros: {
|
||||||
title: function (so, { points, scale, locale, store }) {
|
title: function (so, { points, scale, locale, store, part, getCutOnFold }) {
|
||||||
const prefix = so.prefix || ''
|
const prefix = so.prefix || ''
|
||||||
|
let overwrite = !so.append
|
||||||
|
|
||||||
// Passing `false` will remove the title
|
// Passing `false` will remove the title
|
||||||
if (so === false) {
|
if (so === false || overwrite) {
|
||||||
for (const id of [
|
Object.keys(points).forEach((p) => {
|
||||||
`_${prefix}_titleNr`,
|
if (p.startsWith(`_${prefix}_title`) || p === `_${prefix}_exportDate`) delete points[p]
|
||||||
`_${prefix}_titleName`,
|
})
|
||||||
`_${prefix}_titlePattern`,
|
|
||||||
`_${prefix}_titleFor`,
|
if (so === false) return true
|
||||||
`_${prefix}_exportDate`,
|
|
||||||
])
|
|
||||||
delete points[id]
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const transform = function (anchor) {
|
const transform = function (anchor) {
|
||||||
|
@ -53,44 +50,55 @@ export const plugin = {
|
||||||
|
|
||||||
return `matrix(${so.scale}, 0, 0, ${so.scale}, ${cx}, ${cy}) rotate(${so.rotation} ${anchor.x} ${anchor.y})`
|
return `matrix(${so.scale}, 0, 0, ${so.scale}, ${cx}, ${cy}) rotate(${so.rotation} ${anchor.x} ${anchor.y})`
|
||||||
}
|
}
|
||||||
|
let shift = 8
|
||||||
|
const nextPoint = (text, textClass, shiftAmt = shift) => {
|
||||||
|
const newPoint = so.at.shift(-90 - so.rotation, shiftAmt * so.scale)
|
||||||
|
newPoint.attr('data-text-transform', transform(newPoint)).addText(text, textClass)
|
||||||
|
return newPoint
|
||||||
|
}
|
||||||
const defaults = {
|
const defaults = {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
|
cutlist: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
so = { ...defaults, ...so }
|
so = { ...defaults, ...so }
|
||||||
so.scale = so.scale * scale
|
so.scale = so.scale * scale
|
||||||
let overwrite = true
|
|
||||||
if (so.append) overwrite = false
|
|
||||||
points[`_${prefix}_titleNr`] = so.at
|
points[`_${prefix}_titleNr`] = so.at
|
||||||
.clone()
|
.clone()
|
||||||
.attr('data-text', so.nr, overwrite)
|
.attr('data-text', so.nr, overwrite)
|
||||||
.attr('data-text-class', 'text-4xl fill-note font-bold')
|
.attr('data-text-class', 'text-4xl fill-note font-bold')
|
||||||
.attr('data-text-transform', transform(so.at))
|
.attr('data-text-transform', transform(so.at))
|
||||||
let shift = 8
|
|
||||||
if (so.title) {
|
if (so.title) {
|
||||||
points[`_${prefix}_titleName`] = so.at
|
points[`_${prefix}_titleName`] = nextPoint(so.title, 'text-lg fill-current font-bold')
|
||||||
.shift(-90 - so.rotation, shift * so.scale)
|
|
||||||
.attr('data-text', so.title)
|
|
||||||
.attr('data-text-class', 'text-lg fill-current font-bold')
|
|
||||||
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, 13 * so.scale)))
|
|
||||||
shift += 8
|
shift += 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const partCutlist = store.get(['cutlist', part.name])
|
||||||
|
if (so.cutlist && partCutlist?.materials) {
|
||||||
|
for (const material in partCutlist.materials) {
|
||||||
|
const matCut = partCutlist.materials[material]
|
||||||
|
const cutPoint = nextPoint('plugin:cut', 'text-md fill-current')
|
||||||
|
cutPoint.addText(matCut.cut)
|
||||||
|
if (!matCut.indentical && matCut.cut > 1) cutPoint.addText('plugin:paired')
|
||||||
|
if (typeof getCutOnFold(material) === 'number') cutPoint.addText('plugin:onFoldLower')
|
||||||
|
cutPoint.addText('plugin:from').addText('plugin:' + material)
|
||||||
|
|
||||||
|
points[`_${prefix}_titleCut_${material}`] = cutPoint
|
||||||
|
shift += 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let name = store.data?.name || 'No Name'
|
let name = store.data?.name || 'No Name'
|
||||||
name = name.replace('@freesewing/', '')
|
name = name.replace('@freesewing/', '')
|
||||||
points[`_${prefix}_titlePattern`] = so.at
|
name += 'v' + (store.data?.version || 'No Version')
|
||||||
.shift(-90 - so.rotation, shift * so.scale)
|
points[`_${prefix}_titlePattern`] = nextPoint(name, 'fill-note')
|
||||||
.attr('data-text', name)
|
|
||||||
.attr('data-text', 'v' + (store.data?.version || 'No Version'))
|
|
||||||
.attr('data-text-class', 'fill-note')
|
|
||||||
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
|
|
||||||
if (store.data.for) {
|
if (store.data.for) {
|
||||||
shift += 8
|
shift += 8
|
||||||
points[`_${prefix}_titleFor`] = so.at
|
points[`_${prefix}_titleFor`] = nextPoint(`( ${store.data.for} )`, 'fill-current font-bold')
|
||||||
.shift(-90 - so.rotation, shift * so.scale)
|
|
||||||
.attr('data-text', '( ' + store.data.for + ' )')
|
|
||||||
.attr('data-text-class', 'fill-current font-bold')
|
|
||||||
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
|
|
||||||
}
|
}
|
||||||
shift += 6
|
shift += 6
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
@ -98,20 +106,13 @@ export const plugin = {
|
||||||
let mins = now.getMinutes()
|
let mins = now.getMinutes()
|
||||||
if (hours < 10) hours = `0${hours}`
|
if (hours < 10) hours = `0${hours}`
|
||||||
if (mins < 10) mins = `0${mins}`
|
if (mins < 10) mins = `0${mins}`
|
||||||
points[`_${prefix}_exportDate`] = so.at
|
const exportDate = now.toLocaleDateString(locale || 'en', {
|
||||||
.shift(-90 - so.rotation, shift * so.scale)
|
|
||||||
.attr(
|
|
||||||
'data-text',
|
|
||||||
now.toLocaleDateString(locale || 'en', {
|
|
||||||
weekday: 'long',
|
weekday: 'long',
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'short',
|
month: 'short',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
})
|
})
|
||||||
)
|
points[`_${prefix}_exportDate`] = nextPoint(`${exportDate}@ ${hours}:${mins}`, 'text-sm')
|
||||||
.attr('data-text', `@ ${hours}:${mins}`)
|
|
||||||
.attr('data-text-class', 'text-sm')
|
|
||||||
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ const XrayText = (props) => (
|
||||||
)
|
)
|
||||||
|
|
||||||
const TextSpans = ({ point, className = '', style = {}, onClick = null }) => {
|
const TextSpans = ({ point, className = '', style = {}, onClick = null }) => {
|
||||||
const { t } = useTranslation(['app'])
|
const { t } = useTranslation(['plugin'])
|
||||||
let text = []
|
let text = []
|
||||||
// Handle translation
|
// Handle translation
|
||||||
let translated = ''
|
let translated = ''
|
||||||
|
@ -117,7 +117,7 @@ const XrayTextOnPath = (props) => (
|
||||||
)
|
)
|
||||||
|
|
||||||
export const TextOnPath = (props) => {
|
export const TextOnPath = (props) => {
|
||||||
const { t } = useTranslation(['app'])
|
const { t } = useTranslation(['plugin'])
|
||||||
// Handle translation (and spaces)
|
// Handle translation (and spaces)
|
||||||
let translated = ''
|
let translated = ''
|
||||||
for (let string of props.path.attributes.getAsArray('data-text')) {
|
for (let string of props.path.attributes.getAsArray('data-text')) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Worker from 'web-worker'
|
import Worker from 'web-worker'
|
||||||
import fileSaver from 'file-saver'
|
import fileSaver from 'file-saver'
|
||||||
import { themePlugin } from '@freesewing/plugin-theme'
|
import { themePlugin } from '@freesewing/plugin-theme'
|
||||||
|
import { pluginI18n } from '@freesewing/plugin-i18n'
|
||||||
import { pagesPlugin } from '../layout/plugin-layout-part.mjs'
|
import { pagesPlugin } from '../layout/plugin-layout-part.mjs'
|
||||||
import { capitalize } from 'shared/utils.mjs'
|
import { capitalize } from 'shared/utils.mjs'
|
||||||
|
|
||||||
|
@ -75,14 +76,7 @@ export const handleExport = async (format, gist, design, t, app, onComplete, onE
|
||||||
|
|
||||||
// add the theme and translation to the pattern
|
// add the theme and translation to the pattern
|
||||||
pattern.use(themePlugin, { stripped: format !== 'svg', skipGrid: ['pages'] })
|
pattern.use(themePlugin, { stripped: format !== 'svg', skipGrid: ['pages'] })
|
||||||
pattern.use(
|
pattern.use(pluginI18n, { t })
|
||||||
{
|
|
||||||
hooks: {
|
|
||||||
insertText: (locale, text, { t }) => t(text),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ t }
|
|
||||||
)
|
|
||||||
|
|
||||||
// a specified size should override the gist one
|
// a specified size should override the gist one
|
||||||
if (format !== 'pdf') {
|
if (format !== 'pdf') {
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const ExportDraft = ({ gist, design, app }) => {
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
const [format, setFormat] = useState(false)
|
const [format, setFormat] = useState(false)
|
||||||
|
|
||||||
const { t } = useTranslation(['app'])
|
const { t } = useTranslation(['app', , 'plugin'])
|
||||||
const doExport = (format) => {
|
const doExport = (format) => {
|
||||||
setLink(false)
|
setLink(false)
|
||||||
setError(false)
|
setError(false)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { fabricPlugin } from '../plugin-layout-part.mjs'
|
||||||
import { cutLayoutPlugin } from './plugin-cut-layout.mjs'
|
import { cutLayoutPlugin } from './plugin-cut-layout.mjs'
|
||||||
import { pluginCutlist } from '@freesewing/plugin-cutlist'
|
import { pluginCutlist } from '@freesewing/plugin-cutlist'
|
||||||
import { pluginFlip } from '@freesewing/plugin-flip'
|
import { pluginFlip } from '@freesewing/plugin-flip'
|
||||||
|
import { pluginI18n } from '@freesewing/plugin-i18n'
|
||||||
import { measurementAsMm } from 'shared/utils.mjs'
|
import { measurementAsMm } from 'shared/utils.mjs'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import get from 'lodash.get'
|
import get from 'lodash.get'
|
||||||
|
@ -22,7 +23,7 @@ const useFabricSettings = (gist) => {
|
||||||
return { activeFabric, sheetWidth, grainDirection, sheetHeight }
|
return { activeFabric, sheetWidth, grainDirection, sheetHeight }
|
||||||
}
|
}
|
||||||
|
|
||||||
const useFabricDraft = (gist, design, fabricSettings) => {
|
const useFabricDraft = (gist, design, fabricSettings, t) => {
|
||||||
// get the appropriate layout for the view
|
// get the appropriate layout for the view
|
||||||
const layout =
|
const layout =
|
||||||
get(gist, ['layouts', gist._state.view, fabricSettings.activeFabric]) || gist.layout || true
|
get(gist, ['layouts', gist._state.view, fabricSettings.activeFabric]) || gist.layout || true
|
||||||
|
@ -43,6 +44,8 @@ const useFabricDraft = (gist, design, fabricSettings) => {
|
||||||
// also, pluginCutlist and pluginFlip are needed
|
// also, pluginCutlist and pluginFlip are needed
|
||||||
draft.use(pluginCutlist)
|
draft.use(pluginCutlist)
|
||||||
draft.use(pluginFlip)
|
draft.use(pluginFlip)
|
||||||
|
// add translation
|
||||||
|
draft.use(pluginI18n, { t })
|
||||||
|
|
||||||
// draft the pattern
|
// draft the pattern
|
||||||
draft.draft()
|
draft.draft()
|
||||||
|
@ -77,7 +80,7 @@ export const CutLayout = (props) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const fabricSettings = useFabricSettings(gist)
|
const fabricSettings = useFabricSettings(gist)
|
||||||
const { draft, patternProps } = useFabricDraft(gist, design, fabricSettings)
|
const { draft, patternProps } = useFabricDraft(gist, design, fabricSettings, t)
|
||||||
const fabricList = useFabricList(draft)
|
const fabricList = useFabricList(draft)
|
||||||
|
|
||||||
const setCutFabric = (newFabric) => {
|
const setCutFabric = (newFabric) => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const PrintLayout = (props) => {
|
||||||
if (props.gist?._state?.xray?.enabled) props.updateGist(['_state', 'xray', 'enabled'], false)
|
if (props.gist?._state?.xray?.enabled) props.updateGist(['_state', 'xray', 'enabled'], false)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { t } = useTranslation(['workbench'])
|
const { t } = useTranslation(['workbench', 'plugin'])
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
|
|
||||||
const draft = props.draft
|
const draft = props.draft
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
// Hooks
|
// Hooks
|
||||||
import { useEffect, useState, useMemo } from 'react'
|
import { useEffect, useState, useMemo } from 'react'
|
||||||
import { useGist } from 'shared/hooks/useGist'
|
import { useGist } from 'shared/hooks/useGist'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
// Dependencies
|
// Dependencies
|
||||||
import { pluginTheme } from '@freesewing/plugin-theme'
|
import { pluginTheme } from '@freesewing/plugin-theme'
|
||||||
|
import { pluginI18n } from '@freeSewing/plugin-i18n'
|
||||||
import { preloaders } from 'shared/components/workbench/preloaders.mjs'
|
import { preloaders } from 'shared/components/workbench/preloaders.mjs'
|
||||||
// Components
|
// Components
|
||||||
import { WorkbenchMenu } from 'shared/components/workbench/menu/index.mjs'
|
import { WorkbenchMenu } from 'shared/components/workbench/menu/index.mjs'
|
||||||
|
@ -70,6 +72,8 @@ export const WorkbenchWrapper = ({
|
||||||
const [messages, setMessages] = useState([])
|
const [messages, setMessages] = useState([])
|
||||||
const [popup, setPopup] = useState(false)
|
const [popup, setPopup] = useState(false)
|
||||||
const [preloaded, setPreloaded] = useState(false)
|
const [preloaded, setPreloaded] = useState(false)
|
||||||
|
// we'll only use this if the renderer is svg, but we can't call hooks conditionally
|
||||||
|
const { t } = useTranslation(['plugin'])
|
||||||
|
|
||||||
// We'll use this in more than one location
|
// We'll use this in more than one location
|
||||||
const hasRequiredMeasurements = hasRequiredMeasurementsMethod(design, gist)
|
const hasRequiredMeasurements = hasRequiredMeasurementsMethod(design, gist)
|
||||||
|
@ -128,7 +132,10 @@ export const WorkbenchWrapper = ({
|
||||||
//draft.__init()
|
//draft.__init()
|
||||||
|
|
||||||
// add theme to svg renderer
|
// add theme to svg renderer
|
||||||
if (gist.renderer === 'svg') draft.use(pluginTheme, { skipGrid: ['pages'] })
|
if (gist.renderer === 'svg') {
|
||||||
|
draft.use(pluginI18n, { t })
|
||||||
|
draft.use(pluginTheme, { skipGrid: ['pages'] })
|
||||||
|
}
|
||||||
|
|
||||||
// draft it for draft and event views. Other views may add plugins, etc and we don't want to draft twice
|
// draft it for draft and event views. Other views may add plugins, etc and we don't want to draft twice
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue