2025-04-01 16:15:20 +02:00
|
|
|
import React from 'react'
|
|
|
|
import mustache from 'mustache'
|
2025-05-30 11:29:55 +02:00
|
|
|
import { flattenFlags } from '../lib/index.mjs'
|
2025-04-01 16:15:20 +02:00
|
|
|
import {
|
|
|
|
ChatIcon,
|
|
|
|
ErrorIcon,
|
|
|
|
ExpandIcon,
|
|
|
|
DocsIcon,
|
|
|
|
FixmeIcon,
|
|
|
|
FlagIcon,
|
|
|
|
OptionsIcon,
|
|
|
|
TipIcon,
|
|
|
|
WarningIcon,
|
|
|
|
WrenchIcon,
|
|
|
|
} from '@freesewing/react/components/Icon'
|
|
|
|
import { SubAccordion } from './Accordion.mjs'
|
|
|
|
import { MiniTip, MiniNote } from '@freesewing/react/components/Mini'
|
|
|
|
import Markdown from 'react-markdown'
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper object to look up flag icons
|
|
|
|
*/
|
|
|
|
const flagIcons = {
|
|
|
|
error: ErrorIcon,
|
|
|
|
expand: ExpandIcon,
|
|
|
|
fixme: WrenchIcon,
|
|
|
|
info: DocsIcon,
|
|
|
|
note: ChatIcon,
|
|
|
|
otions: OptionsIcon,
|
|
|
|
tip: TipIcon,
|
|
|
|
warning: WarningIcon,
|
|
|
|
}
|
|
|
|
|
2025-04-18 08:07:13 +00:00
|
|
|
export const FlagTypeIcon = ({ type, className = 'tw:w-6 tw:h-6' }) => {
|
2025-04-01 16:15:20 +02:00
|
|
|
const Icon = flagIcons[type] || FixmeIcon
|
|
|
|
|
|
|
|
return <Icon className={className} />
|
|
|
|
}
|
|
|
|
|
|
|
|
export const Flag = ({ data, handleUpdate, strings }) => {
|
|
|
|
const btnIcon = data.suggest?.icon ? (
|
2025-04-18 08:07:13 +00:00
|
|
|
<FlagTypeIcon type={data.suggest.icon} className="tw:w-5 tw:h-6 tw:sm:w-6 tw:h-6" />
|
2025-04-01 16:15:20 +02:00
|
|
|
) : null
|
|
|
|
|
|
|
|
const button =
|
|
|
|
data.suggest?.text && data.suggest?.update ? (
|
|
|
|
<button
|
2025-04-18 08:07:13 +00:00
|
|
|
className={`tw:daisy-btn tw:daisy-btn-secondary tw:daisy-btn-outline tw:flex tw:flex-row tw:items-center ${
|
|
|
|
btnIcon ? 'tw:gap-6' : ''
|
2025-04-01 16:15:20 +02:00
|
|
|
}`}
|
|
|
|
onClick={() => handleUpdate(data.suggest.update)}
|
|
|
|
>
|
|
|
|
{btnIcon}
|
|
|
|
{strings[data.suggest.text] || data.suggest.text}
|
|
|
|
</button>
|
|
|
|
) : null
|
|
|
|
|
|
|
|
const desc = data.replace
|
|
|
|
? mustache.render(strings[data.desc] || data.desc, data.replace)
|
|
|
|
: strings[data.desc] || data.desc
|
|
|
|
const notes = data.notes
|
|
|
|
? Array.isArray(data.notes)
|
|
|
|
? '\n\n' +
|
|
|
|
data.notes
|
|
|
|
.map((note) =>
|
|
|
|
data.replace
|
|
|
|
? mustache.render(strings[note] || note, data.replace)
|
|
|
|
: strings[note] || note
|
|
|
|
)
|
|
|
|
.join('\n\n')
|
|
|
|
: '\n\n' +
|
|
|
|
(data.replace
|
|
|
|
? mustache.render(strings[data.notes] || data.notes, data.replace)
|
|
|
|
: strings[data.notes] || data.notes)
|
|
|
|
: null
|
|
|
|
|
|
|
|
return (
|
2025-04-18 08:07:13 +00:00
|
|
|
<div className="tw:flex tw:flex-col tw:gap-2 tw:items-start">
|
|
|
|
<div className="tw:first:mt-0 tw:grow md flag tw:flex tw:flex-col tw:gap-2">
|
2025-04-01 16:15:20 +02:00
|
|
|
{desc ? (
|
|
|
|
<MiniTip>
|
|
|
|
<Markdown>{strings[desc] || desc}</Markdown>
|
|
|
|
</MiniTip>
|
|
|
|
) : null}
|
|
|
|
{notes ? (
|
|
|
|
<MiniNote>
|
|
|
|
<Markdown>{strings[notes] || notes}</Markdown>
|
|
|
|
</MiniNote>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
{button ? (
|
2025-04-18 08:07:13 +00:00
|
|
|
<div className="tw:mt-2 tw:w-full tw:flex tw:flex-row tw:justify-end">{button}</div>
|
2025-04-01 16:15:20 +02:00
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const FlagsAccordionTitle = ({ flags }) => {
|
|
|
|
const flagList = flattenFlags(flags)
|
|
|
|
|
|
|
|
if (Object.keys(flagList).length < 1) return null
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2025-04-18 08:07:13 +00:00
|
|
|
<h5 className="tw:flex tw:flex-row tw:gap-2 tw:items-center tw:justify-between tw:w-full">
|
|
|
|
<span className="tw:text-left">Flags ({Object.keys(flagList).length})</span>
|
|
|
|
<FlagTypeIcon className="tw:w-8 tw:h-8" />
|
2025-04-01 16:15:20 +02:00
|
|
|
</h5>
|
2025-04-18 08:07:13 +00:00
|
|
|
<p className="tw:text-left">
|
2025-04-01 16:15:20 +02:00
|
|
|
{Object.keys(flagList).length > 1
|
|
|
|
? 'Some issues about your current pattern need your attention.'
|
|
|
|
: 'A specific issue about your current pattern needs your attention.'}
|
|
|
|
</p>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-05-30 11:29:55 +02:00
|
|
|
export const FlagsAccordionEntries = ({ flags, update, strings }) => {
|
2025-04-01 16:15:20 +02:00
|
|
|
const flagList = flattenFlags(flags)
|
|
|
|
|
|
|
|
if (Object.keys(flagList).length < 1) return null
|
|
|
|
|
|
|
|
const handleUpdate = (config) => {
|
|
|
|
if (config.settings) update.settings(...config.settings)
|
|
|
|
if (config.ui) update.ui(...config.settings)
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<SubAccordion
|
|
|
|
items={Object.entries(flagList).map(([key, flag], i) => {
|
|
|
|
const title = flag.replace ? mustache.render(flag.title, flag.replace) : flag.title
|
|
|
|
|
|
|
|
return [
|
2025-04-18 08:07:13 +00:00
|
|
|
<div className="tw:w-full tw:flex tw:flex-row tw:gap2 tw:justify-between" key={i}>
|
|
|
|
<div className="tw:flex tw:flex-row tw:items-center tw:gap-2">
|
|
|
|
<div className="tw:no-shrink">
|
2025-04-01 16:15:20 +02:00
|
|
|
<FlagIcon type={flag.type} />
|
|
|
|
</div>
|
2025-04-18 08:07:13 +00:00
|
|
|
<span className="tw:font-medium tw:text-left">{strings[title] || title}</span>
|
2025-04-01 16:15:20 +02:00
|
|
|
</div>
|
2025-04-18 08:07:13 +00:00
|
|
|
<span className="tw:uppercase tw:font-bold">{flag.type}</span>
|
2025-04-01 16:15:20 +02:00
|
|
|
</div>,
|
|
|
|
<Flag key={key} data={flag} strings={strings} handleUpdate={handleUpdate} />,
|
|
|
|
key,
|
|
|
|
]
|
|
|
|
})}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|