Skip to content

feat: Points experiment #7454

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

Open
wants to merge 29 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
17b7194
First working version
makseq May 1, 2025
0dd17db
Works!
makseq May 1, 2025
9584874
Revert
makseq May 1, 2025
7191c84
Refactoring
makseq May 1, 2025
9718d6c
Deck.gl working version
makseq May 1, 2025
73d59eb
Fix
makseq May 1, 2025
71bc21f
Fixes
makseq May 1, 2025
4286277
Before debugging
makseq May 1, 2025
c3c630f
Working version with scatter settings and category
makseq May 2, 2025
6ae50d3
Before point layers
makseq May 2, 2025
ab1afaf
Working with colors
makseq May 2, 2025
f41adb5
Multiplayers
makseq May 2, 2025
bc0f612
Multilayer redesign
makseq May 2, 2025
a8066bb
Add activeId state at view
makseq May 2, 2025
7c8ee0d
Backend api for all base task points. Loading on the frontend for all…
makseq May 3, 2025
9f8443f
Working with normal one point click reloading!
makseq May 4, 2025
2f83163
Working. Add more files.
makseq May 4, 2025
a0b2109
Fix highligh red active point
makseq May 5, 2025
c5d8157
Some working state, but selection works not fast, however map is used…
makseq May 8, 2025
e868bf0
Selection works fast!
makseq May 8, 2025
c4995a4
Revert js binaries
makseq May 8, 2025
e95f3e5
Add datamanager rules
makseq May 8, 2025
ce0570b
Use DM callAPI refactoring
makseq May 9, 2025
822885c
Working gray points with dm filters
makseq May 14, 2025
abf3140
Add more
makseq May 14, 2025
4e8ffa3
Merge branch 'develop' of github.com:heartexlabs/label-studio into po…
makseq May 15, 2025
7dc05f7
Merge branch 'develop' of github.com:heartexlabs/label-studio into po…
makseq May 16, 2025
d1f0134
Working filtered points.
makseq May 16, 2025
e591f45
Some checks: See Persisting Class Field in ScatterSettingsDialog in C…
makseq Jun 3, 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
75 changes: 75 additions & 0 deletions .cursor/rules/datamanager-api.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
description:
globs: **/datamanager/**
alwaysApply: false
---
# Data Manager – API usage conventions

## 1. Prefer `root.apiCall(...)`
• Always call the backend through `root.apiCall` (inside MST models) or
`datamanager.apiCall` (inside plain JS/React).
• Never access `APIProxy` methods directly from components/stores.

```js
// inside a store action
const data = yield root.apiCall("tasks", { page: 1, pageSize: 50 });
```

## 2. Signature
`apiCall(methodName, params?, body?, options?)`

| Arg | Type | Notes |
|------------|--------------|------------------------------------------------------|
| methodName | string | Must exist in `src/sdk/api-config.js` |
| params | object | • Keys matching `:vars` in the endpoint path are substituted.<br>• All remaining keys become query-string params. |
| body | object | POST / PATCH payload (will be JSON-stringified) |
| options | object | `{ errorHandler?, headers?, allowToCancel?, alwaysExpectJSON? }` |

### 2.1 `allowToCancel`
Adds an `AbortController`; subsequent identical requests cancel previous ones.
```js
yield root.apiCall("tasks", params, {}, { allowToCancel: true });
```

### 2.2 `errorHandler`
Return `true` to mark the error as handled and suppress the default toast.
```js
yield root.apiCall("task", { taskID }, undefined, {
errorHandler: err => { log(err); return true; }
});
```

## 3. Endpoint definitions
Add/modify endpoints only in `api-config.js`.
Structure:

```js
export const APIConfig = {
gateway : "/api",
endpoints: {
tasks : "/tasks", // GET
task : { path: "/tasks/:taskID", method: "get" },
// …
},
};
```

## 4. Automatic shared params
`project` and `dataset` IDs are appended automatically by `APIProxy` when present.

## 5. Request/response transforms
Pass a `apiTransform` map to `<DataManager>` to mutate params/body/headers:
```js
<DataManager apiTransform={{
tasks: {
params : p => ({ ...p, extra: 1 }),
body : b => ({ ...b, foo: "bar" }),
headers: h => ({ ...h, "X-Feature": "on" }),
}
}}/>
```

## 6. Do NOT
✗ Hard-code URLs in components.
✗ Mix window‐fetch logic with business logic.
✗ Forget to await the returned Promise (it always resolves, never throws).
27 changes: 27 additions & 0 deletions .cursor/rules/datamanager-legacy-components.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
description:
globs: **/datamanager/**
alwaysApply: false
---
# Data-Manager Legacy Components

Use these **only** inside `web/libs/datamanager`.

| Component (path) | Purpose |
|-----------------------------------------|-------------------------------------|
| `Common/Modal/Modal.jsx` | Imperative & confirm/info dialogs |
| `Common/Button/Button.jsx` | BEM button + `Button.Group` |
| `Common/Space/Space.jsx` | Flex/inline-flex gap helper |
| `Common/Spinner/Spinner.jsx` | Inline SVG spinner |
| `Common/Table/Table.jsx` | Virtualised table |
| `Common/Dropdown` | Custom dropdown / select |
| `Common/Tabs` | Draggable tab bar |
| `Common/Pagination` | Pager with page-size select |
| `Common/Badge`, `Tag` | Status labels |
| etc. | |

Guidelines:

* Keep styles in the same folder (`*.scss`), BEM naming.
* Do **not** introduce Tailwind into these components.
* When moving features out of Data-Manager, rewrite them with `@humansignal/ui` primitives.
39 changes: 39 additions & 0 deletions .cursor/rules/datamanager-naming.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
description:
globs: **/datamanager/**
alwaysApply: false
---
# Data Manager – Naming conventions

## 1. General
| Kind | Convention | Example |
|---------------------|------------------------|---------------------------------|
| React component | `PascalCase` | `ScatterView`, `DataManager` |
| Hook | `useCamelCase` prefix | `useShortcut`, `useScatterLayers` |
| Function / variable | `camelCase` | `fetchProject`, `pageSize` |
| Boolean | `is/has/can` prefix | `isLoading`, `hasError` |
| Constant value | `UPPER_SNAKE_CASE` | `DEFAULT_TOOLBAR` |
| MST model | `PascalCase` | `TaskModel`, `TabStore` |
| File name | mirror exported symbol | `ScatterView.tsx` |

## 2. Abbreviations
• Avoid abbreviations unless they are industry-standard (`API`, `SDK`, `ID`).
• Do **not** mix abbreviation casing: `apiCall` (not `APICall`).

## 3. React props & state
• Props interfaces end with `Props`: `ScatterViewProps`.
• Local state variables follow the `verb + Noun` pattern: `setLoading`.

## 4. Enumerations / literals
• Prefer union string literals over `enum`.
```ts
type ViewMode = "list" | "grid" | "scatter";
```

## 5. Derived values
Prefix with `computed` or suffix with descriptor: `computedBounds`, `totalPages`.

## 6. Do NOT
✗ Use Hungarian notation.
✗ Use snake_case for JS/TS variables.
✗ Prefix private fields with underscores (except when mirroring existing code that already does this).
72 changes: 72 additions & 0 deletions .cursor/rules/datamanager-stores.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
description:
globs: **/datamanager/**
alwaysApply: false
---
# Data Manager – MobX-state-tree store rules

## 1. Store structure
```txt
AppStore – root, injected into <Provider/>
├─ Tabs/TabStore
├─ TasksStore (DataStore mixin)
└─ AnnotationStore (DataStore mixin)
```
All stores live in `src/stores/**` and **never import React**.

## 2. DataStore mixin
When you need a paginated list, extend the generic `DataStore`:

```js
export const TasksStore = DataStore("tasksStore", {
listItemType : TaskModel,
apiMethod : "tasks", // MUST exist in api-config
properties : { target: "tasks" },
});
```

### Built-in helper actions
• `fetch({ page, reload, interaction })`
• `setSelected(id | model)` & `unset()`
• `focusPrev()` / `focusNext()`
• `updateItem(id, patch)` – merges server response into MST model

### Flags
`loading`, `loadingItem`, `loadingItems[]`, `total`, `pageSize`, `hasNextPage`

## 3. Accessing the root / SDK
```js
import { getRoot } from "mobx-state-tree";

const root = getRoot(self); // inside any MST node
root.apiCall("task", { taskID }); // API
root.SDK.invoke("taskSelected"); // cross-app events
```

## 4. Async flows
• **Use `flow(function* () { … })`** for every async action.
• Always wrap calls in `try / catch` or rely on `AppStore.apiCall` which never throws.
• Check `result.error` instead of relying on exceptions.

## 5. Selection & focus
Store `selectedId` and `highlightedId` as primitives; expose computed getters:
```js
get selected() { return self.list.find(i => i.id === self.selectedId); }
```

## 6. Events
Emit UI-level events through `root.SDK.invoke(eventName, payload)`; do not use
window events or PubSub libs.

## 7. React integration
React components observe stores via:
```jsx
export const Table = inject("store")(observer(TableImpl));
```
• No state is duplicated in React.
• Components receive plain snapshots (`view.filterSnapshot`, `view.selected.snapshot`) for serialization.

## 8. Do NOT
✗ Mutate MST nodes outside of `actions`.
✗ Call `fetch()` directly from React `render`; use `useEffect`.
✗ Import stores into each other (use `getRoot` instead).
15 changes: 14 additions & 1 deletion .cursor/rules/react.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
description: React coding standards and best practices for the LabelStudio clientside application
globs: **/*.jsx,**/*.tsx
alwaysApply: false
---

# React Best Practices
Expand Down Expand Up @@ -125,4 +126,16 @@ globs: **/*.jsx,**/*.tsx
- Keep components focused on a single responsibility
- Document complex logic with clear comments
- Follow the project's folder structure and naming conventions
- Prefer controlled components over uncontrolled ones
- Prefer controlled components over uncontrolled ones

## Readability & Formatting

- Always run `make fmt-all` (Prettier/Biome/Ruff) before committing.
- Use spaces around binary operators and after commas: `const xs = pts.map(p => p.data.x);` not `pts.map(p=>p.data.x)`.
- Limit line length to 120 chars; break long expressions.

## Documentation & Comments

- Top-level JSDoc for every exported component/hook explaining props & side-effects.
- Inline comments for non-obvious math / transforms.
- Avoid redundant comments; prefer expressive variable names.
19 changes: 18 additions & 1 deletion .cursor/rules/typescript.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
description: TypeScript coding standards and best practices for the LabelStudio clientside application
globs: **/*.ts,**/*.tsx,**/*.d.ts
alwaysApply: false
---

# TypeScript Best Practices
Expand Down Expand Up @@ -54,4 +55,20 @@ globs: **/*.ts,**/*.tsx,**/*.d.ts
- Implement the Repository pattern for data access
- Use the Factory pattern for object creation
- Leverage dependency injection
- Use the Module pattern for encapsulation
- Use the Module pattern for encapsulation

## Readability & Formatting

- Always run `make fmt-all` (Prettier/Biome/Ruff) before pushing.
- Use spaces around operators and after commas.
- Prefer multi-line object literals with trailing commas.

## React + TS patterns

- Prefer `FC<Props>` or explicit function annotations.
- Never use `any`; fallback to `unknown` + type guards.
- Use union types instead of enums when possible.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why?


## Documentation
- Add `/** ... */` JSDoc to every public function/component/hook.
- Describe parameters, return value, side-effects.
63 changes: 63 additions & 0 deletions .cursor/rules/ui-components-system.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
description:
globs:
alwaysApply: false
---
# Component System – General Rules

## 1. Which library to import from?
| Scenario | Import from | Notes |
|------------------------------------|-----------------------------|--------------------------|
| *New* front-end code (apps/libs) | `@humansignal/ui` | Tailwind + Radix shadcn |
| Data-Manager internals | `web/libs/datamanager/...` | Legacy BEM-SCSS |
| Page-level blocks shared by apps | `@humansignal/app-common` | may re-export UI parts |

**Never** mix DM-internal BEM components with the Tailwind ones in the same view.

## 2. Dialogs

1. **Radix Dialog** (`@humansignal/ui → Dialog*`):
```tsx
import { Dialog, DialogTrigger, DialogContent,
DialogHeader, DialogFooter, DialogTitle } from "@humansignal/ui";

<Dialog>
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
<DialogContent>
<DialogHeader><DialogTitle>Title</DialogTitle></DialogHeader>
…body…
<DialogFooter><Button variant="primary">OK</Button></DialogFooter>
</DialogContent>
</Dialog>
```
2. **DM Modal** (`Modal.confirm/info`): keep inside Data-Manager only.

## 3. Buttons

• Prefer `@humansignal/ui` `Button`.
• Use `ButtonGroup` for horizontal groups.
• Disable with `waiting` to show spinner.
• For non-button nodes use `buttonVariant({...}, className)` helper.

Legacy `Common/Button` must **not** leak outside Data-Manager.

## 4. File / folder organisation

my-component/
my-component.tsx
my-component.stories.tsx # always add Storybook
my-component.module.scss # only if Tailwind is insufficient
index.ts # re-export

## 5. Theming & Tokens

• Tailwind config comes from `@humansignal/ui`.
• Only semantic tokens (`bg-primary-background`) – never raw palette names.
• Use `cn()` helper for class merges.

## 6. Accessibility

• Dialogs must trap focus (Radix does by default).
• Buttons require `aria-*` if they aren’t `<button>`.


1 change: 1 addition & 0 deletions label_studio/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
re_path(r'^', include('ml.urls')),
re_path(r'^', include('webhooks.urls')),
re_path(r'^', include('labels_manager.urls')),
re_path(r'^', include('scatter.urls')),
re_path(r'data/local-files/', views.localfiles_data, name='localfiles_data'),
re_path(r'version/', views.version_page, name='version'), # html page
re_path(r'api/version/', views.version_page, name='api-version'), # json response
Expand Down
Loading
Loading