diff --git a/assets/js/src/examples/listings/components/custom-listing.tsx b/assets/js/src/examples/listings/components/custom-listing.tsx new file mode 100644 index 0000000..a971940 --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing.tsx @@ -0,0 +1,27 @@ +import { container } from '@pimcore/studio-ui-bundle' +import { BaseListing, DataObjectProvider, listingDefaultProps, type ObjectListingBuilder } from '@pimcore/studio-ui-bundle/modules/data-object' +import React from 'react' + +export const CustomListing = (): React.JSX.Element => { + const listingBuilder = container.get('Cars/Listing/Builder') + + return ( + + + + ) +} diff --git a/assets/js/src/examples/listings/components/custom-listing/decorator/header/header-decorator.tsx b/assets/js/src/examples/listings/components/custom-listing/decorator/header/header-decorator.tsx new file mode 100644 index 0000000..1ca581c --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing/decorator/header/header-decorator.tsx @@ -0,0 +1,11 @@ +import { type AbstractDecorator } from '@pimcore/studio-ui-bundle/modules/element' +import { withHeader } from './with-header' + +export const HeaderDecorator: AbstractDecorator = (props) => { + const { ViewComponent } = props + + return { + ...props, + ViewComponent: withHeader(ViewComponent) + } +} diff --git a/assets/js/src/examples/listings/components/custom-listing/decorator/header/with-header.tsx b/assets/js/src/examples/listings/components/custom-listing/decorator/header/with-header.tsx new file mode 100644 index 0000000..fac4367 --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing/decorator/header/with-header.tsx @@ -0,0 +1,23 @@ +import { ContentLayout, Header, Toolbar } from '@pimcore/studio-ui-bundle/components' +import { type AbstractDecoratorProps } from '@pimcore/studio-ui-bundle/modules/element' +import React from 'react' + +export const withHeader = (BaseComponent: AbstractDecoratorProps['ViewComponent']): AbstractDecoratorProps['ViewComponent'] => { + const HeaderComponent: AbstractDecoratorProps['ViewComponent'] = (props) => { + return ( + +
+ + } + > + + + ) + } + + return HeaderComponent +} diff --git a/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/pql-filter-decorator.tsx b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/pql-filter-decorator.tsx new file mode 100644 index 0000000..ba05db6 --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/pql-filter-decorator.tsx @@ -0,0 +1,15 @@ +import { type AbstractDecorator } from '@pimcore/studio-ui-bundle/modules/element' +import { withPqlFilterProvider } from './with-pql-filter-provider' +import { withPqlFilterSidebar } from './with-pql-filter-sidebar' +import { withPqlFilterQuery } from './with-pql-filter-query' + +export const PqlFilterDecorator: AbstractDecorator = (props) => { + const { useSidebarOptions, ContextComponent, useDataQueryHelper } = props + + return { + ...props, + ContextComponent: withPqlFilterProvider(ContextComponent), + useSidebarOptions: withPqlFilterSidebar(useSidebarOptions), + useDataQueryHelper: withPqlFilterQuery(useDataQueryHelper) + } +} diff --git a/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/provider/pql-filter-provider.tsx b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/provider/pql-filter-provider.tsx new file mode 100644 index 0000000..95e0f96 --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/provider/pql-filter-provider.tsx @@ -0,0 +1,32 @@ +import React, { createContext, useContext, useMemo, useState } from 'react' + +export interface IPqlFilterContext { + pqlFilter: string | null + setPqlFilter: (filter: string | null) => void +} + +export const PqlFilterContext = createContext(undefined) + +export interface IPqlFilterProviderProps { + children: React.ReactNode +} + +export const PqlFilterProvider = ({ children }: IPqlFilterProviderProps): React.JSX.Element => { + const [pqlFilter, setPqlFilter] = useState(null) + + return useMemo(() => ( + + {children} + + ), [pqlFilter, children]) +} + +export const usePqlFilterContext = (): IPqlFilterContext => { + const context = useContext(PqlFilterContext) + + if (context === undefined) { + throw new Error('usePqlFilterContext must be used within a PqlFilterProvider') + } + + return context +} diff --git a/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/sidebar/pql-sidebar.tsx b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/sidebar/pql-sidebar.tsx new file mode 100644 index 0000000..99dce54 --- /dev/null +++ b/assets/js/src/examples/listings/components/custom-listing/decorator/pql-filter/sidebar/pql-sidebar.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import { Content, ContentLayout, Header, Select } from '@pimcore/studio-ui-bundle/components' +import { usePqlFilterContext } from '../provider/pql-filter-provider' + +export interface predefinedPqlFilter { + label: string + pql: string +} + +export const PqlSidebar = (): React.JSX.Element => { + const { pqlFilter, setPqlFilter } = usePqlFilterContext() + const predefinedPqls: predefinedPqlFilter[] = [ + { label: 'All E-Type models which are green or produced before 1965.', pql: 'series = "E-Type" AND (color = "green" OR productionYear < 1965)' }, + { label: 'All Alfa cars produced after 1965', pql: 'manufacturer:Manufacturer.name = "Alfa" AND productionYear > 1965' }, + { label: 'All red or blue cars using standard PQL syntax.', pql: 'color = "red" OR color = "blue"' } + ] + + const options = predefinedPqls.map((filter) => ({ + label: filter.label, + value: filter.pql + })) + + return ( + + +
+ +