Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for product export in UI #8281

Merged
merged 2 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { ModuleRegistrationName } from "@medusajs/utils"
jest.setTimeout(50000)

const compareCSVs = async (filePath, expectedFilePath) => {
let fileContent = await fs.readFile(filePath, { encoding: "utf-8" })
const asLocalPath = filePath.replace("http://localhost:9000", process.cwd())
let fileContent = await fs.readFile(asLocalPath, { encoding: "utf-8" })
let fixturesContent = await fs.readFile(expectedFilePath, {
encoding: "utf-8",
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ export type Filter = {

type DataTableFilterProps = {
filters: Filter[]
readonly?: boolean
prefix?: string
}

export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
export const DataTableFilter = ({
filters,
readonly,
prefix,
}: DataTableFilterProps) => {
const { t } = useTranslation()
const [searchParams] = useSearchParams()
const [open, setOpen] = useState(false)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Can't we rely solely on the query parameters for the activeFilters state? I feel like it should be possible, and we can remove some code around maintaining their state (so basically we have getInitialFilters be the state, and that gets memoized with location.search passed to it)

Expand Down Expand Up @@ -127,6 +132,7 @@ export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
key={filter.key}
filter={filter}
prefix={prefix}
readonly={readonly}
options={filter.options}
multiple={filter.multiple}
searchable={filter.searchable}
Expand All @@ -139,6 +145,7 @@ export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
key={filter.key}
filter={filter}
prefix={prefix}
readonly={readonly}
openOnMount={filter.openOnMount}
/>
)
Expand All @@ -148,6 +155,7 @@ export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
key={filter.key}
filter={filter}
prefix={prefix}
readonly={readonly}
openOnMount={filter.openOnMount}
/>
)
Expand All @@ -157,14 +165,15 @@ export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
key={filter.key}
filter={filter}
prefix={prefix}
readonly={readonly}
openOnMount={filter.openOnMount}
/>
)
default:
break
}
})}
{availableFilters.length > 0 && (
{!readonly && availableFilters.length > 0 && (
<Popover.Root modal open={open} onOpenChange={setOpen}>
<Popover.Trigger asChild id="filters_menu_trigger">
<Button size="small" variant="secondary">
Expand Down Expand Up @@ -208,7 +217,7 @@ export const DataTableFilter = ({ filters, prefix }: DataTableFilterProps) => {
</Popover.Portal>
</Popover.Root>
)}
{activeFilters.length > 0 && (
{!readonly && activeFilters.length > 0 && (
<ClearAllFilters filters={filters} prefix={prefix} />
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type DateComparisonOperator = {
export const DateFilter = ({
filter,
prefix,
readonly,
openOnMount,
}: DateFilterProps) => {
const [open, setOpen] = useState(openOnMount)
Expand Down Expand Up @@ -118,123 +119,136 @@ export const DateFilter = ({

return (
<Popover.Root modal open={open} onOpenChange={handleOpenChange}>
<DateDisplay label={label} value={displayValue} onRemove={handleRemove} />
<Popover.Portal>
<Popover.Content
data-name="date_filter_content"
align="start"
sideOffset={8}
collisionPadding={24}
className={clx(
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout h-full max-h-[var(--radix-popper-available-height)] w-[300px] overflow-auto rounded-lg"
)}
onInteractOutside={(e) => {
if (e.target instanceof HTMLElement) {
if (
e.target.attributes.getNamedItem("data-name")?.value ===
"filters_menu_content"
) {
e.preventDefault()
<DateDisplay
label={label}
value={displayValue}
onRemove={handleRemove}
readonly={readonly}
/>
{!readonly && (
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are just indentation changes, no actual code changed other than the readonly check.

<Popover.Portal>
<Popover.Content
data-name="date_filter_content"
align="start"
sideOffset={8}
collisionPadding={24}
className={clx(
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout h-full max-h-[var(--radix-popper-available-height)] w-[300px] overflow-auto rounded-lg"
)}
onInteractOutside={(e) => {
if (e.target instanceof HTMLElement) {
if (
e.target.attributes.getNamedItem("data-name")?.value ===
"filters_menu_content"
) {
e.preventDefault()
}
}
}
}}
>
<ul className="w-full p-1">
{presets.map((preset) => {
const isSelected = selectedParams
.get()
.includes(JSON.stringify(preset.value))
return (
<li key={preset.label}>
<button
className="bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none"
type="button"
onClick={() => {
handleSelectPreset(preset.value)
}}
>
<div
className={clx(
"transition-fg flex h-5 w-5 items-center justify-center",
{
"[&_svg]:invisible": !isSelected,
}
)}
}}
>
<ul className="w-full p-1">
{presets.map((preset) => {
const isSelected = selectedParams
.get()
.includes(JSON.stringify(preset.value))
return (
<li key={preset.label}>
<button
className="bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none"
type="button"
onClick={() => {
handleSelectPreset(preset.value)
}}
>
<EllipseMiniSolid />
</div>
{preset.label}
</button>
</li>
)
})}
<li>
<button
className="bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none"
type="button"
onClick={handleSelectCustom}
>
<div
className={clx(
"transition-fg flex h-5 w-5 items-center justify-center",
{
"[&_svg]:invisible": !showCustom,
}
)}
<div
className={clx(
"transition-fg flex h-5 w-5 items-center justify-center",
{
"[&_svg]:invisible": !isSelected,
}
)}
>
<EllipseMiniSolid />
</div>
{preset.label}
</button>
</li>
)
})}
<li>
<button
className="bg-ui-bg-base hover:bg-ui-bg-base-hover focus-visible:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex w-full cursor-pointer select-none items-center rounded-md px-2 py-1.5 outline-none transition-colors data-[disabled]:pointer-events-none"
type="button"
onClick={handleSelectCustom}
>
<EllipseMiniSolid />
</div>
{t("filters.date.custom")}
</button>
</li>
</ul>
{showCustom && (
<div className="border-t px-1 pb-3 pt-1">
<div>
<div className="px-2 py-1">
<Text size="xsmall" leading="compact" weight="plus">
{t("filters.date.from")}
</Text>
</div>
<div className="px-2 py-1">
<DatePicker
maxValue={customEndValue}
value={customStartValue}
onChange={(d) => handleCustomDateChange(d, "start")}
/>
</div>
</div>
<div>
<div className="px-2 py-1">
<Text size="xsmall" leading="compact" weight="plus">
{t("filters.date.to")}
</Text>
<div
className={clx(
"transition-fg flex h-5 w-5 items-center justify-center",
{
"[&_svg]:invisible": !showCustom,
}
)}
>
<EllipseMiniSolid />
</div>
{t("filters.date.custom")}
</button>
</li>
</ul>
{showCustom && (
<div className="border-t px-1 pb-3 pt-1">
<div>
<div className="px-2 py-1">
<Text size="xsmall" leading="compact" weight="plus">
{t("filters.date.from")}
</Text>
</div>
<div className="px-2 py-1">
<DatePicker
maxValue={customEndValue}
value={customStartValue}
onChange={(d) => handleCustomDateChange(d, "start")}
/>
</div>
</div>
<div className="px-2 py-1">
<DatePicker
minValue={customStartValue}
value={customEndValue || undefined}
onChange={(d) => {
handleCustomDateChange(d, "end")
}}
/>
<div>
<div className="px-2 py-1">
<Text size="xsmall" leading="compact" weight="plus">
{t("filters.date.to")}
</Text>
</div>
<div className="px-2 py-1">
<DatePicker
minValue={customStartValue}
value={customEndValue || undefined}
onChange={(d) => {
handleCustomDateChange(d, "end")
}}
/>
</div>
</div>
</div>
</div>
)}
</Popover.Content>
</Popover.Portal>
)}
</Popover.Content>
</Popover.Portal>
)}
</Popover.Root>
)
}

type DateDisplayProps = {
label: string
value?: string
readonly?: boolean
onRemove: () => void
}

const DateDisplay = ({ label, value, onRemove }: DateDisplayProps) => {
const DateDisplay = ({
label,
value,
readonly,
onRemove,
}: DateDisplayProps) => {
const handleRemove = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
onRemove()
Expand All @@ -245,8 +259,10 @@ const DateDisplay = ({ label, value, onRemove }: DateDisplayProps) => {
asChild
className={clx(
"bg-ui-bg-field transition-fg shadow-borders-base text-ui-fg-subtle flex cursor-pointer select-none items-center rounded-md",
"hover:bg-ui-bg-field-hover",
"data-[state=open]:bg-ui-bg-field-hover"
{
"hover:bg-ui-bg-field-hover": !readonly,
"data-[state=open]:bg-ui-bg-field-hover": !readonly,
}
)}
>
<div>
Expand All @@ -268,7 +284,7 @@ const DateDisplay = ({ label, value, onRemove }: DateDisplayProps) => {
</div>
</div>
)}
{value && (
{!readonly && value && (
<div>
<button
onClick={handleRemove}
Expand Down
Loading
Loading