Merge branch 'develop' into i18n
This commit is contained in:
commit
1fd323e109
77 changed files with 2410 additions and 1832 deletions
|
@ -19,6 +19,7 @@ import {
|
|||
} from 'shared/components/icons.mjs'
|
||||
import Link from 'next/link'
|
||||
import { MenuWrapper } from 'shared/components/workbench/menus/shared/menu-wrapper.mjs'
|
||||
import { isProduction } from 'shared/config/freesewing.config.mjs'
|
||||
|
||||
export const ns = ['workbench', 'sections']
|
||||
|
||||
|
@ -46,7 +47,7 @@ export const NavButton = ({
|
|||
const className = `w-full flex flex-row items-center px-4 py-2 ${extraClasses} ${
|
||||
active ? 'text-secondary' : ''
|
||||
}`
|
||||
const span = <span className="font-bold block grow text-left">{label}</span>
|
||||
const span = <span className="font-normal block grow text-left">{label}</span>
|
||||
|
||||
return onClick ? (
|
||||
<button {...{ onClick, className }} title={label}>
|
||||
|
@ -70,7 +71,7 @@ const NavIcons = ({ setView, setDense, dense, view }) => {
|
|||
<NavButton
|
||||
onClick={() => setDense(!dense)}
|
||||
label={t('workbench:viewMenu')}
|
||||
extraClasses="hidden lg:flex text-success bg-neutral hover:bg-success hover:text-neutral"
|
||||
extraClasses="hidden lg:flex text-accent bg-neutral hover:bg-accent hover:text-neutral-content"
|
||||
>
|
||||
{dense ? (
|
||||
<RightIcon
|
||||
|
@ -109,13 +110,15 @@ const NavIcons = ({ setView, setDense, dense, view }) => {
|
|||
>
|
||||
<PrintIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavButton
|
||||
onClick={() => setView('cut')}
|
||||
label={t('workbench:cutLayout')}
|
||||
active={view === 'cut'}
|
||||
>
|
||||
<CutIcon className={iconSize} />
|
||||
</NavButton>
|
||||
{!isProduction && (
|
||||
<NavButton
|
||||
onClick={() => setView('cut')}
|
||||
label={t('workbench:cutLayout')}
|
||||
active={view === 'cut'}
|
||||
>
|
||||
<CutIcon className={iconSize} />
|
||||
</NavButton>
|
||||
)}
|
||||
<NavButton
|
||||
onClick={() => setView('save')}
|
||||
label={t('workbench:savePattern')}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
|||
import { CloseIcon } from 'shared/components/icons.mjs'
|
||||
import { MobileMenubarContext } from 'shared/context/mobile-menubar-context.mjs'
|
||||
import { shownHeaderSelector } from 'shared/components/wrappers/header.mjs'
|
||||
import { MenuAltIcon } from 'shared/components/icons.mjs'
|
||||
|
||||
/**
|
||||
* A component to display menu buttons and actions in mobile.
|
||||
|
@ -35,6 +36,7 @@ export const MobileMenubar = () => {
|
|||
slideFrom="right"
|
||||
keepOpenOnClick={selectedMenu.keepOpenOnClick}
|
||||
keepOpenOnSwipe
|
||||
fullWidth
|
||||
>
|
||||
<div className="mb-16">{selectedMenu.menuContent}</div>
|
||||
<button
|
||||
|
@ -62,10 +64,10 @@ export const MobileMenubar = () => {
|
|||
<div
|
||||
className={`
|
||||
lg:hidden
|
||||
${shownHeaderSelector('bottom-16')}
|
||||
${shownHeaderSelector('bottom-16')}
|
||||
sticky bottom-0 w-20 -ml-20 self-end
|
||||
duration-300 transition-all
|
||||
flex flex-col-reverse gap-4
|
||||
duration-300 transition-all
|
||||
flex flex-col-reverse gap-2 mb-2
|
||||
z-20
|
||||
mobile-menubar
|
||||
`}
|
||||
|
@ -73,11 +75,11 @@ export const MobileMenubar = () => {
|
|||
{Object.keys(menus)
|
||||
.sort((a, b) => menus[a].order - menus[b].order)
|
||||
.map((m) => {
|
||||
const Icon = menus[m].Icon
|
||||
const Icon = m === 'nav' ? MenuAltIcon : menus[m].Icon
|
||||
return (
|
||||
<button
|
||||
key={m}
|
||||
className="btn btn-accent btn-circle mx-4"
|
||||
className={`btn ${m === 'nav' ? 'btn-neutral' : 'btn-primary'} btn-circle mx-4`}
|
||||
onClick={() => setSelectedModal(m)}
|
||||
>
|
||||
<Icon />
|
||||
|
|
|
@ -234,7 +234,7 @@ export const ListInput = ({ name, config, current, updateFunc, compact = false,
|
|||
const titleKey = config.choiceTitles ? config.choiceTitles[entry] : `${name}.o.${entry}`
|
||||
const title = t(`${titleKey}.t`)
|
||||
const desc = t(`${titleKey}.d`)
|
||||
const sideBySide = desc.length + title.length < 70
|
||||
const sideBySide = desc.length + title.length < 60
|
||||
|
||||
return (
|
||||
<ButtonFrame
|
||||
|
|
|
@ -216,10 +216,10 @@ export const MenuItemGroup = ({
|
|||
: () => <span>¯\_(ツ)_/¯</span>
|
||||
|
||||
return [
|
||||
<div className="flex flex-row items-center justify-between" key="a">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<div className="flex flex-row items-center justify-between w-full" key="a">
|
||||
<div className="flex flex-row items-center gap-4 w-full">
|
||||
<ItemIcon />
|
||||
<h6>{t([`${itemName}.t`, itemName])}</h6>
|
||||
<span className="font-medium">{t([`${itemName}.t`, itemName])}</span>
|
||||
</div>
|
||||
<div className="font-bold">
|
||||
<Value
|
||||
|
@ -280,33 +280,5 @@ export const MenuItemGroup = ({
|
|||
]
|
||||
})
|
||||
|
||||
// if it should be wrapped in a collapsible
|
||||
/*
|
||||
if (collapsible) {
|
||||
// props to give to the group title
|
||||
const titleProps = {
|
||||
name,
|
||||
t,
|
||||
emoji: emojis[name] || emojis.groupDflt,
|
||||
}
|
||||
return (
|
||||
<Collapse
|
||||
bottom
|
||||
color={topLevel ? 'primary' : 'secondary'}
|
||||
title={
|
||||
<ItemTitle
|
||||
{...titleProps}
|
||||
current={Icon ? <Icon className="w-6 h-6 text-primary" /> : ''}
|
||||
/>
|
||||
}
|
||||
openTitle={<ItemTitle open {...titleProps} />}
|
||||
>
|
||||
{content}
|
||||
</Collapse>
|
||||
)
|
||||
}
|
||||
*/
|
||||
|
||||
//otherwise just return the content
|
||||
return <SubAccordion items={content.filter((item) => item !== null)} />
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { formatMm } from 'shared/utils.mjs'
|
||||
import { BoolYesIcon, BoolNoIcon } from 'shared/components/icons.mjs'
|
||||
|
||||
/*********************************************************************************************************
|
||||
* This file contains the base components to be used for displaying values in menu titles in the workbench
|
||||
|
@ -38,10 +39,10 @@ export const ListValue = ({ current, t, config, changed }) => {
|
|||
// if not, is the value a string
|
||||
else if (typeof val === 'string') key = val
|
||||
// otherwise stringify booleans
|
||||
else if (val) key = 'yes'
|
||||
else key = 'no'
|
||||
else if (val) key = <BoolYesIcon />
|
||||
else key = <BoolNoIcon />
|
||||
|
||||
const translated = config.doNotTranslate ? key : t(key)
|
||||
const translated = config.doNotTranslate || typeof key !== 'string' ? key : t(key)
|
||||
|
||||
return <HighlightedValue changed={changed}>{translated}</HighlightedValue>
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ export const CutView = ({
|
|||
|
||||
return (
|
||||
<PatternWithMenu
|
||||
noHeader
|
||||
{...{
|
||||
settings,
|
||||
ui,
|
||||
|
|
|
@ -69,7 +69,7 @@ export const DraftMenu = ({
|
|||
<span>{t(`${section.ns}:${section.name}.t`)}</span>
|
||||
{section.icon}
|
||||
</h5>
|
||||
<p>{t(`${section.ns}:${section.name}.d`)}</p>
|
||||
<p className="text-left">{t(`${section.ns}:${section.name}.d`)}</p>
|
||||
</>,
|
||||
section.menu,
|
||||
])}
|
||||
|
|
|
@ -20,6 +20,8 @@ import { MsetIcon, BookmarkIcon, CsetIcon, EditIcon } from 'shared/components/ic
|
|||
|
||||
export const ns = nsMerge(authNs, setsNs)
|
||||
|
||||
const iconClasses = { className: 'w-8 h-8 md:w-10 md:h-10 lg:w-12 lg:h-12 shrink-0', stroke: 1.5 }
|
||||
|
||||
export const MeasiesView = ({ design, Design, settings, update, missingMeasurements, setView }) => {
|
||||
const { t } = useTranslation(['workbench'])
|
||||
const { setLoadingStatus, LoadingStatus } = useLoadingStatus()
|
||||
|
@ -61,7 +63,7 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme
|
|||
<Fragment key={1}>
|
||||
<div className={horFlexClasses}>
|
||||
<h5 id="ownsets">{t('workbench:chooseFromOwnSets')}</h5>
|
||||
<MsetIcon className="w-6 h-6 shrink-0" />
|
||||
<MsetIcon {...iconClasses} />
|
||||
</div>
|
||||
<p>{t('workbench:chooseFromOwnSetsDesc')}</p>
|
||||
</Fragment>,
|
||||
|
@ -77,7 +79,7 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme
|
|||
<Fragment key={1}>
|
||||
<div className={horFlexClasses}>
|
||||
<h5 id="bookmarkedsets">{t('workbench:chooseFromBookmarkedSets')}</h5>
|
||||
<BookmarkIcon className="w-6 h-6 shrink-0" />
|
||||
<BookmarkIcon {...iconClasses} />
|
||||
</div>
|
||||
<p>{t('workbench:chooseFromBookmarkedSetsDesc')}</p>
|
||||
</Fragment>,
|
||||
|
@ -93,7 +95,7 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme
|
|||
<Fragment key={1}>
|
||||
<div className={horFlexClasses}>
|
||||
<h5 id="curatedsets">{t('workbench:chooseFromCuratedSets')}</h5>
|
||||
<CsetIcon />
|
||||
<CsetIcon {...iconClasses} />
|
||||
</div>
|
||||
<p>{t('workbench:chooseFromCuratedSetsDesc')}</p>
|
||||
</Fragment>,
|
||||
|
@ -103,7 +105,7 @@ export const MeasiesView = ({ design, Design, settings, update, missingMeasureme
|
|||
<Fragment key={1}>
|
||||
<div className={horFlexClasses}>
|
||||
<h5 id="editmeasies">{t('workbench:editMeasiesByHand')}</h5>
|
||||
<EditIcon />
|
||||
<EditIcon {...iconClasses} />
|
||||
</div>
|
||||
<p>{t('workbench:editMeasiesByHandDesc')}</p>
|
||||
</Fragment>,
|
||||
|
|
|
@ -16,20 +16,23 @@ export const PatternWithMenu = ({
|
|||
pattern,
|
||||
menu,
|
||||
setSettings,
|
||||
noHeader = false,
|
||||
}) => (
|
||||
<PanZoomContextProvider>
|
||||
<div className="flex flex-col h-full">
|
||||
<ViewHeader
|
||||
{...{
|
||||
settings,
|
||||
ui,
|
||||
update,
|
||||
control,
|
||||
account,
|
||||
design,
|
||||
setSettings,
|
||||
}}
|
||||
/>
|
||||
{noHeader ? null : (
|
||||
<ViewHeader
|
||||
{...{
|
||||
settings,
|
||||
ui,
|
||||
update,
|
||||
control,
|
||||
account,
|
||||
design,
|
||||
setSettings,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex lg:flex-row grow lg:max-h-[90vh] max-h-[calc(100vh-3rem)] h-full py-4 lg:mt-6">
|
||||
<div className="lg:w-2/3 flex flex-col h-full grow px-4">
|
||||
{title}
|
||||
|
|
|
@ -1,28 +1,79 @@
|
|||
import { Fragment } from 'react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { ClearIcon, ExportIcon } from 'shared/components/icons.mjs'
|
||||
import { ShowButtonsToggle } from 'shared/components/workbench/pattern/movable/transform-buttons.mjs'
|
||||
import { SubAccordion } from 'shared/components/accordion.mjs'
|
||||
import {
|
||||
WarningIcon,
|
||||
ResetIcon,
|
||||
LeftRightIcon,
|
||||
BoolYesIcon,
|
||||
BoolNoIcon,
|
||||
} from 'shared/components/icons.mjs'
|
||||
import { ListInput } from 'shared/components/inputs.mjs'
|
||||
import { horFlexClasses } from 'shared/utils.mjs'
|
||||
|
||||
export const ns = ['workbench', 'print']
|
||||
|
||||
export const PrintActions = ({ update, ui, exportIt }) => {
|
||||
export const PrintActions = ({ update, ui }) => {
|
||||
// get translation for the menu
|
||||
const { t } = useTranslation(ns)
|
||||
|
||||
const resetLayout = () => update.ui(['layouts', 'print'])
|
||||
|
||||
return (
|
||||
<div className="mt-2 mb-4">
|
||||
<div className="flex justify-evenly flex-col lg:flex-row">
|
||||
<ShowButtonsToggle update={update} ui={ui} />
|
||||
<button className="btn btn-primary btn-outline" onClick={resetLayout}>
|
||||
<ClearIcon />
|
||||
<span className="ml-2">{t('reset')}</span>
|
||||
</button>
|
||||
<button className="btn btn-primary" onClick={exportIt}>
|
||||
<ExportIcon />
|
||||
<span className="ml-2">{t('export')}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<>
|
||||
<SubAccordion
|
||||
items={[
|
||||
[
|
||||
<div className="w-full flex flex-row gap2 justify-between" key={1}>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<LeftRightIcon />
|
||||
<span>{t('workbench:partTransfo')}</span>
|
||||
</div>
|
||||
{ui.hideMovableButtons ? <BoolNoIcon /> : <BoolYesIcon />}
|
||||
</div>,
|
||||
<ListInput
|
||||
key={2}
|
||||
update={() => update.ui('hideMovableButtons', ui.hideMovableButtons ? false : true)}
|
||||
label={
|
||||
<span className="text-base font-normal">{t('workbench:partTransfoDesc')}</span>
|
||||
}
|
||||
list={[
|
||||
{
|
||||
val: true,
|
||||
label: t('workbench:partTransfoNo'),
|
||||
desc: t('workbench:partTransfoNoDesc'),
|
||||
},
|
||||
{
|
||||
val: false,
|
||||
label: t('workbench:partTransfoYes'),
|
||||
desc: t('workbench:partTransfoYesDesc'),
|
||||
},
|
||||
]}
|
||||
current={ui.hideMovableButtons ? true : false}
|
||||
/>,
|
||||
],
|
||||
[
|
||||
<div className="w-full flex flex-row gap2 justify-between" key={1}>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<ResetIcon />
|
||||
<span>{t('workbench:resetPrintLayout')}</span>
|
||||
</div>
|
||||
<WarningIcon />
|
||||
</div>,
|
||||
|
||||
<Fragment key={2}>
|
||||
<p>{t('workbench:resetPrintLayoutDesc')}</p>
|
||||
<button
|
||||
className={`${horFlexClasses} btn btn-warning btn-outline w-full`}
|
||||
onClick={resetLayout}
|
||||
>
|
||||
<ResetIcon />
|
||||
<span>{t('workbench:resetPrintLayout')}</span>
|
||||
</button>
|
||||
</Fragment>,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
import { measurementAsMm } from 'shared/utils.mjs'
|
||||
import {
|
||||
PageSizeIcon,
|
||||
PageOrientationIcon,
|
||||
PageMarginIcon,
|
||||
CoverPageIcon,
|
||||
CuttingLayoutIcon,
|
||||
} from 'shared/components/icons.mjs'
|
||||
import { isProduction } from 'shared/config/freesewing.config.mjs'
|
||||
|
||||
export const printSettingsPath = ['print', 'pages']
|
||||
|
||||
export const defaultPrintSettings = (units, inMm = true) => {
|
||||
const margin = units === 'imperial' ? 0.5 : 1
|
||||
return {
|
||||
size: 'a4',
|
||||
size: units === 'imperial' ? 'letter' : 'a4',
|
||||
orientation: 'portrait',
|
||||
margin: inMm ? measurementAsMm(margin, units) : margin,
|
||||
coverPage: true,
|
||||
|
@ -22,6 +30,7 @@ export const loadPrintConfig = (units) => {
|
|||
dflt: defaults.size,
|
||||
choiceTitles: {},
|
||||
valueTitles: {},
|
||||
icon: PageSizeIcon,
|
||||
},
|
||||
orientation: {
|
||||
control: 2,
|
||||
|
@ -35,6 +44,7 @@ export const loadPrintConfig = (units) => {
|
|||
landscape: 'landscape',
|
||||
},
|
||||
dflt: defaults.orientation,
|
||||
icon: PageOrientationIcon,
|
||||
},
|
||||
margin: {
|
||||
control: 2,
|
||||
|
@ -42,14 +52,17 @@ export const loadPrintConfig = (units) => {
|
|||
max: 2.5,
|
||||
step: units === 'imperial' ? 0.125 : 0.1,
|
||||
dflt: defaults.margin,
|
||||
icon: PageMarginIcon,
|
||||
},
|
||||
coverPage: {
|
||||
control: 3,
|
||||
dflt: defaults.coverPage,
|
||||
icon: CoverPageIcon,
|
||||
},
|
||||
cutlist: {
|
||||
control: 3,
|
||||
dflt: defaults.cutlist,
|
||||
icon: CuttingLayoutIcon,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -58,5 +71,10 @@ export const loadPrintConfig = (units) => {
|
|||
config.size.valueTitles[s] = s
|
||||
})
|
||||
|
||||
/*
|
||||
* Don't include cutlist in production until it's ready to go
|
||||
*/
|
||||
if (isProduction) delete config.cutlist
|
||||
|
||||
return config
|
||||
}
|
||||
|
|
|
@ -5,38 +5,17 @@ import {
|
|||
handleExport,
|
||||
ns as exportNs,
|
||||
} from 'shared/components/workbench/exporting/export-handler.mjs'
|
||||
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
|
||||
import get from 'lodash.get'
|
||||
import { MovablePattern } from 'shared/components/workbench/pattern/movable/index.mjs'
|
||||
import { PrintMenu, ns as menuNs } from './menu.mjs'
|
||||
import { defaultPrintSettings, printSettingsPath } from './config.mjs'
|
||||
import { PrintIcon, RightIcon } from 'shared/components/icons.mjs'
|
||||
import { LoadingContext } from 'shared/context/loading-context.mjs'
|
||||
import { useToast } from 'shared/hooks/use-toast.mjs'
|
||||
import { PatternWithMenu, ns as wrapperNs } from '../pattern-with-menu.mjs'
|
||||
import { V3Wip } from 'shared/components/v3-wip.mjs'
|
||||
import { nsMerge } from 'shared/utils.mjs'
|
||||
|
||||
const viewNs = ['print', ...exportNs]
|
||||
export const ns = [...viewNs, ...menuNs, ...wrapperNs]
|
||||
export const ns = nsMerge(menuNs, wrapperNs, exportNs, 'print', 'status')
|
||||
|
||||
const PageCounter = ({ pattern }) => {
|
||||
const pages = pattern.setStores[0].get('pages', {})
|
||||
const { cols, rows, count } = pages
|
||||
|
||||
return (
|
||||
<div className="flex flex-row font-bold items-center text-2xl justify-center ">
|
||||
<PrintIcon />
|
||||
<span className="ml-2">{count}</span>
|
||||
<span className="mx-6 opacity-50">|</span>
|
||||
<RightIcon />
|
||||
<span className="ml-2">{cols}</span>
|
||||
<span className="mx-6 opacity-50">|</span>
|
||||
<div className="rotate-90">
|
||||
<RightIcon />
|
||||
</div>
|
||||
<span className="ml-2">{rows}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export const PrintView = ({
|
||||
design,
|
||||
pattern,
|
||||
|
@ -52,7 +31,7 @@ export const PrintView = ({
|
|||
}) => {
|
||||
const { t } = useTranslation(ns)
|
||||
const loading = useContext(LoadingContext)
|
||||
const toast = useToast()
|
||||
const { setLoadingStatus, LoadingStatus } = useLoadingStatus()
|
||||
|
||||
const defaultSettings = defaultPrintSettings(settings.units)
|
||||
// add the pages plugin to the draft
|
||||
|
@ -73,6 +52,7 @@ export const PrintView = ({
|
|||
}
|
||||
|
||||
const exportIt = () => {
|
||||
setLoadingStatus([true, 'generatingPdf'])
|
||||
handleExport({
|
||||
format: pageSettings.size,
|
||||
settings,
|
||||
|
@ -82,43 +62,44 @@ export const PrintView = ({
|
|||
ui,
|
||||
startLoading: loading.startLoading,
|
||||
stopLoading: loading.stopLoading,
|
||||
onComplete: () => {},
|
||||
onError: (err) => toast.error(err.message),
|
||||
onComplete: () => {
|
||||
setLoadingStatus([true, 'pdfReady', true, true])
|
||||
},
|
||||
onError: (err) => {
|
||||
setLoadingStatus([true, 'pdfFailed', true, true])
|
||||
console.log(err)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<PatternWithMenu
|
||||
{...{
|
||||
settings,
|
||||
ui,
|
||||
update,
|
||||
control: account.control,
|
||||
account,
|
||||
design,
|
||||
setSettings,
|
||||
title: (
|
||||
<div className="flex lg:justify-between items-baseline flex-wrap px-2">
|
||||
<h2 className="text-center lg:text-left capitalize">
|
||||
{t('layoutThing', { thing: design }) + ' ' + t('forPrinting')}
|
||||
</h2>
|
||||
<PageCounter pattern={pattern} />
|
||||
</div>
|
||||
),
|
||||
pattern: (
|
||||
<MovablePattern
|
||||
{...{
|
||||
renderProps,
|
||||
update,
|
||||
immovable: ['pages'],
|
||||
layoutPath: ['layouts', 'print'],
|
||||
showButtons: !ui.hideMovableButtons,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
menu: (
|
||||
<>
|
||||
<V3Wip />
|
||||
<>
|
||||
<LoadingStatus />
|
||||
<PatternWithMenu
|
||||
noHeader
|
||||
{...{
|
||||
settings,
|
||||
ui,
|
||||
update,
|
||||
control: account.control,
|
||||
account,
|
||||
design,
|
||||
setSettings,
|
||||
title: (
|
||||
<h2 className="text-center lg:text-left capitalize">{t('workbench:printLayout')}</h2>
|
||||
),
|
||||
pattern: (
|
||||
<MovablePattern
|
||||
{...{
|
||||
renderProps,
|
||||
update,
|
||||
immovable: ['pages'],
|
||||
layoutPath: ['layouts', 'print'],
|
||||
showButtons: !ui.hideMovableButtons,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
menu: (
|
||||
<PrintMenu
|
||||
{...{
|
||||
design,
|
||||
|
@ -134,9 +115,9 @@ export const PrintView = ({
|
|||
exportIt,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,45 @@
|
|||
import {
|
||||
DesignOptions,
|
||||
ns as designMenuNs,
|
||||
} from 'shared/components/workbench/menus/design-options/index.mjs'
|
||||
import {
|
||||
CoreSettings,
|
||||
ClearAllButton,
|
||||
ns as coreMenuNs,
|
||||
} from 'shared/components/workbench/menus/core-settings/index.mjs'
|
||||
import { PrintSettings, ns as printMenuNs } from './settings.mjs'
|
||||
import { PrintActions } from './actions.mjs'
|
||||
import { PrintIcon, CompareIcon } from 'shared/components/icons.mjs'
|
||||
import { Accordion } from 'shared/components/accordion.mjs'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { horFlexClasses, capitalize } from 'shared/utils.mjs'
|
||||
|
||||
export const ns = [...coreMenuNs, ...designMenuNs, ...printMenuNs]
|
||||
export const ns = printMenuNs
|
||||
|
||||
const PageCounter = ({ pattern, t, ui, settings }) => {
|
||||
const pages = pattern.setStores[0].get('pages', {})
|
||||
const format = ui.print?.pages?.size
|
||||
? ui.print.pages.size
|
||||
: settings.units === 'imperial'
|
||||
? 'letter'
|
||||
: 'a4'
|
||||
const { cols, rows, count } = pages
|
||||
|
||||
return (
|
||||
<div className="flex flex-row flex-wrap items-center gap-1 mb-2 py-2">
|
||||
<b>{t('workbench:currentPrintLayout')}:</b>
|
||||
<div className="flex flex-row flex-wrap items-center gap-1">
|
||||
<span>
|
||||
{count} {capitalize(format)} {t('workbench:pages')},
|
||||
</span>
|
||||
<span>
|
||||
{cols} {t('workbench:columns')},
|
||||
</span>
|
||||
<span>
|
||||
{rows} {t('workbench:rows')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row flex-wrap items-center italic">
|
||||
({t('workbench:xTotalPagesSomeBlank', { total: cols * rows, blank: cols * rows - count })})
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const PrintMenu = ({
|
||||
design,
|
||||
patternConfig,
|
||||
setSettings,
|
||||
settings,
|
||||
ui,
|
||||
update,
|
||||
|
@ -23,8 +47,9 @@ export const PrintMenu = ({
|
|||
account,
|
||||
DynamicDocs,
|
||||
exportIt,
|
||||
pattern,
|
||||
}) => {
|
||||
const control = account.control
|
||||
const { t } = useTranslation()
|
||||
const menuProps = {
|
||||
design,
|
||||
patternConfig,
|
||||
|
@ -33,15 +58,43 @@ export const PrintMenu = ({
|
|||
language,
|
||||
account,
|
||||
DynamicDocs,
|
||||
control,
|
||||
control: account.control,
|
||||
}
|
||||
|
||||
const sections = [
|
||||
{
|
||||
name: 'printSettings',
|
||||
ns: 'workbench',
|
||||
icon: <PrintIcon className="w-8 h-8" />,
|
||||
menu: <PrintSettings {...menuProps} ui={ui} />,
|
||||
},
|
||||
{
|
||||
name: 'layoutSettings',
|
||||
ns: 'workbench',
|
||||
icon: <CompareIcon className="w-8 h-8" />,
|
||||
menu: <PrintActions {...menuProps} ui={ui} />,
|
||||
},
|
||||
]
|
||||
console.log(ui)
|
||||
return (
|
||||
<nav>
|
||||
<PrintActions {...menuProps} ui={ui} exportIt={exportIt} />
|
||||
<PrintSettings {...menuProps} ui={ui} />
|
||||
<DesignOptions {...menuProps} isFirst={false} />
|
||||
<CoreSettings {...menuProps} />
|
||||
<ClearAllButton setSettings={setSettings} />
|
||||
</nav>
|
||||
<>
|
||||
<PageCounter {...{ pattern, t, ui, settings }} />
|
||||
<button className={`${horFlexClasses} btn btn-primary btn-lg`} onClick={exportIt}>
|
||||
<PrintIcon className="w-8 h-8" />
|
||||
{t('workbench:generatePdf')}
|
||||
</button>
|
||||
<Accordion
|
||||
items={sections.map((section) => [
|
||||
<>
|
||||
<h5 className="flex flex-row gap-2 items-center justify-between w-full">
|
||||
<span>{t(`${section.ns}:${section.name}.t`)}</span>
|
||||
{section.icon}
|
||||
</h5>
|
||||
<p className="text-left">{t(`${section.ns}:${section.name}.d`)}</p>
|
||||
</>,
|
||||
section.menu,
|
||||
])}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import { PrintIcon } from 'shared/components/icons.mjs'
|
||||
import { WorkbenchMenu } from 'shared/components/workbench/menus/shared/index.mjs'
|
||||
import { ListInput, BoolInput, MmInput } from 'shared/components/workbench/menus/shared/inputs.mjs'
|
||||
import { ListValue, BoolValue, MmValue } from 'shared/components/workbench/menus/shared/values.mjs'
|
||||
import {
|
||||
BoolValue,
|
||||
MmValue,
|
||||
HighlightedValue,
|
||||
} from 'shared/components/workbench/menus/shared/values.mjs'
|
||||
import { loadPrintConfig, printSettingsPath } from './config.mjs'
|
||||
import { capitalize } from 'shared/utils.mjs'
|
||||
import get from 'lodash.get'
|
||||
import { PatternIcon } from 'shared/components/icons.mjs'
|
||||
|
||||
const inputs = {
|
||||
size: ListInput,
|
||||
|
@ -14,8 +20,18 @@ const inputs = {
|
|||
}
|
||||
|
||||
const values = {
|
||||
size: ListValue,
|
||||
orientation: ListValue,
|
||||
size: ({ current, changed, config }) => (
|
||||
<HighlightedValue changed={changed}>
|
||||
{capitalize(current ? current : config.dflt)}
|
||||
</HighlightedValue>
|
||||
),
|
||||
orientation: ({ current, changed }) => (
|
||||
<HighlightedValue changed={changed}>
|
||||
<PatternIcon
|
||||
className={`w-6 h-6 text-inherit ${current === 'landscape' ? '-rotate-90' : ''}`}
|
||||
/>
|
||||
</HighlightedValue>
|
||||
),
|
||||
margin: MmValue,
|
||||
coverPage: BoolValue,
|
||||
cutlist: BoolValue,
|
||||
|
|
|
@ -2,6 +2,7 @@ import { useTranslation } from 'next-i18next'
|
|||
import { PanZoomPattern } from 'shared/components/workbench/pan-zoom-pattern.mjs'
|
||||
import { TestMenu, ns as menuNs } from './menu.mjs'
|
||||
import { PatternWithMenu, ns as wrapperNs } from '../pattern-with-menu.mjs'
|
||||
import { Popout } from 'shared/components/popout/index.mjs'
|
||||
|
||||
export const ns = [...menuNs, wrapperNs]
|
||||
|
||||
|
@ -23,24 +24,35 @@ export const TestView = ({
|
|||
|
||||
const renderProps = pattern.getRenderProps()
|
||||
const patternConfig = pattern.getConfig()
|
||||
let placeholder = false
|
||||
|
||||
/*
|
||||
* Translation of the title needs some work
|
||||
*/
|
||||
let title = t('workbench:testDesignOption', {
|
||||
design,
|
||||
option: t(`${design}:${settings.sample?.option}.t`),
|
||||
})
|
||||
let title = t('workbench:chooseATest')
|
||||
if (settings.sample?.type === 'measurement')
|
||||
title = t('workbench:testDesignMeasurement', {
|
||||
design,
|
||||
measurement: t(`measurements:${settings.sample?.measurement}`),
|
||||
})
|
||||
else if (settings.sample?.type === 'option')
|
||||
title = t('workbench:testDesignOption', {
|
||||
design,
|
||||
option: t(`${design}:${settings.sample?.option}.t`),
|
||||
})
|
||||
else if (settings.sample?.type === 'sets')
|
||||
title = t('workbench:testDesignSets', {
|
||||
design,
|
||||
thing: 'fixme views/test/index.mjs',
|
||||
})
|
||||
else
|
||||
placeholder = (
|
||||
<Popout tip>
|
||||
<p>{t('workbench:chooseATestDesc')}</p>
|
||||
<p className="hidden md:block">{t('workbench:chooseATestMenuMsg')}</p>
|
||||
<p className="block md:hidden">{t('workbench:chooseATestMenuMobileMsg')}</p>
|
||||
</Popout>
|
||||
)
|
||||
|
||||
return (
|
||||
<PatternWithMenu
|
||||
|
@ -53,7 +65,7 @@ export const TestView = ({
|
|||
design,
|
||||
setSettings,
|
||||
title: <h2>{title}</h2>,
|
||||
pattern: <PanZoomPattern {...{ renderProps }} />,
|
||||
pattern: placeholder ? placeholder : <PanZoomPattern {...{ renderProps }} />,
|
||||
menu: (
|
||||
<TestMenu
|
||||
{...{
|
||||
|
|
|
@ -10,11 +10,11 @@ import {
|
|||
BulletIcon,
|
||||
UnitsIcon,
|
||||
DetailIcon,
|
||||
IconWrapper,
|
||||
ClearIcon,
|
||||
ResetIcon,
|
||||
UploadIcon,
|
||||
BookmarkIcon,
|
||||
ZoomInIcon,
|
||||
ZoomOutIcon,
|
||||
} from 'shared/components/icons.mjs'
|
||||
import { shownHeaderSelector } from 'shared/components/wrappers/header.mjs'
|
||||
import { useLoadingStatus } from 'shared/hooks/use-loading-status.mjs'
|
||||
|
@ -22,18 +22,6 @@ import { capitalize, shortDate } from 'shared/utils.mjs'
|
|||
|
||||
export const ns = ['common', 'core-settings', 'ui-settings']
|
||||
|
||||
const ZoomInIcon = (props) => (
|
||||
<IconWrapper {...props}>
|
||||
<path d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6" />
|
||||
</IconWrapper>
|
||||
)
|
||||
|
||||
const ZoomOutIcon = (props) => (
|
||||
<IconWrapper {...props}>
|
||||
<path d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6" />
|
||||
</IconWrapper>
|
||||
)
|
||||
|
||||
const IconButton = ({ Icon, onClick, dflt = true, title, hide = false, extraClasses = '' }) => (
|
||||
<div className="tooltip tooltip-bottom tooltip-primary flex items-center" data-tip={title}>
|
||||
<button
|
||||
|
@ -49,13 +37,13 @@ const IconButton = ({ Icon, onClick, dflt = true, title, hide = false, extraClas
|
|||
)
|
||||
|
||||
const smZoomClasses =
|
||||
'[.mobile-menubar_&]:btn [.mobile-menubar_&]:btn-secondary [.mobile-menubar_&]:btn-circle [.mobile-menubar_&]:my-2'
|
||||
'[.mobile-menubar_&]:btn [.mobile-menubar_&]:btn-secondary [.mobile-menubar_&]:btn-circle [.mobile-menubar_&]:my-1'
|
||||
const ZoomButtons = ({ t, zoomFunctions, zoomed }) => {
|
||||
if (!zoomFunctions) return null
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row items-center lg:content-center lg:gap-4">
|
||||
<IconButton
|
||||
Icon={ClearIcon}
|
||||
Icon={ResetIcon}
|
||||
onClick={zoomFunctions.reset}
|
||||
title={t('resetZoom')}
|
||||
hide={!zoomed}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue