Skip to content

Commit

Permalink
feat(import-app): channel validation if present in the schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Plopix committed Feb 12, 2024
1 parent 91f6491 commit be11346
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 64 deletions.
43 changes: 0 additions & 43 deletions components/crystallize-import/product.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface FormSubmission {
mapping: Record<string, string>;
groupProductsBy?: string;
doPublish: boolean;
channel?: string;
validFlowStage?: string;
invalidFlowStage?: string;
}
1 change: 1 addition & 0 deletions components/crystallize-import/src/contracts/ui-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export type State = {
errors?: string[];
loading?: boolean;
done?: boolean;
channels: Record<string, string[]>;
preflight?: {
validCount: number;
errorCount: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type Deps = {
type ValidationSchema<T> = {
schema: JSONSchemaType<T>;
validate: ValidateFunction<JTDDataType<T>>;
channels: string[];
};

export const fetchValidationsSchema = async ({ apiClient }: Deps): Promise<Record<string, ValidationSchema<any>>> => {
Expand Down Expand Up @@ -102,6 +103,7 @@ export const fetchValidationsSchema = async ({ apiClient }: Deps): Promise<Recor
results[key] = {
schema,
validate,
channels: schema.properties?.channel?.enum ?? [],
};
}),
);
Expand Down
32 changes: 19 additions & 13 deletions components/crystallize-import/src/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,27 @@ import { App } from '~/ui/import/App';

export const loader = async ({ request }: LoaderFunctionArgs) => {
const api = await CrystallizeAPI(request);
try {
const shapes = await api.fetchShapes();
const [folders, flows] = await Promise.all([api.fetchFolders(shapes), api.fetchFlows()]);
return json({
shapes,
flows,
folders,
});
} catch (err) {
console.error(err);
return json({ shapes: [], folders: [], flows: [] });
}
const [shapes, validationRules] = await Promise.all([api.fetchShapes(), api.fetchValidationsSchema()]);
const channels = shapes.reduce((memo: Record<string, string[]>, shape) => {
const ch = validationRules?.[shape.identifier]?.channels ?? [];
return {
...memo,
[shape.identifier]: ch,
};
}, {});

const [folders, flows] = await Promise.all([api.fetchFolders(shapes), api.fetchFlows()]);

return json({
shapes,
flows,
channels,
folders,
});
};

export default function Index() {
const { shapes, folders, flows } = useLoaderData<typeof loader>();
const { shapes, folders, flows, channels } = useLoaderData<typeof loader>();
const initialState: State = {
shapes,
folders,
Expand All @@ -32,6 +37,7 @@ export default function Index() {
headers: [],
attributes: [],
rows: [],
channels,
mapping: {},
};

Expand Down
9 changes: 7 additions & 2 deletions components/crystallize-import/src/routes/api.preflight.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { JSONItem } from '@crystallize/import-utilities';
import { type ActionFunctionArgs, json } from '@remix-run/node';
import { FormSubmission } from '~/contracts/form-submission';
import { specFromFormSubmission } from '~/core.server/spec-from-form-submission.server';
import CrystallizeAPI from '~/core.server/use-cases/crystallize';

Expand All @@ -15,7 +16,8 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const api = await CrystallizeAPI(request);
const [validationRules, shapes] = await Promise.all([api.fetchValidationsSchema(), api.fetchShapes()]);
try {
const spec = await specFromFormSubmission(await request.json(), shapes);
const submission: FormSubmission = await request.json();
const spec = await specFromFormSubmission(submission, shapes);
const items = spec.items ?? [];

const results = items.reduce(
Expand All @@ -27,7 +29,10 @@ export const action = async ({ request }: ActionFunctionArgs) => {
validCount: memo.validCount + 1,
};
}
const valid = validate(item);
const valid = validate({
...item,
...(submission.channel ? { channel: submission.channel } : {}),
});

if (!valid) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { PiAirplaneInFlightDuotone } from 'react-icons/pi';
import { useImport } from '../provider';
import { ColumnHeader } from './data-grid/ColumnHeader';
import { FormSubmission } from '~/contracts/form-submission';
import { useRef } from 'react';

export const DataMatchingForm = () => {
const { state, dispatch } = useImport();

const channelRef = useRef<HTMLSelectElement>(null);

const columnsFromRows: Column[] = state.headers.map(
(header): Column => ({
...keyColumn(header, textColumn),
Expand Down Expand Up @@ -36,6 +39,19 @@ export const DataMatchingForm = () => {
</h2>
</div>
<div className="flex flex-row items-center space-x-2">
{state.channels[state.selectedShape.identifier] &&
state.channels[state.selectedShape.identifier].length > 0 && (
<select ref={channelRef} defaultValue={''}>
<option value={''} disabled>
Channel
</option>
{state.channels[state.selectedShape.identifier].map((channel) => (
<option key={channel} value={channel}>
{channel}
</option>
))}
</select>
)}
<button
className="go"
onClick={async () => {
Expand All @@ -46,6 +62,7 @@ export const DataMatchingForm = () => {
folderPath: state.selectedFolder.tree?.path ?? '/',
groupProductsBy: state.groupProductsBy,
mapping: state.mapping,
channel: channelRef.current?.value,
rows: state.rows.filter((row) => row._import),
};
const res = await fetch('/api/preflight', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,16 @@ export const Submit = () => {
<input type="checkbox" ref={publishRef} />
Publish
</label>
<label>
Send valid to: <FlowStagesSelect ref={validFlowRef} />
</label>
<label>
Send errors to: <FlowStagesSelect ref={invalidFlowRef} />
</label>
{state.flows.length > 0 && (
<>
<label>
Send valid to: <FlowStagesSelect ref={validFlowRef} />
</label>
<label>
Send errors to: <FlowStagesSelect ref={invalidFlowRef} />
</label>
</>
)}
</div>
{(state.preflight?.errorCount ?? 0) > 0 && (
<p className="text-error"> You have {state.preflight?.errorCount ?? 0} errors.</p>
Expand Down

0 comments on commit be11346

Please sign in to comment.