Skip to content

Commit

Permalink
feat(Delimiter): add delimiter for object inline (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
NasgulNexus authored Mar 13, 2024
1 parent 5d4e7d2 commit 5012d5d
Show file tree
Hide file tree
Showing 36 changed files with 232 additions and 36 deletions.
1 change: 1 addition & 0 deletions docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ type Spec = ArraySpec | BooleanSpec | NumberSpec | ObjectSpec | StringSpec;
| viewSpec.oneOfParams | `object` | | [Parameters](#oneofparams) that must be passed to oneof input |
| viewSpec.placeholder | `string` | | A short hint displayed in the field before the user enters the value |
| viewSpec.hidden | `boolean` | | Hide field and view |
| viewSpec.delimiter | `Record<string, string>` | | Values of delimiters of inline object input elements |

### StringSpec

Expand Down
1 change: 1 addition & 0 deletions src/lib/core/types/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export interface ObjectSpec<
hidden?: boolean;
inputProps?: InputComponentProps;
layoutProps?: LayoutComponentProps;
delimiter?: Record<string, string>;
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/lib/kit/components/Inputs/ObjectBase/ObjectBase.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@
}
}
}

&__delimiter {
display: flex;
margin-right: 8px;
align-items: center;
white-space: nowrap;
}
}
28 changes: 18 additions & 10 deletions src/lib/kit/components/Inputs/ObjectBase/ObjectBase.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {Plus} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';
import {Button, Icon, Text} from '@gravity-ui/uikit';
import isObjectLike from 'lodash/isObjectLike';
import set from 'lodash/set';

Expand Down Expand Up @@ -81,24 +81,32 @@ export const ObjectBase: React.FC<ObjectBaseProps> = ({
? filterPropertiesForObjectInline(spec.properties)
: spec.properties;

const delimiter = spec.viewSpec.delimiter;
const orderProperties = spec.viewSpec.order || Object.keys(specProperties);

return (
<div className={b('content', {inline})}>
{(spec.viewSpec.order || Object.keys(specProperties)).map((property: string) =>
{orderProperties.map((property: string) =>
specProperties[property] ? (
<Controller
value={restProps.input.value?.[property]}
spec={specProperties[property]}
name={`${name ? name + '.' : ''}${property}`}
parentOnChange={parentOnChange}
parentOnUnmount={restProps.input.parentOnUnmount}
key={`${name ? name + '.' : ''}${property}`}
/>
<React.Fragment key={`${name ? name + '.' : ''}${property}`}>
<Controller
value={restProps.input.value?.[property]}
spec={specProperties[property]}
name={`${name ? name + '.' : ''}${property}`}
parentOnChange={parentOnChange}
parentOnUnmount={restProps.input.parentOnUnmount}
/>
{delimiter && delimiter[property] ? (
<Text className={b('delimiter')}>{delimiter[property]}</Text>
) : null}
</React.Fragment>
) : null,
)}
</div>
);
}, [
spec.properties,
spec.viewSpec.delimiter,
spec.viewSpec.order,
restProps.input.value,
restProps.input.parentOnUnmount,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {OBJECT_BASE, VALUE} from './helpers';
import {OBJECT_BASE, OBJECT_INLINE, VALUE, VALUE_INLINE} from './helpers';

import {test} from '~playwright/core';
import {DynamicForm} from '~playwright/core/DynamicForm';
Expand Down Expand Up @@ -75,8 +75,36 @@ test.describe('Object Base', () => {
});
});

test.describe('Object Inline', () => {
test('default', async ({mount, expectScreenshot}) => {
await mount(<DynamicForm spec={OBJECT_INLINE.default} />);

await expectScreenshot();
});

test('delimiter', async ({mount, expectScreenshot}) => {
await mount(<DynamicForm spec={OBJECT_INLINE.delimiter} />);

await expectScreenshot();
});
});

test('Object Base view', async ({mount, expectScreenshot}) => {
await mount(<DynamicView spec={OBJECT_BASE.default} value={VALUE} />);

await expectScreenshot();
});

test.describe('Object Inline view', () => {
test('default', async ({mount, expectScreenshot}) => {
await mount(<DynamicView spec={OBJECT_INLINE.default} value={VALUE_INLINE} />);

await expectScreenshot();
});

test('delimiter', async ({mount, expectScreenshot}) => {
await mount(<DynamicView spec={OBJECT_INLINE.delimiter} value={VALUE_INLINE} />);

await expectScreenshot();
});
});
66 changes: 66 additions & 0 deletions src/lib/kit/components/Inputs/ObjectBase/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,73 @@ export const OBJECT_BASE: Record<string, ObjectSpec> = {
},
};

export const OBJECT_INLINE: Record<string, ObjectSpec> = {
default: {
type: SpecTypes.Object,
defaultValue: {type: 'first', name: 'Name'},
properties: {
type: {
type: SpecTypes.String,
enum: ['first', 'second', 'third'],
viewSpec: {
type: 'select',
placeholder: 'Choose type',
layout: 'transparent',
layoutTitle: 'Type',
},
},
name: {
type: SpecTypes.String,
viewSpec: {
type: 'base',
placeholder: 'Type your name',
layout: 'transparent',
layoutTitle: 'Name',
},
},
},
viewSpec: {
type: 'inline',
layout: 'row',
layoutTitle: 'Candidate',
},
},
delimiter: {
type: SpecTypes.Object,
defaultValue: {type: 'first', name: 'Name'},
properties: {
type: {
type: SpecTypes.String,
enum: ['first', 'second', 'third'],
viewSpec: {
type: 'select',
placeholder: 'Choose type',
layout: 'transparent',
layoutTitle: 'Type',
},
},
name: {
type: SpecTypes.String,
viewSpec: {
type: 'base',
placeholder: 'Type your name',
layout: 'transparent',
layoutTitle: 'Name',
},
},
},
viewSpec: {
type: 'inline',
layout: 'row',
layoutTitle: 'Candidate',
delimiter: {type: ':'},
},
},
};

export const VALUE: FormValue = {
name: 'name',
age: 10,
};

export const VALUE_INLINE: FormValue = {type: 'first', name: 'Name'};
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@
}
}
}

&__delimiter {
display: flex;
margin-right: 8px;
align-items: center;
white-space: nowrap;
}
}
52 changes: 31 additions & 21 deletions src/lib/kit/components/Views/ObjectBaseView/ObjectBaseView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import isObjectLike from 'lodash/isObjectLike';
import {Text} from '@gravity-ui/uikit';

import {ObjectIndependentView, ObjectIndependentViewProps, ViewController} from '../../../../core';
import {block, filterPropertiesForObjectInline} from '../../../utils';
Expand All @@ -20,29 +21,38 @@ export const ObjectBaseView: React.FC<ObjectBaseViewProps> = ({
Layout,
...restProps
}) => {
if (!spec.properties || !isObjectLike(spec.properties)) {
return null;
}
const content = React.useMemo(() => {
if (!spec.properties || !isObjectLike(spec.properties)) {
return null;
}

const specProperties = inline
? filterPropertiesForObjectInline(spec.properties)
: spec.properties;

const content = (
<div className={b('content', {inline})}>
{(spec.viewSpec.order || Object.keys(specProperties)).map((property: string) =>
specProperties[property] ? (
<ViewController
spec={specProperties[property]}
name={`${name ? name + '.' : ''}${property}`}
key={`${name ? name + '.' : ''}${property}`}
/>
) : null,
)}
</div>
);
const specProperties = inline
? filterPropertiesForObjectInline(spec.properties)
: spec.properties;

const delimiter = spec.viewSpec.delimiter;
const orderProperties = spec.viewSpec.order || Object.keys(specProperties);

return (
<div className={b('content', {inline})}>
{orderProperties.map((property: string) =>
specProperties[property] ? (
<React.Fragment key={`${name ? name + '.' : ''}${property}`}>
<ViewController
spec={specProperties[property]}
name={`${name ? name + '.' : ''}${property}`}
/>
{delimiter && delimiter[property] ? (
<Text className={b('delimiter')}>{delimiter[property]}</Text>
) : null}
</React.Fragment>
) : null,
)}
</div>
);
}, [inline, name, spec.properties, spec.viewSpec.delimiter, spec.viewSpec.order]);

if (!Layout) {
if (!Layout || !content) {
return content;
}

Expand Down
7 changes: 6 additions & 1 deletion src/stories/ObjectBase.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ const baseSpec: ObjectSpec = {

const value = {name: 'Foo', age: 13, license: false};

const excludeOptions = ['description', 'viewSpec.type', 'viewSpec.oneOfParams'];
const excludeOptions = [
'description',
'viewSpec.type',
'viewSpec.oneOfParams',
'viewSpec.delimiter',
];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof ObjectBase> = (__, {viewMode}) => (
Expand Down
2 changes: 1 addition & 1 deletion src/stories/ObjectCardOneOf.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const baseSpec: ObjectSpec = {
},
};

const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder'];
const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder', 'viewSpec.delimiter'];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof CardOneOfBase> = (__, {viewMode}) => (
Expand Down
4 changes: 4 additions & 0 deletions src/stories/ObjectInline.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const baseSpec: ObjectSpec = {
type: 'inline',
layout: 'row',
layoutTitle: 'Candidate',
delimiter: {
type: ':',
name: '-',
},
},
};

Expand Down
1 change: 1 addition & 0 deletions src/stories/ObjectMultiOneOf.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const excludeOptions = [
'viewSpec.itemLabel',
'viewSpec.table',
'viewSpec.oneOfParams',
'viewSpec.delimiter',
];

const value = {
Expand Down
1 change: 1 addition & 0 deletions src/stories/ObjectMultiOneOfFlat.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const excludeOptions = [
'viewSpec.itemLabel',
'viewSpec.table',
'viewSpec.oneOfParams',
'viewSpec.delimiter',
];

const value = {
Expand Down
2 changes: 1 addition & 1 deletion src/stories/ObjectOneOf.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const baseSpec: ObjectSpec = {
},
};

const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder'];
const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder', 'viewSpec.delimiter'];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfBase> = (__, {viewMode}) => (
Expand Down
2 changes: 1 addition & 1 deletion src/stories/ObjectOneOfFlat.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const baseSpec: ObjectSpec = {
},
};

const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder'];
const excludeOptions = ['viewSpec.type', 'viewSpec.placeholder', 'viewSpec.delimiter'];

const template = (spec: ObjectSpec = baseSpec) => {
const Template: StoryFn<typeof OneOfFlatBase> = (__, {viewMode}) => (
Expand Down
1 change: 1 addition & 0 deletions src/stories/ObjectSecret.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const excludeOptions = [
'viewSpec.disabled',
'viewSpec.oneOfParams',
'viewSpec.placeholder',
'viewSpec.delimiter',
];

const template = (spec: ObjectSpec = baseSpec) => {
Expand Down
1 change: 1 addition & 0 deletions src/stories/ObjectTextLink.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const excludeOptions = [
'viewSpec.disabled',
'viewSpec.oneOfParams',
'viewSpec.placeholder',
'viewSpec.delimiter',
];

const template = (spec: ObjectSpec = baseSpec) => {
Expand Down
1 change: 1 addition & 0 deletions src/stories/ObjectValue.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const excludeOptions = [
'viewSpec.disabled',
'viewSpec.oneOfParams',
'viewSpec.placeholder',
'viewSpec.delimiter',
];

const template = (spec: ObjectSpec = baseSpec) => {
Expand Down
Loading

0 comments on commit 5012d5d

Please sign in to comment.