Skip to content

Commit

Permalink
Fix loading full value of truncated data when editing multi str field (
Browse files Browse the repository at this point in the history
…Fixes #302)
  • Loading branch information
jaclarke committed Feb 26, 2024
1 parent e8b1069 commit 299d56e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 67 deletions.
62 changes: 38 additions & 24 deletions shared/studio/components/dataEditor/editor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useEffect, useRef} from "react";
import {action, makeObservable, observable} from "mobx";
import {action, makeObservable, observable, runInAction} from "mobx";

import cn from "@edgedb/common/utils/classNames";

Expand Down Expand Up @@ -33,40 +33,54 @@ export class DataEditorState {
) {
makeObservable(this);

if (isEditorValue) {
this.value = value;
const _init = (_value: any) =>
runInAction(() => {
if (isEditorValue) {
this.value = _value;
} else {
this.value =
_value != null
? isMulti
? _value.map((val: any) => valueToEditorValue(val, type))
: valueToEditorValue(_value, type)
: isRequired
? isMulti
? []
: newPrimitiveValue(type)[0]
: null;
}

this.hasError =
this.value === null
? false
: isMulti
? (this.value as EditorValue[]).some(
(v: any) => !isEditorValueValid(v, type)
)
: !isEditorValueValid(this.value, type);

this.loaded = true;
});

if (value instanceof Promise) {
value.then((_value) => _init(_value));
} else {
this.value =
value != null
? isMulti
? value.map((val: any) => valueToEditorValue(val, type))
: valueToEditorValue(value, type)
: isRequired
? isMulti
? []
: newPrimitiveValue(type)[0]
: null;
_init(value);
}

this.hasError =
this.value === null
? false
: isMulti
? (this.value as EditorValue[]).some(
(v: any) => !isEditorValueValid(v, type)
)
: !isEditorValueValid(this.value, type);
}

@observable
loaded = false;

isEdited = false;

@observable.ref value: EditorValue | null;
@observable.ref value: EditorValue | null = null;
@action setValue(val: EditorValue | null) {
this.value = val;
this.isEdited = true;
}

@observable hasError: boolean;
@observable hasError: boolean = false;
@action setError(err: boolean) {
this.hasError = err;
}
Expand Down
48 changes: 13 additions & 35 deletions shared/studio/tabs/dataview/dataInspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,8 @@ const GridCell = observer(function GridCell({
field.type === ObjectFieldType.property &&
edits.activePropertyEdit?.cellId === cellId
) {
return cellEditState?.value === undefined &&
field.schemaType.name === "std::str" &&
typeof value === "string" &&
value.length === 100 &&
!state.fullyFetchedData.has(cellId) ? (
<FetchingDataPlaceholder state={state} data={data} field={field} />
return !edits.activePropertyEdit.loaded ? (
<div className={styles.fetchingDataPlaceholder}>loading...</div>
) : (
<DataEditor state={edits.activePropertyEdit} />
);
Expand Down Expand Up @@ -532,14 +528,15 @@ const GridCell = observer(function GridCell({
[styles.hasEdits]:
!isDeletedRow && rowData && (!!cellEditState || !!linkEditState),
[styles.hasErrors]:
(cellEditState && !cellEditState.value.valid) ||
(insertedRow && _value && !_value.valid) ||
(!rowData &&
isEditable &&
field.required &&
!field.hasDefault &&
value === null &&
!linkEditState),
isEditable &&
((cellEditState && !cellEditState.value.valid) ||
(insertedRow && _value && !_value.valid) ||
(!rowData &&
isEditable &&
field.required &&
!field.hasDefault &&
value === null &&
!linkEditState)),
})}
onClick={() => {
if (field.type === ObjectFieldType.link && content !== null) {
Expand All @@ -555,11 +552,8 @@ const GridCell = observer(function GridCell({
onDoubleClick={() => {
if (isEditable) {
if (field.type === ObjectFieldType.property) {
edits.startEditingCell(
data.id,
data.__tname__,
field,
state.fullyFetchedData.get(cellId) ?? value
edits.startEditingCell(data.id, data.__tname__, field, () =>
state.fetchFullCellData(data.id, value, field)
);
} else {
state.openNestedView(
Expand All @@ -579,22 +573,6 @@ const GridCell = observer(function GridCell({
);
});

function FetchingDataPlaceholder({
state,
data,
field,
}: {
state: DataInspectorState;
data: any;
field: ObjectField;
}) {
useEffect(() => {
state.fetchFullCellData(data.id, field);
}, []);

return <div className={styles.fetchingDataPlaceholder}>loading...</div>;
}

const FieldHeaders = observer(function FieldHeaders() {
const {state} = useDataInspectorState();
const isMobile = useIsMobile();
Expand Down
4 changes: 2 additions & 2 deletions shared/studio/tabs/dataview/state/edits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class DataEditingManager extends Model({}) {
objectId: string | number,
objectTypeName: string,
field: ObjectPropertyField,
value: any
valueGetter: () => any
) {
const cellId = `${objectId}__${field.name}`;

Expand All @@ -117,7 +117,7 @@ export class DataEditingManager extends Model({}) {
field.schemaType as PrimitiveType,
field.required,
field.multi,
editValue?.value ?? value,
editValue ? editValue.value : valueGetter(),
editValue != null && !editValue.valid,
(discard) => {
if (!discard && state.isEdited) {
Expand Down
40 changes: 34 additions & 6 deletions shared/studio/tabs/dataview/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -788,16 +788,44 @@ export class DataInspector extends Model({
@observable.shallow
fullyFetchedData = new Map<string, any>();

async fetchFullCellData(dataId: string, field: ObjectField) {
fetchFullCellData(
dataId: string | number,
value: any,
field: ObjectPropertyField
) {
if (typeof dataId !== "string") {
return value;
}

const cellId = `${dataId}__${field.name}`;

if (this.fullyFetchedData.has(cellId)) {
return this.fullyFetchedData.get(cellId);
}

const isTruncated =
field.schemaType.name === "std::str" &&
(field.multi
? Array.isArray(value) &&
typeof value[0] === "string" &&
value.some((val) => val.length === 100)
: typeof value === "string" && value.length === 100);

if (!isTruncated) {
return value;
}

const query = `select (select ${
field.escapedSubtypeName ?? this._getObjectTypeQuery
} filter .id = <uuid>$id).${field.escapedName}`;
const conn = connCtx.get(this)!;

const val = (await conn.query(query, {id: dataId})).result![0];

runInAction(() => {
this.fullyFetchedData.set(`${dataId}__${field.name}`, val);
const conn = connCtx.get(this)!;
return conn.query(query, {id: dataId}).then(({result}) => {
const val = field.multi ? result! : result![0];
runInAction(() => {
this.fullyFetchedData.set(cellId, val);
});
return val;
});
}

Expand Down

0 comments on commit 299d56e

Please sign in to comment.