Skip to content

Commit 08b0ad0

Browse files
committed
Merge branch 'develop' into 'fb-utc-3/popover-spark'
Workflow run: https://github.com/HumanSignal/label-studio/actions/runs/15130255175
2 parents 2ebd1f6 + a56a3b9 commit 08b0ad0

File tree

22 files changed

+787
-81
lines changed

22 files changed

+787
-81
lines changed

.github/workflows/apply-linters.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
ref: ${{ inputs.branch_name }}
2525

2626
- name: Set up Python
27-
uses: actions/setup-python@v4
27+
uses: actions/setup-python@v5
2828
with:
2929
python-version: '3.12'
3030

.github/workflows/docker-build-ontop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ jobs:
110110
${{ steps.calculate-docker-tags.outputs.docker-tags }}
111111
112112
- name: Push Docker image
113-
uses: docker/build-push-action@v6.16.0
113+
uses: docker/build-push-action@v6.17.0
114114
id: docker_build_and_push
115115
with:
116116
context: .

.github/workflows/docker-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ jobs:
130130
type=raw,value=${{ steps.version.outputs.build_version }}
131131
132132
- name: Push Docker image
133-
uses: docker/build-push-action@v6.16.0
133+
uses: docker/build-push-action@v6.17.0
134134
id: docker_build_and_push
135135
with:
136136
context: .

.github/workflows/docker-release-promote.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ jobs:
195195
${{ steps.generate-tags.outputs.ubuntu-tags }}
196196
197197
- name: Build and Push Release Ubuntu Docker image
198-
uses: docker/build-push-action@v6.16.0
198+
uses: docker/build-push-action@v6.17.0
199199
id: docker_build
200200
with:
201201
context: ${{ steps.release_dockerfile.outputs.release_dir }}

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ jobs:
140140

141141
- name: Upload coverage to Codecov
142142
if: ${{ github.event.pull_request.head.repo.fork == false && github.event.pull_request.user.login != 'dependabot[bot]' }}
143-
uses: codecov/codecov-action@v5.4.2
143+
uses: codecov/codecov-action@v5.4.3
144144
with:
145145
name: codecov-python-${{ matrix.python-version }}
146146
flags: pytests

docs/source/guide/storage.md

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,9 @@ When disabled, tasks in JSON format can be loaded directly from storage buckets
7777

7878
<img src="/images/source-storages-treat-off.png" class="make-intense-zoom">
7979

80-
###### On
81-
82-
When enabled, Label Studio automatically lists files from the storage bucket and constructs tasks. This is only possible for simple labeling tasks that involve a single media source (such as an image, text, etc.).*
83-
84-
<img src="/images/source-storages-treat-on.png" class="make-intense-zoom">
85-
86-
87-
#### One Task - One JSON File
88-
89-
If you plan to load JSON tasks from the Source Storage (`Treat every bucket object as a source file = No`), you must place only one task as the **dict** per one JSON file. Otherwise, Label Studio will not load your data properly.
80+
You may put multiple tasks inside the same JSON file, but not mix task formats inside the same file.
9081

91-
{% details <b>Example with tasks in separate JSON files</b> %}
82+
{% details <b>Example with bare tasks</b> %}
9283

9384

9485
`task_01.json`
@@ -107,11 +98,27 @@ If you plan to load JSON tasks from the Source Storage (`Treat every bucket obje
10798
}
10899
```
109100

101+
Or:
102+
103+
`tasks.json`
104+
```
105+
[
106+
{
107+
"image": "s3://bucket/1.jpg",
108+
"text": "opossums are awesome"
109+
},
110+
{
111+
"image": "s3://bucket/2.jpg",
112+
"text": "cats are awesome"
113+
}
114+
]
115+
```
116+
110117
{% enddetails %}
111118

112119
<br>
113120

114-
{% details <b>Example with tasks, annotations and predictions in separate JSON files</b> %}
121+
{% details <b>Example with tasks, annotations and predictions</b> %}
115122

116123
`task_with_predictions_and_annotations_01.json`
117124
```
@@ -137,28 +144,39 @@ If you plan to load JSON tasks from the Source Storage (`Treat every bucket obje
137144
}
138145
```
139146

140-
{% enddetails %}
141-
142-
<br>
147+
Or:
143148

144-
{% details <b>Python script to split a single JSON file with multiple tasks</b> %}
149+
`tasks_with_predictions_and_annotations.json`
150+
```
151+
[
152+
{
153+
"data": {
154+
"image": "s3://bucket/1.jpg",
155+
"text": "opossums are awesome"
156+
},
157+
"annotations": [...],
158+
"predictions": [...]
159+
},
160+
{
161+
"data": {
162+
"image": "s3://bucket/2.jpg",
163+
"text": "cats are awesome"
164+
}
165+
"annotations": [...],
166+
"predictions": [...]
167+
}
168+
]
169+
```
145170

146-
Python script to split a single JSON file containing multiple tasks into separate JSON files, each containing one task:
171+
{% enddetails %}
147172

148-
```python
149-
import sys
150-
import json
173+
<br>
151174

152-
input_json = sys.argv[1]
153-
with open(input_json) as inp:
154-
tasks = json.load(inp)
175+
###### On
155176

156-
for i, v in enumerate(tasks):
157-
with open(f'task_{i}.json', 'w') as f:
158-
json.dump(v, f)
159-
```
177+
When enabled, Label Studio automatically lists files from the storage bucket and constructs tasks. This is only possible for simple labeling tasks that involve a single media source (such as an image, text, etc.).*
160178

161-
{% enddetails %}
179+
<img src="/images/source-storages-treat-on.png" class="make-intense-zoom">
162180

163181

164182
### Target storage

docs/source/guide/tasks.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,9 @@ You can then import text tasks to label that match the following JSON format:
343343
}]
344344
}]
345345
```
346-
If you're placing JSON files in [cloud storage](storage.html), place 1 task in each JSON file in the storage bucket. If you want to upload a JSON file from your machine directly into Label Studio, you can place multiple tasks in one JSON file and import it using Label Studio GUI (Data Manager => Import button).
347346

348347
#### Example JSON with multiple tasks
349-
You can place multiple tasks in one JSON file if you're uploading the JSON file using Label Studio Import Dialog only (Data Manager => Import button).
348+
You can place multiple tasks in one JSON file if you're uploading the JSON file using Label Studio Import Dialog only (Data Manager => Import button), or when importing from [cloud storage](storage.html). When using cloud storage, you must ensure every task in the file is formatted the same way.
350349

351350
<br/>
352351
{% details <b>To place multiple tasks in one JSON file, use this JSON format example</b> %}
@@ -376,6 +375,22 @@ The "data" parameter must contain the "my_text" field defined in the text labeli
376375
}
377376
]
378377
{% endcodeblock %}
378+
379+
You can also use the bare contents of the "data" field without nesting, as long as you have no annotations or predictions.
380+
381+
{% codeblock lang:json %}
382+
[
383+
{
384+
"my_text":"Opossums like to be aloft in trees."
385+
},
386+
{
387+
"my_text":"Opossums are opportunistic."
388+
},
389+
{
390+
"my_text":"Opossums like to forage for food."
391+
}
392+
]
393+
{% endcodeblock %}
379394
{% enddetails %}
380395

381396
#### Example JSON for older versions of Label Studio

docs/source/guide/troubleshooting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ If there is only LIST permission, Label Studio can scan the bucket for the exist
190190
### Tasks don't load the way I expect
191191
192192
If the tasks sync to Label Studio but don't appear the way that you expect, maybe with URLs instead of images or with one task where you expect to see many, check the following:
193-
- If you're placing JSON files in [cloud storage](storage.html), place 1 task in each JSON file in the storage bucket. If you want to upload a JSON file from local storage into Label Studio, you can place multiple tasks in one JSON file.
193+
- If you're placing JSON files in [cloud storage](storage.html), ensure that if you have multiple tasks in the same file, they are all formatted the same way (for example, you cannot have 1 task with the raw contents of the `data` field and another task that contains annotations and predictions in the same file).
194194
- If you're syncing image or audio files, make sure **Treat every bucket object as a source file** is enabled.
195195
196196
### Unable to access local storage when using Windows

docs/themes/v2/layout/templates.ejs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
<div class="templates-grid">
66
<% page.cards.forEach(function(card) { %>
7+
<% const tags = typeof card.categories === "object" ? card.categories.join(", ") : card.categories %>
78
<div class="templates-card">
89
<img src="<%= card.image %>" alt="" />
910
<a href="<%= card.url %>"><%- partial("component/heading", {text: card.title, size: "XXSmall", tag: "span" }) %></a>
10-
<%- partial("component/text", {text: card.categories, tag: "p", size: "Small"}) %>
11+
<%- partial("component/text", {text: tags, tag: "p", size: "Small"}) %>
1112
</div>
1213
<% }); %>
1314
</div>

label_studio/feature_flags.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,7 +2096,7 @@
20962096
},
20972097
"fflag_feat_dia_2092_multitasks_per_storage_link": {
20982098
"key": "fflag_feat_dia_2092_multitasks_per_storage_link",
2099-
"on": false,
2099+
"on": true,
21002100
"prerequisites": [],
21012101
"targets": [],
21022102
"contextTargets": [],
@@ -2118,7 +2118,7 @@
21182118
"trackEvents": false,
21192119
"trackEventsFallthrough": false,
21202120
"debugEventsUntilDate": null,
2121-
"version": 2,
2121+
"version": 4,
21222122
"deleted": false
21232123
},
21242124
"fflag_feat_front_dev-2536_comment_notifications_short": {

poetry.lock

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/libs/editor/src/mixins/ToolManagerMixin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { FF_DEV_3391 } from "../utils/feature-flags";
77
export const ToolManagerMixin = types.model().actions((self) => {
88
return {
99
afterAttach() {
10-
if (ff.isActive(FF_DEV_3391) && !self.annotation) {
10+
if (ff.isActive(FF_DEV_3391) && self.annotationStore.initialized) {
11+
self.tools = self.annotationStore.names.get(self.name).tools;
1112
return;
1213
}
1314
const toolNames = self.toolNames ?? [];

web/libs/editor/src/regions/PolygonPoint.jsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { Circle, Rect } from "react-konva";
33
import { observer } from "mobx-react";
44
import { getParent, getRoot, hasParent, types } from "mobx-state-tree";
55

6+
import { RELATIVE_STAGE_HEIGHT, RELATIVE_STAGE_WIDTH } from "../components/ImageView/Image";
67
import { guidGenerator } from "../core/Helpers";
78
import { useRegionStyles } from "../hooks/useRegionColor";
9+
import { AnnotationMixin } from "../mixins/AnnotationMixin";
810
import { FF_DEV_3793, isFF } from "../utils/feature-flags";
9-
import { RELATIVE_STAGE_HEIGHT, RELATIVE_STAGE_WIDTH } from "../components/ImageView/Image";
1011

1112
const PolygonPointAbsoluteCoordsDEV3793 = types
1213
.model()
@@ -83,12 +84,10 @@ const PolygonPointRelativeCoords = types
8384
return self.parent?.parent;
8485
},
8586

86-
get annotation() {
87-
return getRoot(self).annotationStore.selected;
88-
},
8987
get canvasX() {
9088
return isFF(FF_DEV_3793) ? self.stage?.internalToCanvasX(self.x) : self.x;
9189
},
90+
9291
get canvasY() {
9392
return isFF(FF_DEV_3793) ? self.stage?.internalToCanvasY(self.y) : self.y;
9493
},
@@ -196,10 +195,12 @@ const PolygonPointRelativeCoords = types
196195
},
197196
}));
198197

199-
const PolygonPoint = isFF(FF_DEV_3793)
198+
const PolygonPointModel = isFF(FF_DEV_3793)
200199
? PolygonPointRelativeCoords
201200
: types.compose("PolygonPoint", PolygonPointRelativeCoords, PolygonPointAbsoluteCoordsDEV3793);
202201

202+
const PolygonPoint = types.compose("PolygonPoint", AnnotationMixin, PolygonPointModel);
203+
203204
const PolygonPointView = observer(({ item, name }) => {
204205
if (!item.parent) return;
205206

web/libs/editor/src/regions/TimeSeriesRegion.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ const Model = types
3131
return self.object;
3232
},
3333

34-
// Do not remove this annotation getter until saving/updating annotation in LS will work without errors
35-
get annotation() {
36-
const root = getRoot(self);
37-
38-
return root !== self ? root.annotationStore?.selected : null;
39-
},
40-
4134
getRegionElement() {
4235
return self._brushRef;
4336
},

0 commit comments

Comments
 (0)