Skip to content
This repository has been archived by the owner on Jun 13, 2024. It is now read-only.

Commit

Permalink
feat: Matrix Job Support (#210)
Browse files Browse the repository at this point in the history
* feat/definition-styles

* feat: Matrix jobs prelim

* feat: made fields optiona

* feat: improved matrix style
  • Loading branch information
Jaryt authored Aug 9, 2022
1 parent 50df329 commit 5572635
Show file tree
Hide file tree
Showing 12 changed files with 357 additions and 176 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0-development",
"homepage": "https://circleci-public.github.io/visual-config-editor/",
"dependencies": {
"@circleci/circleci-config-sdk": "v0.9.0-alpha.8",
"@circleci/circleci-config-sdk": "v0.9.0-alpha.9",
"@craco/craco": "^6.3.0",
"@monaco-editor/react": "^4.3.1",
"algoliasearch": "^4.13.1",
Expand Down
2 changes: 1 addition & 1 deletion src/components/atoms/Definition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const Definition = (props: {
return (
<button
className="w-full mb-2 p-4 py-2 cursor-pointer text-left text-circle-black
bg-white border border-circle-gray-300 rounded-sm hover:border-gray-700 text-base"
bg-white border border-circle-gray-300 rounded-md2 hover:border-gray-700 text-base"
draggable="true"
onDragStart={(e) => {
const type = props.type;
Expand Down
40 changes: 28 additions & 12 deletions src/components/atoms/form/InspectorProperty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type InspectorFieldProps = {
onChange?: (e: any) => void;
children?: ReactElement[] | ReactElement;
dependent?: (value: any) => ReactElement;
pinned?: ReactElement;
};

const getField = (
Expand Down Expand Up @@ -57,16 +58,28 @@ const getField = (
{...field}
{...props}
className={`${props.type !== 'checkbox' ? 'w-full' : 'ml-auto'}
border rounded-sm p-2 px-4 shadow-sm hover:border-circle-black placeholder-circle-gray-500 hover:bg-white ${
!field.value && 'bg-circle-gray-50'
border rounded p-2 px-4 shadow-sm hover:border-circle-black placeholder-circle-gray-500 ${
!field.value && 'bg-circle-gray-100'
} ${error ? 'border-circle-red' : 'border-circle-gray-300'}`}
></Field>
)
);
};

const InspectorProperty = ({ label, ...props }: InspectorFieldProps) => {
const [field, meta, helper] = useField(props);
const InspectorProperty = (props: InspectorFieldProps) => {
const field = useField(props);
return <FieldlessInspectorProperty {...props} field={field} />;
};

export const FieldlessInspectorProperty = ({
label,
field,
pinned,
...props
}: InspectorFieldProps & {
field: [FieldInputProps<any>, FieldMetaProps<any>, FieldHelperProps<any>];
}) => {
const [input, meta, helper] = field;
const { touched, error, value } = meta;

// Sync form value to the prop value on mount
Expand All @@ -85,17 +98,20 @@ const InspectorProperty = ({ label, ...props }: InspectorFieldProps) => {
hidden={props.hidden}
>
<div className="flex flex-row mb-2">
<p className="font-medium text-sm my-auto text-circle-black">
<h3 className="font-medium text-sm my-auto text-circle-black">
{label}
</p>
</h3>
<InfoIcon className="w-5 flex my-auto p-1" color="#6A6A6A" />
{props.required && (
<span className="ml-auto leading-5 text-xs text-circle-black px-2 bg-circle-gray-300 rounded-full font-medium">
required
</span>
)}
<div className="ml-auto ">
{props.required && (
<span className="leading-5 text-xs text-circle-black px-2 bg-circle-gray-300 rounded-full font-medium">
required
</span>
)}
{pinned}
</div>
</div>
{getField(props, field, meta, helper, error)}
{getField(props, input, meta, helper, error)}
{touched && error && (
<span className="text-sm text-circle-red">{error}</span>
)}
Expand Down
199 changes: 119 additions & 80 deletions src/components/atoms/form/ListProperty.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { ArrayHelpers, FieldArray, useField } from 'formik';
import { ReactElement } from 'react';
import {
ArrayHelpers,
FieldArray,
FieldArrayRenderProps,
FieldHelperProps,
FieldInputProps,
FieldMetaProps,
useField,
} from 'formik';
import { ReactElement, useEffect } from 'react';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import DeleteItemIcon from '../../../icons/ui/DeleteItemIcon';
import DragListIcon from '../../../icons/ui/DragItemIcon';
Expand All @@ -23,7 +31,8 @@ export type ListPropertyProps = InspectorFieldProps & {
empty?: string | ReactElement;
addButton?: boolean;
pinned?: ReactElement;
listItem: (props: ListItemChildProps) => ReactElement;
listItem?: (props: ListItemChildProps) => ReactElement;
labels?: (values: any) => string[];
};

export type ListItemProps = {
Expand All @@ -33,6 +42,7 @@ export type ListItemProps = {
arrayHelper: ArrayHelpers;
children: ReactElement;
lastRemaining: boolean;
labels?: (values: any) => string[];
};

const ListItem = ({
Expand All @@ -41,6 +51,7 @@ const ListItem = ({
children,
values,
lastRemaining,
labels,
}: ListItemProps) => {
const updateConfirmation = useStoreActions(
(actions) => actions.triggerConfirmation,
Expand All @@ -50,12 +61,12 @@ const ListItem = ({
<Draggable key={index} draggableId={`${index}`} index={index}>
{(provided, _) => (
<div
className="w-full mb-2 p-1 px-3 text-sm
bg-white border border-circle-gray-300 hover:border-circle-black rounded-sm flex flex-row"
className="w-full mb-4 p-1 px-3 text-sm
bg-white border border-circle-gray-300 hover:border-circle-black rounded-md2 flex flex-row"
ref={provided.innerRef}
{...provided.draggableProps}
>
<div className="ml-auto mr-3" {...provided.dragHandleProps}>
<div className="ml-auto mr-3 my-auto" {...provided.dragHandleProps}>
<DragListIcon className="w-4 h-6 py-1" color="#AAAAAA" />
</div>
{children}
Expand All @@ -64,7 +75,7 @@ bg-white border border-circle-gray-300 hover:border-circle-black rounded-sm flex
onClick={() => {
updateConfirmation({
modalDialogue: 'delete',
labels: ['step', `${values?.name}`],
labels: labels ? labels(values) : ['item'],
onConfirm: () => arrayHelper.remove(index),
});
}}
Expand All @@ -82,95 +93,123 @@ bg-white border border-circle-gray-300 hover:border-circle-black rounded-sm flex

// This is currently hard coded to support steps, but can be broken out to support other sorts of lists.

const ListProperty = ({
const ListProperty = (props: ListPropertyProps) => {
const field = useField(props);

return (
<FieldArray
{...field}
name={props.name}
render={(arrayHelper) => (
<FieldlessListProperty
{...props}
field={field}
arrayHelper={arrayHelper}
/>
)}
/>
);
};

export const FieldlessListProperty = ({
label,
values,
description,
empty: emptyText,
children,
listItem,
labels,
field,
placeholder,
arrayHelper,
...props
}: InspectorFieldProps & ListPropertyProps) => {
const [field] = useField(props);
}: ListPropertyProps & {
field: [FieldInputProps<any>, FieldMetaProps<any>, FieldHelperProps<any>];
arrayHelper: FieldArrayRenderProps;
}) => {
const [input, , helper] = field;
const ListChild = listItem;

return (
<CollapsibleList
title={label}
className={props.className}
titleExpanded={props.titleExpanded}
expanded={props.expanded}
pinned={props.pinned}
pinned={
<>
{props.addButton && (
<AddButton
className="ml-auto"
onClick={() => {
helper.setValue(input.value ? [...input.value, ''] : ['']);
}}
/>
)}
{props.pinned}
</>
}
>
<>
{field.value?.length > 0 ? (
<FieldArray
{...field}
name={props.name}
render={(arrayHelper) => (
<>
<DragDropContext
onDragEnd={(result) => {
if (result.destination) {
arrayHelper.move(
result.source.index,
result.destination.index,
);
}
}}
>
{children}
<Droppable droppableId="droppable">
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
className="p-2 pr-0 flex flex-col "
>
{field.value.map((item: any, index: number) => {
return (
<ListItem
key={index}
lastRemaining={field.value.length === 1}
index={index}
arrayHelper={arrayHelper}
>
<ListChild
setValue={(value) => {
arrayHelper.replace(index, value);
}}
item={item}
index={index}
values={values}
/>
</ListItem>
);
})}
{provided.placeholder}
{props.addButton && (
<AddButton
className="ml-auto"
onClick={() => {
arrayHelper.push('');
}}
/>
)}
</div>
)}
</Droppable>
</DragDropContext>
</>
{input.value?.length > 0 ? (
<DragDropContext
onDragEnd={(result) => {
if (result.destination) {
arrayHelper.move(result.source.index, result.destination.index);
}
}}
>
{children}
<Droppable droppableId="droppable">
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
className="p-2 pr-0 flex flex-col"
>
{input.value.map((item: any, index: number) => {
return (
<ListItem
key={index}
lastRemaining={input.value.length === 1}
index={index}
values={item}
arrayHelper={arrayHelper}
labels={labels}
>
{ListChild ? (
<ListChild
setValue={(value) => {
arrayHelper.replace(index, value);
}}
item={item}
index={index}
values={values}
/>
) : (
<input
className="w-full h-full p-1"
defaultValue={item}
placeholder={placeholder}
onChange={(e) => {
arrayHelper.replace(index, e.target.value);
}}
/>
)}
</ListItem>
);
})}
{provided.placeholder}
</div>
)}
/>
) : (
<>
<p className="ml-2 font-medium text-sm text-circle-gray-500">
{emptyText}
</p>
{children}
</>
)}
</>
</Droppable>
</DragDropContext>
) : (
<>
<p className="ml-2 font-medium text-sm text-circle-gray-500">
{emptyText}
</p>
{children}
</>
)}
</CollapsibleList>
);
};
Expand Down
Loading

0 comments on commit 5572635

Please sign in to comment.