Skip to content

Commit

Permalink
- PDF field mappings
Browse files Browse the repository at this point in the history
- working on drag/drop for preview page
  • Loading branch information
danielnaab committed Feb 28, 2024
1 parent 69ab8ff commit 0fb7b1a
Show file tree
Hide file tree
Showing 15 changed files with 374 additions and 152 deletions.
7 changes: 5 additions & 2 deletions apps/spotlight/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ const context = getAppContext();
/>
<link href="/favicon/favicon.ico" rel="shortcut icon" />
<meta name="generator" content={Astro.generator} />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
<script src="../lib/initialize.ts"></script>
<title>{title}</title>
</head>
Expand All @@ -54,7 +57,7 @@ const context = getAppContext();
<UsaBanner />
<Header />
<slot />
<Footer github={context.github} />
<Footer github={context.github} />
</div>
</body>
</html>
22 changes: 11 additions & 11 deletions packages/design/sass/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

h1 {
font-size: 2.5em;

span {
display: inline-block;
vertical-align: top;
Expand Down Expand Up @@ -51,11 +51,11 @@ main {
max-width: 75rem;
}

.usa-combo-box__input,
.usa-input,
.usa-input-group,
.usa-range,
.usa-select,
.usa-combo-box__input,
.usa-input,
.usa-input-group,
.usa-range,
.usa-select,
.usa-textarea {
max-width: 40rem;
height: 3rem;
Expand Down Expand Up @@ -166,7 +166,7 @@ main {
padding: 15px;
font-size: 20px;
text-align: center;

&:hover {
background: #f5f2ff;
border: 1px solid #e4deff;
Expand All @@ -187,9 +187,9 @@ main {
}
}

[contentEditable=true]:focus,
[href]:focus,
[tabindex]:focus,
[contentEditable=true]:focus,
[href]:focus,
[tabindex]:focus,
iframe:focus {
outline: 0.25rem solid #783cb9;
}
Expand Down Expand Up @@ -218,7 +218,7 @@ iframe:focus {
.edit-button-icon {
padding: 0 10px;
flex: none;
}
}
}

&.field-selected {
Expand Down
28 changes: 14 additions & 14 deletions packages/design/src/Form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,15 @@ export default function Form({
})}
>
<fieldset className="usa-fieldset">
{prompt.parts
.map((part, index) => {
return (
<PromptComponent
key={index}
context={context}
promptPart={part}
/>
);
})
.filter(a => a)}
{prompt.parts.map((part, index) => {
return (
<PromptComponent
key={index}
context={context}
promptPart={part}
/>
);
})}
{/* Add submit button or other controls as needed */}
</fieldset>
<ActionBar actions={prompt.actions} />
Expand All @@ -133,9 +131,11 @@ const PromptComponent = ({
const Component = context.components[promptPart.pattern.type];
return (
<Component pattern={promptPart.pattern}>
{promptPart.children?.map((child, index) => (
<PromptComponent key={index} context={context} promptPart={child} />
))}
{promptPart.children?.map((child, index) => {
return (
<PromptComponent key={index} context={context} promptPart={child} />
);
})}
</Component>
);
};
128 changes: 128 additions & 0 deletions packages/design/src/FormManager/FormEdit/DraggableList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, { Children, useState } from 'react';
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
useSortable,
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

import {
getFormElement,
type FormDefinition,
type FormElement,
FormElementId,
} from '@atj/forms';

import { SequenceElement } from '@atj/forms/src/config/elements/sequence';

const SortableItem = ({
id,
children,
}: {
id: string;
children: React.ReactNode;
}) => {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id });

const style = {
transform: CSS.Transform.toString(transform),
transition,
};

return (
<li ref={setNodeRef} style={style}>
<div className="editFieldsRowWrapper grid-row grid-gap">
<div
className="editPageGrabButtonWrapper grid-col-1 grid-col"
{...listeners}
{...attributes}
style={{ cursor: 'grab' }}
>
<span className="grabber1">:::</span>
<span className="grabber2">:::</span>
</div>
<div className="editFieldsWrapper grid-col-11 grid-col">{children}</div>
</div>
</li>
);
};

type DraggableListProps = React.PropsWithChildren<{
element: FormElement<SequenceElement>;
form: FormDefinition;
setSelectedElement: (element: FormElement) => void;
}>;
export const DraggableList: React.FC<DraggableListProps> = ({
element,
form,
setSelectedElement,
children,
}) => {
const [elements, setElements] = useState<FormElement[]>(
element.data.elements.map((elementId: FormElementId) => {
return getFormElement(form, elementId);
})
);
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
);

const arrayChildren = Children.toArray(children);
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={event => {
const { active, over } = event;
if (over === null) {
return;
}
if (active.id !== over.id) {
const oldIndex = elements.findIndex(element => {
return element.id === active.id;
});
const newIndex = elements.findIndex(element => {
return element.id === over.id;
});
const newOrder = arrayMove(elements, oldIndex, newIndex);
setElements(newOrder);
setSelectedElement({
id: element.id,
type: element.type,
data: {
elements: newOrder.map(element => element.id),
},
default: {
elements: [],
},
required: element.required,
} satisfies SequenceElement);
}
}}
>
<SortableContext items={elements} strategy={verticalListSortingStrategy}>
<ul className="editFormWrapper">
{arrayChildren.map((child, index) => (
<SortableItem key={index} id={elements[index].id}>
{child}
</SortableItem>
))}
</ul>
</SortableContext>
</DndContext>
);
};

export default DraggableList;
85 changes: 45 additions & 40 deletions packages/design/src/FormManager/FormEdit/FormElementEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,67 @@
import React from 'react';
import React, { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import {
FormDefinition,
FormElement,
FormElementMap,
getFormElementConfig,
updateElement,
type FormElementMap,
} from '@atj/forms';
import { FormEditUIContext } from '../../config';
import { usePreviewContext } from './context';

export const FormElementEdit = ({
context,
initialForm,
formElement,
onChange,
}: {
context: FormEditUIContext;
initialForm: FormDefinition;
formElement: FormElement;
onChange: (form: FormDefinition) => void;
}) => {
const { form, selectedElement, setCurrentForm } = usePreviewContext();
if (!selectedElement) {
return;
}

const methods = useForm<FormElementMap>({
defaultValues: {
[formElement.id]: formElement,
[selectedElement.id]: selectedElement,
},
});
const SelectedEditComponent = context.editComponents[formElement.type];
useEffect(() => {
methods.setValue(selectedElement.id, selectedElement);
}, [selectedElement]);

const SelectedEditComponent = context.editComponents[selectedElement.type];
return (
<FormProvider {...methods}>
<form
className="editForm"
onSubmit={methods.handleSubmit(formData => {
const elementConfig = getFormElementConfig(
context.config,
formElement.type
);
const data = formData[formElement.id].data;
const result = elementConfig.parseConfigData(data);
if (!result.success) {
return;
}
const updatedForm = updateElement(initialForm, {
...formElement,
data: result.data,
});
onChange(updatedForm);
})}
>
<SelectedEditComponent
context={context}
form={initialForm}
element={formElement}
/>
<p>
<input className="usa-button" type="submit" value="Save" />
</p>
</form>
<div className="settingsContainer">
<h2>Editing {selectedElement.id}...</h2>
<form
className="editForm"
onSubmit={methods.handleSubmit(formData => {
const elementConfig = getFormElementConfig(
context.config,
selectedElement.type
);
const data = formData[selectedElement.id].data;
const result = elementConfig.parseConfigData(data);
if (!result.success) {
return;
}
const updatedForm = updateElement(form, {
...selectedElement,
data: result.data,
});
setCurrentForm(updatedForm);
})}
>
<SelectedEditComponent
context={context}
form={form}
element={selectedElement}
/>
<p>
<input className="usa-button" type="submit" value="Save" />
</p>
</form>
</div>
</FormProvider>
);
};
Loading

0 comments on commit 0fb7b1a

Please sign in to comment.