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

feat: OPTIC-107: Draft saving on view all #5141

Merged
merged 30 commits into from Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
53ab90d
[submodules] Build static HumanSignal/dm2
Travis1282 Dec 5, 2023
96749c9
[submodules] Build static HumanSignal/dm2
Travis1282 Dec 6, 2023
a831f13
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Dec 6, 2023
b883a2c
[submodules] Build static HumanSignal/label-studio-frontend
Dec 8, 2023
8af2d99
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Dec 8, 2023
c2cddf1
[submodules] Build static HumanSignal/dm2
Dec 8, 2023
6f8e094
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Dec 8, 2023
ffacd74
[submodules] Build static HumanSignal/dm2
Dec 8, 2023
4f64486
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Dec 8, 2023
a31004a
[submodules] Build static HumanSignal/dm2
Dec 8, 2023
4c4f348
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Dec 8, 2023
82b833e
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Dec 28, 2023
d89944f
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Dec 28, 2023
4c134a8
[submodules] Build static HumanSignal/dm2
Travis1282 Dec 28, 2023
ba112db
[submodules] Build static HumanSignal/dm2
Travis1282 Jan 3, 2024
9aaa658
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Jan 3, 2024
d324ea9
[submodules] Build static HumanSignal/dm2
Travis1282 Jan 4, 2024
3437edd
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Jan 4, 2024
104c3b8
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 4, 2024
4627756
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 4, 2024
8017ee8
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 4, 2024
6768d80
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 4, 2024
921a370
[submodules] Copy src HumanSignal/label-studio-frontend
Travis1282 Jan 8, 2024
950f156
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 8, 2024
3b3283d
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Jan 8, 2024
baafe13
ci: Build frontend
robot-ci-heartex Jan 8, 2024
5141695
[submodules] Copy src HumanSignal/label-studio-frontend
Travis1282 Jan 8, 2024
28c2c53
[submodules] Build static HumanSignal/label-studio-frontend
Travis1282 Jan 8, 2024
f59a5da
Merge branch 'origin/develop' into 'fb-optic-107/save-draft-view-all'
Travis1282 Jan 8, 2024
1dd67bc
ci: Build frontend
robot-ci-heartex Jan 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion label_studio/frontend/dist/dm/js/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion label_studio/frontend/dist/dm/js/main.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions label_studio/frontend/dist/dm/version.json
@@ -1,6 +1,6 @@
{
"message": "feat: DIA-474: [FE] add new column for DE",
"commit": "a8e6e5e6cd6601d765a7f0abd4efa87cec1a3fe5",
"message": "feat: OPTIC-107: Draft saving on view all",
"commit": "b2006083fb40a3d5a1ee7979ff24497864dfcdac",
"branch": "master",
"date": "2024-01-03T07:13:20Z"
"date": "2024-01-04T09:37:55Z"
}
2 changes: 1 addition & 1 deletion label_studio/frontend/dist/lsf/css/main.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion label_studio/frontend/dist/lsf/css/main.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion label_studio/frontend/dist/lsf/js/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion label_studio/frontend/dist/lsf/js/main.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions label_studio/frontend/dist/lsf/version.json
@@ -1,6 +1,6 @@
{
"message": "fix: LEAP-344: View all annotation tab is not loading",
"commit": "eb1194c1e8ad5f9c0e725b2955dbc202f169649b",
"message": "feat: OPTIC-107: Draft saving on view all",
"commit": "08aa5b599a64e4b90956b861739df273946ee738",
"branch": "master",
"date": "2024-01-08T09:48:32Z"
"date": "2024-01-08T13:19:30Z"
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion web/dist/libs/editor/main.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/dist/libs/editor/main.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/dist/libs/editor/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/dist/libs/editor/main.js.map

Large diffs are not rendered by default.

Expand Up @@ -171,6 +171,7 @@ const RelationItemObserver = observer(({ relation, startNode, endNode, visible,
endNode={endNode}
direction={relation.direction}
visible={visibility}
labels={relation.selectedValues}
{...rest}
/>
) : null;
Expand Down Expand Up @@ -229,7 +230,6 @@ class RelationsOverlay extends PureComponent {
rootRef={this.rootNode}
startNode={relation.node1}
endNode={relation.node2}
labels={relation.relations?.selectedValues()}
dimm={hasHighlight && !highlighted}
highlight={highlighted}
visible={highlighted || visible}
Expand Down
Expand Up @@ -31,6 +31,7 @@

&__icon
width 24px
min-height 24px
display flex
flex none
position relative
Expand Down
Expand Up @@ -56,9 +56,9 @@ const RelationItem: FC<{relation: any}> = observer(({ relation }) => {
const { direction } = relation;

switch (direction) {
case 'left': return <IconRelationLeft/>;
case 'right': return <IconRelationRight/>;
case 'bi': return <IconRelationBi/>;
case 'left': return <IconRelationLeft data-direction={relation.direction}/>;
case 'right': return <IconRelationRight data-direction={relation.direction}/>;
case 'bi': return <IconRelationBi data-direction={relation.direction}/>;
default: return null;
}
}, [relation.direction]);
Expand Down Expand Up @@ -92,6 +92,7 @@ const RelationItem: FC<{relation: any}> = observer(({ relation }) => {
{(hovered || relation.showMeta) && relation.hasRelations && (
<Button
primary={relation.showMeta}
aria-label={`${relation.showMeta ? 'Hide' : 'Show'} Relation Labels`}
type={relation.showMeta ? undefined : 'text'}
onClick={relation.toggleMeta}
style={{ padding: 0 }}
Expand All @@ -102,14 +103,14 @@ const RelationItem: FC<{relation: any}> = observer(({ relation }) => {
</Elem>
<Elem name="action">
{(hovered || !relation.visible) && (
<Button type="text" onClick={relation.toggleVisibility}>
<Button type="text" onClick={relation.toggleVisibility} aria-label={`${relation.visible ? 'Hide' : 'Show'} Relation`}>
{relation.visible ? <IconEyeOpened/> : <IconEyeClosed />}
</Button>
)}
</Elem>
<Elem name="action">
{hovered && (
<Button type="text" danger onClick={() => {
<Button type="text" danger aria-label="Delete Relation" onClick={() => {
relation.node1.setHighlight(false);
relation.node2.setHighlight(false);
relation.parent.deleteRelation(relation);
Expand All @@ -127,10 +128,9 @@ const RelationItem: FC<{relation: any}> = observer(({ relation }) => {
);
});

const RelationMeta: FC<any> = ({ relation }) => {
const { relations } = relation;
const { children, choice } = relations;
const selected = relations.getSelected().map((v: any) => v.value);
const RelationMeta: FC<any> = observer(({ relation }) => {
const { selectedValues, control } = relation;
const { children, choice } = control;

const selectionMode = useMemo(() => {
return choice === 'multiple' ? 'multiple' : undefined;
Expand All @@ -139,17 +139,16 @@ const RelationMeta: FC<any> = ({ relation }) => {
const onChange = useCallback((val: any) => {
const values: any[] = wrapArray(val);

relations.unselectAll();
values.forEach(v => relations.findRelation(v).setSelected(true));
}, []);
relation.setRelations(values);
}, [relation]);

return (
<Block name="relation-meta">
<Select
mode={selectionMode}
style={{ width: '100%' }}
placeholder="Select labels"
defaultValue={selected}
value={selectedValues}
onChange={onChange}
>
{children.map((c: any) => (
Expand All @@ -160,6 +159,6 @@ const RelationMeta: FC<any> = ({ relation }) => {
</Select>
</Block>
);
};
});

export const Relations = observer(RealtionsComponent);
1 change: 1 addition & 0 deletions web/libs/editor/src/components/TopBar/Actions.js
Expand Up @@ -15,6 +15,7 @@ export const Actions = ({ store }) => {
const isViewAll = annotationStore.viewingAll;

const onToggleVisibility = useCallback(() => {
!isViewAll && entity.saveDraftImmediatelyWithResults({ useToast: true });
annotationStore.toggleViewingAllAnnotations();
}, [annotationStore]);

Expand Down
7 changes: 6 additions & 1 deletion web/libs/editor/src/components/TopBar/TopBar.js
Expand Up @@ -19,6 +19,11 @@ export const TopBar = observer(({ store }) => {

const isViewAll = annotationStore?.viewingAll === true;

const toggleViewAll = () => {
!isViewAll && entity.saveDraftImmediatelyWithResults({ useToast: true });
annotationStore.toggleViewingAllAnnotations();
};

return store ? (
<Block name="topbar" mod={{ newLabelingUI: isFF(FF_DEV_3873) }}>
{isFF(FF_DEV_3873) ? (
Expand All @@ -31,7 +36,7 @@ export const TopBar = observer(({ store }) => {
icon={<IconViewAll />}
type="text"
aria-label="View All"
onClick={() => annotationStore.toggleViewingAllAnnotations()}
onClick={toggleViewAll}
primary={ isViewAll }
style={{
height: 36,
Expand Down
3 changes: 2 additions & 1 deletion web/libs/editor/src/core/TimeTraveller.js
Expand Up @@ -9,7 +9,7 @@ const TimeTraveller = types
undoIdx: 0,
targetPath: '',
skipNextUndoState: types.optional(types.boolean, false),

lastAdditionTime: types.optional(types.Date, new Date()),
createdIdx: 0,
})
.volatile(() => ({
Expand Down Expand Up @@ -102,6 +102,7 @@ const TimeTraveller = types
self.undoIdx = self.history.length - 1;
replaceNextUndoState = false;
changesDuringFreeze = false;
self.lastAdditionTime = new Date();
},

reinit(force = true) {
Expand Down
34 changes: 24 additions & 10 deletions web/libs/editor/src/stores/Annotation/Annotation.js
Expand Up @@ -31,6 +31,12 @@ import { UserExtended } from '../UserStore';

const hotkeys = Hotkey('Annotations', 'Annotations');

const TrackedState = types
.model('TrackedState', {
areas: types.map(Area),
relationStore: types.optional(RelationStore, {}),
});

export const Annotation = types
.model('Annotation', {
id: types.identifier,
Expand Down Expand Up @@ -70,19 +76,19 @@ export const Annotation = types
ground_truth: types.optional(types.boolean, false),
skipped: false,

history: types.optional(TimeTraveller, { targetPath: '../areas' }),
// This field stores all data that affects undo/redo history
// It should contain real objects to be able to work with them through snapshots
// Annotation will use getters to get them at the top level
// This data is never redefined directly, it's empty at the start
trackedState: types.optional(TrackedState, {}),
history: types.optional(TimeTraveller, { targetPath: '../trackedState' }),

dragMode: types.optional(types.boolean, false),

editable: types.optional(types.boolean, true),
readonly: types.optional(types.boolean, false),

relationMode: types.optional(types.boolean, false),
relationStore: types.optional(RelationStore, {
relations: [],
}),

areas: types.map(Area),

suggestions: types.map(Area),

Expand All @@ -98,6 +104,14 @@ export const Annotation = types

...(isFF(FF_DEV_3391) ? { root: Types.allModelsTypes() } : {}),
})
.views(self => ({
get areas() {
return self.trackedState.areas;
},
get relationStore() {
return self.trackedState.relationStore;
},
}))
.preProcessSnapshot(sn => {
// sn.draft = Boolean(sn.draft);
let user = sn.user ?? sn.completed_by ?? undefined;
Expand Down Expand Up @@ -188,7 +202,7 @@ export const Annotation = types
return self.results
.map(r => r.serialize())
.filter(Boolean)
.concat(self.relationStore.serializeAnnotation());
.concat(self.relationStore.serialize());
},

get serializedSelection() {
Expand Down Expand Up @@ -696,11 +710,11 @@ export const Annotation = types
if (self.autosave) self.autosave.flush();
},

async saveDraftImmediatelyWithResults() {
async saveDraftImmediatelyWithResults(params) {
// There is no draft to save as it was already saved as an annotation
if (self.submissionStarted || self.isDraftSaving) return {};
self.setDraftSaving(true);
const res = await self.saveDraft(null);
const res = await self.saveDraft(params);

return res;
},
Expand Down Expand Up @@ -928,7 +942,7 @@ export const Annotation = types
const result = self.results
.map(r => r.serialize(options))
.filter(Boolean)
.concat(self.relationStore.serializeAnnotation(options));
.concat(self.relationStore.serialize(options));

document.body.style.cursor = 'default';

Expand Down