Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose onIncompatibleSchemaChange properties in materialization workflows #1372

Merged
merged 36 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
14bdb66
Introduce a spec-level field to materialization workflows
kiahna-tucker Nov 22, 2024
8396524
Reduce space between section description and field
kiahna-tucker Nov 22, 2024
2e9b592
Remove inapplicable error handling
kiahna-tucker Nov 22, 2024
f420f08
Display property value in field-level error
kiahna-tucker Nov 22, 2024
0a54cf6
Remove superfluous container from OnIncompatibleSchemaChange
kiahna-tucker Nov 22, 2024
a26cffe
Remove superfluous container from section header
kiahna-tucker Nov 22, 2024
74cb065
Remove superfluous condition from incompatible schema hook
kiahna-tucker Nov 22, 2024
8b224b6
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Nov 25, 2024
838875f
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Nov 25, 2024
ebb1e61
Display binding-level onIncompatibleSchemaChange field
kiahna-tucker Nov 27, 2024
c957e7b
Create shared onIncompatibleSchemaChange Autocomplete component
kiahna-tucker Dec 2, 2024
f0f8733
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Dec 2, 2024
79d1830
Update binding-level onIncompatibleSchemaChange field via Next cta
kiahna-tucker Dec 3, 2024
0bd1c97
Rename hook to update binding-level property
kiahna-tucker Dec 3, 2024
23dc2f7
Emphasize visual hierarchy in target and output collections subheaders
kiahna-tucker Dec 3, 2024
a22e4cd
Adjust font size of binding selector section headers
kiahna-tucker Dec 3, 2024
b3d5a8b
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Dec 6, 2024
0bf4b05
Remove dictionary entry for binding when field cleared
kiahna-tucker Dec 6, 2024
bd84212
Move onIncompatibleSchemaChange state into binding state
kiahna-tucker Dec 9, 2024
c8036f8
Correct the spacing around and within backfill sections
kiahna-tucker Dec 9, 2024
86a3305
Correct updateResourceConfig logic to carry over incompatible schema …
kiahna-tucker Dec 9, 2024
ee5f5d1
Create component for binding backfill section
kiahna-tucker Dec 9, 2024
365da80
Create component for top-level backfill section
kiahna-tucker Dec 9, 2024
b309bcc
Rename extended onIncompatibleSchemaChange form components
kiahna-tucker Dec 9, 2024
4dfdbd2
Use the entity util to add or remove property in spec hook
kiahna-tucker Dec 9, 2024
dfc189a
Update LogRocket event for missing draft resources
kiahna-tucker Dec 9, 2024
8eca245
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Dec 9, 2024
a60223e
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Dec 18, 2024
4635d22
Merge branch 'main' into kiahna-tucker/incompatible-schema/init-field
kiahna-tucker Dec 19, 2024
a0f48ff
Extend input arguments for setBindingOnIncompatibleSchemaChange
kiahna-tucker Dec 19, 2024
224aeaf
Use autocomplete default props in base form field
kiahna-tucker Dec 19, 2024
201d194
Use onIncompatibleSchemaChange util for binding-level property
kiahna-tucker Dec 19, 2024
cf6cf5e
Preserve field input until server updated successfully
kiahna-tucker Dec 20, 2024
b9efd7a
Broaden the type of currentSetting from string to any
kiahna-tucker Dec 20, 2024
23e4275
Define an error boundary for specification-level field
kiahna-tucker Dec 20, 2024
9f3acbb
Replace instance of JSON stringify with stringifyJSON
kiahna-tucker Jan 6, 2025
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
Expand Up @@ -11,7 +11,6 @@ import { useIntl } from 'react-intl';
import {
useBinding_currentBindingUUID,
useBinding_currentCollection,
useBinding_resourceConfigOfMetaBindingProperty,
} from 'stores/Binding/hooks';
import { useBindingStore } from 'stores/Binding/Store';
import { useFormStateStore_setFormState } from 'stores/FormState/hooks';
Expand All @@ -26,12 +25,6 @@ function Form({ bindingIndex = -1 }: OnIncompatibleSchemaChangeProps) {
const currentCollection = useBinding_currentCollection();
const currentBindingUUID = useBinding_currentBindingUUID();

const incompatibleSchemaChange =
useBinding_resourceConfigOfMetaBindingProperty(
currentBindingUUID,
'onIncompatibleSchemaChange'
);

const setIncompatibleSchemaChange = useBindingStore(
(state) => state.setBindingOnIncompatibleSchemaChange
);
Expand All @@ -58,12 +51,15 @@ function Form({ bindingIndex = -1 }: OnIncompatibleSchemaChangeProps) {
async (value?: AutoCompleteOption | null) => {
setFormState({ status: FormStatus.UPDATING, error: null });

if (currentBindingUUID) {
setIncompatibleSchemaChange(value?.val);
}

updateOnIncompatibleSchemaChange(value?.val, bindingMetadata)
.then(() => {
if (currentBindingUUID) {
setIncompatibleSchemaChange(
value?.val,
currentBindingUUID
);
}

setFormState({ status: FormStatus.UPDATED });
})
.catch((err) => {
Expand All @@ -77,12 +73,17 @@ function Form({ bindingIndex = -1 }: OnIncompatibleSchemaChangeProps) {
{ ...snackbarSettings, variant: 'error' }
);

setIncompatibleSchemaChange(
currentSetting,
currentBindingUUID
);
setFormState({ status: FormStatus.FAILED });
});
},
[
bindingMetadata,
currentBindingUUID,
currentSetting,
enqueueSnackbar,
intl,
setFormState,
Expand All @@ -93,13 +94,7 @@ function Form({ bindingIndex = -1 }: OnIncompatibleSchemaChangeProps) {

return (
<IncompatibleSchemaChangeForm
currentSetting={
currentSetting
? currentSetting
: typeof incompatibleSchemaChange === 'string'
? incompatibleSchemaChange
: ''
}
currentSetting={currentSetting ? currentSetting : ''}
updateDraftedSetting={updateServer}
/>
);
Expand Down
29 changes: 22 additions & 7 deletions src/components/incompatibleSchemaChange/Form.tsx
kiahna-tucker marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useSupportedOptions from 'hooks/OnIncompatibleSchemaChange/useSupportedOp
import { useEffect, useMemo, useState } from 'react';
import { useIntl } from 'react-intl';
import { useFormStateStore_isActive } from 'stores/FormState/hooks';
import { autoCompleteDefaultProps } from './shared';
import { BaseFormProps } from './types';

export default function IncompatibleSchemaChangeForm({
Expand All @@ -27,7 +28,7 @@ export default function IncompatibleSchemaChangeForm({
const options = useSupportedOptions();

const selection = useMemo(() => {
if (!currentSetting) {
if (!currentSetting || typeof currentSetting !== 'string') {
return null;
}

Expand Down Expand Up @@ -68,7 +69,10 @@ export default function IncompatibleSchemaChangeForm({
id: 'incompatibleSchemaChange.error.message',
},
{
currentSetting,
currentSetting:
typeof currentSetting === 'string'
? currentSetting
: JSON.stringify(currentSetting),
kiahna-tucker marked this conversation as resolved.
Show resolved Hide resolved
}
)}
</Typography>
Expand All @@ -87,9 +91,8 @@ export default function IncompatibleSchemaChangeForm({
</AlertBox>
) : null}

{/* The presence of ListboxComponent in autoCompleteDefaultProps prevents
the options from rendering. */}
<Autocomplete
{...autoCompleteDefaultProps}
disabled={formActive}
getOptionLabel={(option) => option.label}
inputValue={inputValue}
Expand All @@ -108,8 +111,12 @@ export default function IncompatibleSchemaChangeForm({
);
}}
onChange={(_state, newVal) => updateDraftedSetting(newVal)}
onInputChange={(_event, newInputValue) => {
setInputValue(newInputValue);
onInputChange={(event, newInputValue) => {
// Set the input value component state only when an option is clicked
// to avoid clashing with the effect which also updates this state.
if (Boolean(event)) {
setInputValue(newInputValue);
}
}}
options={options}
renderInput={(params) => {
Expand All @@ -124,7 +131,15 @@ export default function IncompatibleSchemaChangeForm({
{
id: 'incompatibleSchemaChange.error.message',
},
{ currentSetting }
{
currentSetting:
typeof currentSetting ===
'string'
? currentSetting
: JSON.stringify(
currentSetting
),
}
)
: undefined
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/incompatibleSchemaChange/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { choices } from './shared';

export interface BaseFormProps {
currentSetting: string;
currentSetting: any;
updateDraftedSetting: Function;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export default function Form() {
async (option?: AutoCompleteOption | null) => {
setFormState({ status: FormStatus.UPDATING, error: null });

setIncompatibleSchemaChange(option?.val);

updateOnIncompatibleSchemaChange(option?.val)
.then(() => {
setIncompatibleSchemaChange(option?.val);

setFormState({ status: FormStatus.UPDATED });
})
.catch(() => {
Expand All @@ -40,10 +40,12 @@ export default function Form() {
{ ...snackbarSettings, variant: 'error' }
);

setIncompatibleSchemaChange(currentSetting);
setFormState({ status: FormStatus.FAILED });
});
},
[
currentSetting,
enqueueSnackbar,
intl,
setFormState,
Expand Down
5 changes: 4 additions & 1 deletion src/components/shared/Entity/Backfill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEntityType } from 'context/EntityContext';
import { useEntityWorkflow_Editing } from 'context/Workflow';
import { useIntl } from 'react-intl';
import OnIncompatibleSchemaChange from '../../materialization/OnIncompatibleSchemaChange';
import ErrorBoundryWrapper from '../ErrorBoundryWrapper';

export default function Backfill() {
const intl = useIntl();
Expand All @@ -22,7 +23,9 @@ export default function Backfill() {
) : null}

{entityType === 'materialization' ? (
<OnIncompatibleSchemaChange />
<ErrorBoundryWrapper>
<OnIncompatibleSchemaChange />
</ErrorBoundryWrapper>
) : null}
</SectionWrapper>
) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,16 @@ import {
} from 'components/editor/Store/hooks';
import { AutoCompleteOption } from 'components/incompatibleSchemaChange/types';
import { useEntityType } from 'context/EntityContext';
import { cloneDeep } from 'lodash';
import { useCallback } from 'react';
import { useIntl } from 'react-intl';
import { logRocketEvent } from 'services/shared';
import { BASE_ERROR } from 'services/supabase';
import { CustomEvents } from 'services/types';
import { BindingMetadata, Schema } from 'types';
import { addOrRemoveOnIncompatibleSchemaChange } from 'utils/entity-utils';
import { hasLength } from 'utils/misc-utils';

const updateSchema = (binding: any, newVal: any) => {
if (newVal) {
binding.onIncompatibleSchemaChange = newVal;
} else {
delete binding.onIncompatibleSchemaChange;
}
};

function useBindingIncompatibleSchemaSetting() {
const intl = useIntl();
const entityType = useEntityType();
Expand All @@ -31,25 +27,31 @@ function useBindingIncompatibleSchemaSetting() {

const updateOnIncompatibleSchemaChange = useCallback(
async (
newVal: AutoCompleteOption['val'] | undefined,
value: AutoCompleteOption['val'] | undefined,
bindingMetadata: BindingMetadata[]
) => {
const bindingMetadataExists = hasLength(bindingMetadata);
if (!mutateDraftSpecs || !draftId || draftSpecs.length === 0) {
logRocketEvent(
`${CustomEvents.INCOMPATIBLE_SCHEMA_CHANGE}:Missing Draft Resources`,
{
draftIdMissing: !draftId,
draftSpecMissing: draftSpecs.length === 0,
mutateMissing: !mutateDraftSpecs,
}
);

return Promise.resolve();
}

if (!bindingMetadataExists) {
if (!hasLength(bindingMetadata)) {
return Promise.resolve();
}

const invalidBindingIndex = bindingMetadata.findIndex(
({ bindingIndex }) => bindingIndex === -1
);

if (
!draftId ||
!mutateDraftSpecs ||
draftSpecs.length === 0 ||
invalidBindingIndex > -1
) {
if (invalidBindingIndex > -1) {
return Promise.reject({
...BASE_ERROR,
message: intl.formatMessage(
Expand All @@ -64,11 +66,14 @@ function useBindingIncompatibleSchemaSetting() {
});
}

const spec: Schema = draftSpecs[0].spec;
const spec: Schema = cloneDeep(draftSpecs[0].spec);

bindingMetadata.forEach(({ bindingIndex }) => {
if (bindingIndex > -1) {
updateSchema(spec.bindings[bindingIndex], newVal);
addOrRemoveOnIncompatibleSchemaChange(
spec.bindings[bindingIndex],
value
);
}
});

Expand Down
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I struggled with how to name a hook that is for a component... thoughts on keeping the "components are capitalized" rule within the hooks folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I think that works for now. It may be difficult to live with as components are often subject to being relocated and renamed, but we can play it by ear.

Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ import {
useEditorStore_queryResponse_mutate,
} from 'components/editor/Store/hooks';
import { AutoCompleteOption } from 'components/incompatibleSchemaChange/types';
import { cloneDeep } from 'lodash';
import { useCallback, useMemo } from 'react';
import { logRocketEvent } from 'services/shared';
import { CustomEvents } from 'services/types';
import { useBindingStore } from 'stores/Binding/Store';
import { Schema } from 'types';
import { addOrRemoveOnIncompatibleSchemaChange } from 'utils/entity-utils';

export default function useSpecificationIncompatibleSchemaSetting() {
// Binding Store
const onIncompatibleSchemaChange = useBindingStore(
(state) => state.onIncompatibleSchemaChange
);

// Draft Editor Store
const draftId = useEditorStore_persistedDraftId();
const draftSpecs = useEditorStore_queryResponse_draftSpecs();
Expand All @@ -44,7 +39,7 @@ export default function useSpecificationIncompatibleSchemaSetting() {
return Promise.resolve();
}

const spec: Schema = draftSpec.spec;
const spec: Schema = cloneDeep(draftSpec.spec);
kiahna-tucker marked this conversation as resolved.
Show resolved Hide resolved

addOrRemoveOnIncompatibleSchemaChange(spec, value);

Expand All @@ -66,8 +61,6 @@ export default function useSpecificationIncompatibleSchemaSetting() {
return {
currentSetting: draftSpec?.spec?.onIncompatibleSchemaChange
? draftSpec.spec.onIncompatibleSchemaChange
: typeof onIncompatibleSchemaChange === 'string'
? onIncompatibleSchemaChange
: '',
updateOnIncompatibleSchemaChange,
};
Expand Down
4 changes: 1 addition & 3 deletions src/stores/Binding/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -870,11 +870,9 @@ const getInitialState = (
);
},

setBindingOnIncompatibleSchemaChange: (value) => {
setBindingOnIncompatibleSchemaChange: (value, bindingUUID) => {
set(
produce((state: BindingState) => {
const bindingUUID = state.currentBinding?.uuid;

if (bindingUUID) {
state.resourceConfigs[
bindingUUID
Expand Down
5 changes: 4 additions & 1 deletion src/stores/Binding/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ export interface BindingState
setSpecOnIncompatibleSchemaChange: (
value: BindingState['onIncompatibleSchemaChange']
) => void;
setBindingOnIncompatibleSchemaChange: (value: string | undefined) => void;
setBindingOnIncompatibleSchemaChange: (
value: string | undefined,
bindingUUID: string | null
) => void;

// Resource Config
resourceConfigs: ResourceConfigDictionary;
Expand Down
10 changes: 5 additions & 5 deletions src/utils/entity-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import produce from 'immer';
import { SourceCaptureDef } from 'types';
import { Schema, SourceCaptureDef } from 'types';
import { hasLength, specContainsDerivation } from 'utils/misc-utils';

export const updateShardDisabled = (draftSpec: any, enabling: boolean) => {
Expand Down Expand Up @@ -65,14 +65,14 @@ export const addOrRemoveSourceCapture = (
};

export const addOrRemoveOnIncompatibleSchemaChange = (
draftSpec: any,
schema: Schema,
value: string | undefined
) => {
if (hasLength(value)) {
draftSpec.onIncompatibleSchemaChange = value;
schema.onIncompatibleSchemaChange = value;
} else {
delete draftSpec.onIncompatibleSchemaChange;
delete schema.onIncompatibleSchemaChange;
}

return draftSpec;
return schema;
};
Loading
Loading