Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
fea4342
add base listing block component
nileshgulia1 Mar 17, 2026
2927d92
feat(QuerystringWidget): add Querystring Widget for seven
nileshgulia1 Mar 19, 2026
20f5feb
refactor: remove listing block edits
nileshgulia1 Mar 19, 2026
116ddbf
Merge branch 'seven' into seven-querystring
nileshgulia1 Mar 19, 2026
3cd04b5
fix: eslint
nileshgulia1 Mar 19, 2026
a7b584b
refactor: get Querystring options for criteria from backend
nileshgulia1 Mar 19, 2026
34559ed
Merge branch 'seven' into seven-querystring
nileshgulia1 Mar 20, 2026
76f3a57
Merge branch 'seven' into seven-querystring
nileshgulia1 May 18, 2026
93f1036
refactor: use Selects from quanta
nileshgulia1 May 18, 2026
73da4b8
chore: update changelog
nileshgulia1 May 18, 2026
c3c6226
Merge branch 'seven' into seven-querystring
nileshgulia1 May 19, 2026
45d3070
feat: add ComboBox.quanta and use it in Select for queryString
nileshgulia1 May 19, 2026
2d25f9c
Merge branch 'seven' into seven-querystring
nileshgulia1 May 19, 2026
ef68b6d
fix Combobox.quanta import
nileshgulia1 May 19, 2026
eeb54e6
refactor: add missing file querystringSearch
nileshgulia1 May 19, 2026
acc5311
chore: update changelog
nileshgulia1 May 19, 2026
57ca619
Merge branch 'seven' into seven-querystring
nileshgulia1 May 21, 2026
202d8fe
fix: use textWidget with type 'number' instead of NumberField
nileshgulia1 Jun 1, 2026
f66df64
Merge branch 'seven' into seven-querystring
nileshgulia1 Jun 1, 2026
4c3e765
Merge branch 'seven' into seven-querystring
nileshgulia1 Jun 3, 2026
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
@@ -0,0 +1,386 @@
import { useMemo } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import {
RouterProvider,
createMemoryRouter,
type LoaderFunctionArgs,
} from 'react-router';
import { fn } from 'storybook/test';
import type { QuerystringValue } from './QuerystringWidgetContext';
import { QuerystringWidget } from './QuerystringWidget';

interface QuerystringWidgetStoryProps {
label?: string;
description?: string;
errorMessage?: string;
value?: QuerystringValue;
defaultValue?: QuerystringValue;
onChange?: (value: QuerystringValue) => void;
onPatchFormData?: (partial: Record<string, unknown>) => void;
}

const createQuerystringLoader = () => {
return ({ request }: LoaderFunctionArgs) => {
return {
content: {
'@id': '/Test/Document',
},
};
};
};

const createQuerystringRouter = (props: QuerystringWidgetStoryProps) =>
createMemoryRouter(
[
{
id: 'root',
path: '/',
loader: createQuerystringLoader(),
element: (
<div className="min-h-screen bg-white p-8">
<div className="max-w-2xl">
<QuerystringWidget {...(props as any)} />
</div>
</div>
),
},
{
path: '/@queryStringOptions',
loader: () => ({
indexes: {
Creator: {
title: 'Creator',
description: 'The person that created an item',
enabled: true,
sortable: true,
group: 'Metadata',
operators: {
is: { title: 'Is', description: null, widget: null },
},
},
Title: {
title: 'Title',
description: "Text search of an item's title",
enabled: true,
sortable: false,
group: 'Text',
operators: {
has: { title: 'Contains', description: null, widget: null },
},
},
Subject: {
title: 'Tag',
description: 'Tags are used for organization of content',
enabled: true,
sortable: false,
group: 'Text',
operators: {
is: { title: 'Is', description: null, widget: null },
},
},
path: {
title: 'Location',
description: 'The location of an item',
enabled: true,
sortable: false,
group: 'Metadata',
operators: {
is: {
title: 'Navigation path',
description: null,
widget: null,
},
},
},
modified: {
title: 'Modification date',
description: 'The time and date an item was last modified',
enabled: true,
sortable: true,
group: 'Dates',
operators: {
before: {
title: 'Before date',
description: null,
widget: null,
},
after: { title: 'After date', description: null, widget: null },
},
},
created: {
title: 'Creation date',
description: 'The date an item was created',
enabled: true,
sortable: true,
group: 'Dates',
operators: {
before: {
title: 'Before date',
description: null,
widget: null,
},
after: { title: 'After date', description: null, widget: null },
},
},
review_state: {
title: 'Review state',
description: "An item's workflow state (e.g.published)",
enabled: true,
sortable: true,
group: 'Metadata',
operators: {
is: { title: 'Is', description: null, widget: null },
},
values: {
published: { title: 'Published' },
pending: { title: 'Pending review' },
private: { title: 'Private' },
},
},
portal_type: {
title: 'Type',
description: "An item's type (e.g. Event)",
enabled: true,
sortable: false,
group: 'Metadata',
operators: {
is: { title: 'Is', description: null, widget: null },
},
values: {
Document: { title: 'Page' },
Folder: { title: 'Folder' },
Image: { title: 'Image' },
File: { title: 'File' },
Event: { title: 'Event' },
},
},
},
}),
},
{
path: '/@querystringSearch',
loader: () => ({
items: [
{
'@id': '/Test/example-news-item',
'@type': 'News Item',
title: 'Example news item',
description: 'A sample result for the query-string search.',
},
{
'@id': '/Test/example-page',
'@type': 'Document',
title: 'Example page',
description: 'Another sample result.',
},
],
items_total: 2,
}),
},
],
{
initialEntries: ['/'],
},
);

const StoryRouter = (props: QuerystringWidgetStoryProps) => {
const router = useMemo(() => createQuerystringRouter(props), [props]);
return <RouterProvider router={router} />;
};

const meta = {
component: QuerystringWidget,
parameters: {
layout: 'fullscreen',
backgrounds: { disable: true },
},
tags: ['autodocs'],
args: {
label: 'Search Criteria',
description: 'Define search criteria to filter content',
onChange: fn(),
onPatchFormData: fn(),
},
} satisfies Meta<QuerystringWidgetStoryProps>;

export default meta;
type Story = StoryObj<typeof meta>;

/**
* Default empty state of the QuerystringWidget with no criteria
*/
export const Default: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
};

/**
* QuerystringWidget with a single criterion
*/
export const WithSingleCriterion: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
value: {
query: [
{
i: 'Creator',
o: 'is',
v: 'admin',
},
],
sort_on: 'Title',
sort_order: 'ascending',
limit: 100,
b_size: 50,
} as QuerystringValue,
},
};

/**
* QuerystringWidget with multiple criteria
*/
export const WithMultipleCriteria: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
value: {
query: [
{
i: 'Creator',
o: 'is',
v: 'admin',
},
{
i: 'Title',
o: 'has',
v: 'Document',
},
{
i: 'modified',
o: 'before',
v: '2024-12-31',
},
],
sort_on: 'modified',
sort_order: 'descending',
limit: 50,
b_size: 25,
} as QuerystringValue,
},
};

/**
* QuerystringWidget with path criterion (shows depth field)
*/
export const WithPathCriterionAndDepth: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
value: {
query: [
{
i: 'path',
o: 'is',
v: '/Test/Folder',
},
{
i: 'review_state',
o: 'is',
v: 'published',
},
],
depth: 2,
sort_on: 'Title',
sort_order: 'ascending',
limit: 100,
b_size: 50,
} as QuerystringValue,
},
};

/**
* QuerystringWidget in error state
*/
export const WithError: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
label: 'Search Criteria',
description: 'Define search criteria to filter content',
errorMessage: 'Please check your search criteria',
value: {
query: [
{
i: 'Creator',
o: 'is',
v: '',
},
],
} as QuerystringValue,
},
};

/**
* QuerystringWidget with all options configured
*/
export const FullyConfigured: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
label: 'Advanced Search',
description:
'Build complex search queries by adding multiple criteria. Criteria are combined with AND logic.',
value: {
query: [
{
i: 'Title',
o: 'has',
v: 'news',
},
{
i: 'Creator',
o: 'is',
v: 'site_owner',
},
{
i: 'modified',
o: 'after',
v: '2024-01-01',
},
{
i: 'review_state',
o: 'is',
v: 'published',
},
],
sort_on: 'modified',
sort_order: 'descending',
limit: 200,
b_size: 25,
} as QuerystringValue,
},
};

/**
* QuerystringWidget with complex date-based criteria
*/
export const WithDateCriteria: Story = {
render: (args) => <StoryRouter {...(args as any)} />,
args: {
label: 'Date-based Search',
description: 'Filter content by creation and modification dates',
value: {
query: [
{
i: 'created',
o: 'after',
v: '2024-01-01',
},
{
i: 'modified',
o: 'before',
v: '2024-12-31',
},
],
sort_on: 'created',
sort_order: 'descending',
limit: 50,
b_size: 10,
} as QuerystringValue,
},
};
Loading
Loading