Skip to content

Commit 4126da9

Browse files
authored
fix: BROS-136: BROS-156: Release blockers (#7939)
- BROS-136: Don't allow to create regions in View All (#7907) - BROS-156: Always show Fix+Accept when we have draft (#7897)
1 parent f393e7c commit 4126da9

File tree

12 files changed

+56
-63
lines changed

12 files changed

+56
-63
lines changed

web/libs/editor/src/components/BottomBar/buttons.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,23 @@ type AcceptButtonProps = {
4949

5050
export const AcceptButton = memo(
5151
observer(({ disabled, history, store }: AcceptButtonProps) => {
52+
const annotation = store.annotationStore.selected;
53+
// changes in current sessions or saved draft
54+
const hasChanges = history.canUndo || annotation.versions.draft;
55+
5256
return (
5357
<ButtonTooltip key="accept" title="Accept annotation: [ Ctrl+Enter ]">
5458
<Button
5559
aria-label="accept-annotation"
5660
disabled={disabled}
5761
look="primary"
5862
onClick={async () => {
59-
const selected = store.annotationStore?.selected;
60-
61-
selected?.submissionInProgress();
63+
annotation.submissionInProgress();
6264
await store.commentStore.commentFormSubmit();
6365
store.acceptAnnotation();
6466
}}
6567
>
66-
{history.canUndo ? "Fix + Accept" : "Accept"}
68+
{hasChanges ? "Fix + Accept" : "Accept"}
6769
</Button>
6870
</ButtonTooltip>
6971
);

web/libs/editor/src/components/TimeSeries/TimeSeriesVisualizer.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class TimeSeriesVisualizerD3 extends React.Component {
9797
} = this.props;
9898

9999
const activeStates = parent?.activeStates();
100-
const statesSelected = activeStates && activeStates.length;
100+
const statesSelected = activeStates?.length;
101101
const readonly = parent?.annotation?.isReadOnly();
102102

103103
// skip if event fired by .move() - prevent recursion and bugs
@@ -108,10 +108,13 @@ class TimeSeriesVisualizerD3 extends React.Component {
108108
const x = d3.mouse(d3.event.sourceEvent.target)[0];
109109
const newRegion = this.newRegion;
110110

111+
// double click handler to create instant region
111112
// when 2nd click happens during 300ms after 1st click and in the same place
112113
if (newRegion && Math.abs(newRegion.x - x) < 4) {
113114
clearTimeout(this.newRegionTimer);
114-
parent?.regionChanged(newRegion.range, ranges.length, newRegion.states);
115+
if (!readonly) {
116+
parent?.regionChanged(newRegion.range, ranges.length, newRegion.states);
117+
}
115118
this.newRegion = null;
116119
this.newRegionTimer = null;
117120
} else if (statesSelected) {

web/libs/editor/src/components/Timeline/Timeline.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const TimelineComponent: FC<TimelineProps> = ({
3232
speed,
3333
className,
3434
formatPosition,
35+
readonly = false,
3536
...props
3637
}) => {
3738
const View = Views[mode];
@@ -106,8 +107,9 @@ const TimelineComponent: FC<TimelineProps> = ({
106107
seekOffset,
107108
settings: View.settings,
108109
visibleWidth: seekVisibleWidth,
110+
readonly,
109111
}),
110-
[position, seekOffset, seekVisibleWidth, length, regions, step, playing, View.settings, data],
112+
[position, seekOffset, seekVisibleWidth, length, regions, step, playing, View.settings, data, readonly],
111113
);
112114

113115
useEffect(() => {

web/libs/editor/src/components/Timeline/Types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface TimelineProps<D extends ViewTypes = "frames"> {
3232
controlsOnTop?: boolean;
3333
controls?: TimelineControls;
3434
customControls?: TimelineCustomControls[];
35+
readonly?: boolean;
3536
onReady?: (data: Record<string, any>) => void;
3637
onPlay?: () => void;
3738
onPause?: () => void;
@@ -121,6 +122,7 @@ export interface TimelineContextValue {
121122
settings?: TimelineSettings;
122123
changeSetting?: (key: string, value: any) => void;
123124
data?: any;
125+
readonly?: boolean;
124126
}
125127

126128
export interface TimelineMinimapProps {

web/libs/editor/src/components/Timeline/Views/Frames/Controls.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type DataType = {
1010
};
1111

1212
export const Controls: FC<TimelineExtraControls<Actions, DataType>> = ({ onAction }) => {
13-
const { position, regions } = useContext(TimelineContext);
13+
const { position, regions, readonly } = useContext(TimelineContext);
1414
const hasSelectedRegion = regions.some(({ selected, timeline }) => selected && !timeline);
1515
const closestKeypoint = useMemo(() => {
1616
const region = regions.find((r) => r.selected && !r.timeline);
@@ -69,11 +69,11 @@ export const Controls: FC<TimelineExtraControls<Actions, DataType>> = ({ onActio
6969

7070
return (
7171
<>
72-
<ControlButton onClick={onKeypointToggle} disabled={!hasSelectedRegion} tooltip="Toggle Keypoint">
72+
<ControlButton onClick={onKeypointToggle} disabled={!hasSelectedRegion || readonly} tooltip="Toggle Keypoint">
7373
{keypointIcon}
7474
</ControlButton>
7575

76-
<ControlButton onClick={onLifespanToggle} disabled={!closestKeypoint} tooltip="Toggle Interpolation">
76+
<ControlButton onClick={onLifespanToggle} disabled={!closestKeypoint || readonly} tooltip="Toggle Interpolation">
7777
{interpolationIcon}
7878
</ControlButton>
7979
</>

web/libs/editor/src/components/TopBar/Controls.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export const Controls = controlsInjector(
116116
store.acceptAnnotation();
117117
}}
118118
>
119-
{history.canUndo ? "Fix + Accept" : "Accept"}
119+
{history.canUndo || annotation.versions.draft ? "Fix + Accept" : "Accept"}
120120
</Button>
121121
</ButtonTooltip>,
122122
);

web/libs/editor/src/tags/object/AudioUltra/model.js

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ import { observe } from "mobx";
22
import { getEnv, getRoot, getType, types } from "mobx-state-tree";
33
import { createRef } from "react";
44
import { customTypes } from "../../../core/CustomTypes";
5-
import { guidGenerator } from "../../../core/Helpers.ts";
65
import { AnnotationMixin } from "../../../mixins/AnnotationMixin";
76
import IsReadyMixin from "../../../mixins/IsReadyMixin";
87
import ProcessAttrsMixin from "../../../mixins/ProcessAttrs";
98
import { SyncableMixin } from "../../../mixins/Syncable";
109
import { AudioRegionModel } from "../../../regions/AudioRegion";
11-
import Utils from "../../../utils";
1210
import { FF_LSDV_E_278, isFF } from "../../../utils/feature-flags";
1311
import { isDefined } from "../../../utils/utilities";
1412
import ObjectBase from "../Base";
@@ -155,13 +153,13 @@ export const AudioModel = types.compose(
155153
activeStates() {
156154
const states = self.states();
157155

158-
return states && states.filter((s) => getType(s).name === "LabelsModel" && s.isSelected);
156+
return states?.filter((s) => getType(s).name === "LabelsModel" && s.isSelected);
159157
},
160158

161159
get activeState() {
162160
const states = self.states();
163161

164-
return states && states.filter((s) => getType(s).name === "LabelsModel" && s.isSelected)[0];
162+
return states?.filter((s) => getType(s).name === "LabelsModel" && s.isSelected)[0];
165163
},
166164

167165
get activeLabel() {
@@ -175,6 +173,9 @@ export const AudioModel = types.compose(
175173
// use label to generate a unique key to ensure that adding/deleting can trigger changes
176174
return labels ? labels.join(",") : "";
177175
},
176+
get readonly() {
177+
return self.annotation.isReadOnly();
178+
},
178179
}))
179180
////// Sync actions
180181
.actions((self) => ({
@@ -218,9 +219,9 @@ export const AudioModel = types.compose(
218219
////// Incoming
219220

220221
registerSyncHandlers() {
221-
["play", "pause", "seek"].forEach((event) => {
222+
for (const event of ["play", "pause", "seek"]) {
222223
self.syncHandlers.set(event, self.handleSync);
223-
});
224+
}
224225
self.syncHandlers.set("speed", self.handleSyncSpeed);
225226
},
226227

@@ -287,13 +288,13 @@ export const AudioModel = types.compose(
287288
const selectedColor = activeState?.selectedColor;
288289
const labels = activeState?.selectedValues();
289290

290-
selectedRegions.forEach((r) => {
291+
for (const r of selectedRegions) {
291292
r.update({ color: selectedColor, labels: labels ?? [] });
292293

293294
const region = r.isRegion ? self.updateRegion(r) : self.addRegion(r);
294295

295296
self.annotation.selectArea(region);
296-
});
297+
}
297298

298299
if (selectedRegions.length) {
299300
self.requestWSUpdate();
@@ -340,7 +341,7 @@ export const AudioModel = types.compose(
340341
(target) => target.type === "paragraphs" && target.contextscroll,
341342
);
342343

343-
syncedParagraphs.forEach((paragraph) => {
344+
for (const paragraph of syncedParagraphs) {
344345
const segments = Object.values(paragraph.regionsStartEnd).map(({ start, end }) => ({
345346
start,
346347
end,
@@ -350,7 +351,7 @@ export const AudioModel = types.compose(
350351
}));
351352

352353
self._ws.addRegions(segments);
353-
});
354+
}
354355
},
355356

356357
handleNewRegions() {
@@ -380,7 +381,7 @@ export const AudioModel = types.compose(
380381
},
381382

382383
onHotKey(e) {
383-
e && e.preventDefault();
384+
e?.preventDefault();
384385
self._ws.togglePlay();
385386
return false;
386387
},
@@ -393,34 +394,6 @@ export const AudioModel = types.compose(
393394
self.playBackRate = val;
394395
},
395396

396-
createRegion(wsRegion, states) {
397-
let bgColor = self.selectedregionbg;
398-
const st = states.find((s) => s.type === "labels");
399-
400-
if (st) bgColor = Utils.Colors.convertToRGBA(st.getSelectedColor(), 0.3);
401-
402-
const r = AudioRegionModel.create({
403-
id: wsRegion.id ? wsRegion.id : guidGenerator(),
404-
pid: wsRegion.pid ? wsRegion.pid : guidGenerator(),
405-
parentID: wsRegion.parent_id === null ? "" : wsRegion.parent_id,
406-
start: wsRegion.start,
407-
end: wsRegion.end,
408-
score: wsRegion.score,
409-
readonly: wsRegion.readonly,
410-
regionbg: self.regionbg,
411-
selectedregionbg: bgColor,
412-
normalization: wsRegion.normalization,
413-
states,
414-
});
415-
416-
r.setWSRegion(wsRegion);
417-
418-
self.regions.push(r);
419-
self.annotation.addRegion(r);
420-
421-
return r;
422-
},
423-
424397
addRegion(wsRegion) {
425398
// area id is assigned to WS region during deserealization
426399
const find_r = self.annotation.areas.get(wsRegion.id);
@@ -484,9 +457,9 @@ export const AudioModel = types.compose(
484457
},
485458

486459
clearRegionMappings() {
487-
self.regs.forEach((r) => {
460+
for (const r of self.regs) {
488461
r.setWSRegion(null);
489-
});
462+
}
490463
},
491464

492465
onLoad(ws) {

web/libs/editor/src/tags/object/AudioUltra/view.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ const AudioUltraView: FC<AudioUltraProps> = ({ item, children, settings = {}, ch
7171
onError: item.onError,
7272
regions: {
7373
createable: !item.readonly,
74-
updateable: !item.readonly,
75-
deleteable: !item.readonly,
7674
},
7775
timeline: {
7876
backgroundColor: isDarkMode ? "rgb(38, 37, 34)" : "rgba(255,255,255,0.8)",

web/libs/editor/src/tags/object/Paragraphs/HtxParagraphs.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ class HtxParagraphsView extends Component {
303303
if (!states || states.length === 0 || ev.ctrlKey || ev.metaKey)
304304
return this._selectRegions(ev.ctrlKey || ev.metaKey);
305305

306+
if (item.annotation.isReadOnly()) {
307+
return;
308+
}
309+
306310
const selectedRanges = this.captureDocumentSelection();
307311

308312
if (selectedRanges.length === 0) {

web/libs/editor/src/tags/object/TimeSeries/Channel.jsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class ChannelD3 extends React.Component {
199199
} = this.props;
200200

201201
const activeStates = parent?.activeStates();
202-
const statesSelected = activeStates && activeStates.length;
202+
const statesSelected = activeStates?.length;
203203
const readonly = parent?.annotation?.isReadOnly();
204204

205205
// skip if event fired by .move() - prevent recursion and bugs
@@ -210,10 +210,13 @@ class ChannelD3 extends React.Component {
210210
const x = d3.mouse(d3.event.sourceEvent.target)[0];
211211
const newRegion = this.newRegion;
212212

213+
// double click handler to create instant region
213214
// when 2nd click happens during 300ms after 1st click and in the same place
214215
if (newRegion && Math.abs(newRegion.x - x) < 4) {
215216
clearTimeout(this.newRegionTimer);
216-
parent?.regionChanged(newRegion.range, ranges.length, newRegion.states);
217+
if (!readonly) {
218+
parent?.regionChanged(newRegion.range, ranges.length, newRegion.states);
219+
}
217220
this.newRegion = null;
218221
this.newRegionTimer = null;
219222
} else if (statesSelected) {
@@ -364,7 +367,7 @@ class ChannelD3 extends React.Component {
364367
const block = this.gCreator;
365368
const getRegion = this.getRegion;
366369
const x = this.x;
367-
const brush = (this.brushCreator = d3
370+
const brush = d3
368371
.brushX()
369372
.extent([
370373
[0, 0],
@@ -381,7 +384,9 @@ class ChannelD3 extends React.Component {
381384
// replacing default filter to allow ctrl-click action
382385
.filter(() => {
383386
return !d3.event.button;
384-
}));
387+
});
388+
389+
this.brushCreator = brush;
385390

386391
this.gCreator.call(this.brushCreator);
387392
}

0 commit comments

Comments
 (0)