Skip to content

Commit c9e2c47

Browse files
martinRenoupre-commit-ci[bot]trungleducgithub-actions[bot]
authored
Object properties panel: Use selected object name as the title (#540)
* Object properties panel: Use selected object name as the title * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update selected object between documents * Select primitive on creation * Update UI test * Update Playwright Snapshots --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Duc Trung Le <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 3961078 commit c9e2c47

File tree

5 files changed

+96
-23
lines changed

5 files changed

+96
-23
lines changed

packages/base/src/commands.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { DocumentRegistry } from '@jupyterlab/docregistry';
4343
import { PathExt } from '@jupyterlab/coreutils';
4444
import { MainViewModel } from './3dview/mainviewmodel';
4545
import { handleRemoveObject } from './panelview';
46-
46+
import { v4 as uuid } from 'uuid';
4747
export function newName(type: string, model: IJupyterCadModel): string {
4848
const sharedModel = model.sharedModel;
4949

@@ -241,6 +241,12 @@ export async function executeOperator(
241241
sharedModel.transact(() => {
242242
transaction(sharedModel);
243243
});
244+
setTimeout(() => {
245+
current.context.model.syncSelected(
246+
{ [objectModel.name]: { type: 'shape' } },
247+
uuid()
248+
);
249+
}, 0); // doing the selection at the next tick
244250
}
245251

246252
const OPERATORS = {
@@ -1217,9 +1223,10 @@ namespace Private {
12171223
name: Name
12181224
};
12191225

1220-
const sharedModel = current.context.model.sharedModel;
1226+
const jcadModel = current.context.model;
12211227

1222-
if (sharedModel) {
1228+
if (jcadModel) {
1229+
const sharedModel = jcadModel.sharedModel;
12231230
if (!sharedModel.objectExists(objectModel.name)) {
12241231
// Try a dry run with the update content to verify its feasibility
12251232
const currentJcadContent = current.context.model.getContent();
@@ -1241,6 +1248,12 @@ namespace Private {
12411248
objectModel.shapeMetadata = objMeta;
12421249
}
12431250
sharedModel.addObject(objectModel);
1251+
setTimeout(() => {
1252+
jcadModel.syncSelected(
1253+
{ [objectModel.name]: { type: 'shape' } },
1254+
uuid()
1255+
);
1256+
}, 0); // doing the selection at the next tick
12441257
} else {
12451258
showErrorMessage(
12461259
'The object already exists',

packages/base/src/panelview/objectproperties.tsx

+30-14
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,30 @@ class ObjectPropertiesReact extends React.Component<IProps, IStates> {
7575
if (changed) {
7676
this.props.cpModel.disconnect(this._sharedJcadModelChanged);
7777
this.props.cpModel.disconnect(this._onClientSharedStateChanged);
78+
const currentModel = changed.context.model;
79+
currentModel.sharedObjectsChanged.connect(this._sharedJcadModelChanged);
80+
const clients = currentModel.sharedModel.awareness.getStates() as Map<
81+
number,
82+
IJupyterCadClientState
83+
>;
7884

79-
changed.context.model.sharedObjectsChanged.connect(
80-
this._sharedJcadModelChanged
81-
);
82-
changed.context.model.clientStateChanged.connect(
83-
this._onClientSharedStateChanged
85+
this.setState(
86+
old => ({
87+
jcadOption: undefined,
88+
selectedObjectData: undefined,
89+
selectedObject: undefined,
90+
schema: undefined,
91+
filePath: changed.context.localPath,
92+
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
93+
clientId: currentModel.getClientId()
94+
}),
95+
() => {
96+
this._onClientSharedStateChanged(currentModel, clients);
97+
currentModel.clientStateChanged.connect(
98+
this._onClientSharedStateChanged
99+
);
100+
}
84101
);
85-
this.setState(old => ({
86-
jcadOption: undefined,
87-
selectedObjectData: undefined,
88-
selectedObject: undefined,
89-
schema: undefined,
90-
filePath: changed.context.localPath,
91-
jcadObject: this.props.cpModel.jcadModel?.getAllObject(),
92-
clientId: changed.context.model.getClientId()
93-
}));
94102
} else {
95103
this.setState({
96104
jcadOption: undefined,
@@ -251,6 +259,7 @@ class ObjectPropertiesReact extends React.Component<IProps, IStates> {
251259
newState = localState;
252260
}
253261
}
262+
254263
if (newState) {
255264
const selection = newState.selected.value;
256265
const selectedObjectNames = Object.keys(selection || {});
@@ -294,6 +303,13 @@ class ObjectPropertiesReact extends React.Component<IProps, IStates> {
294303
}));
295304
}
296305
}
306+
} else {
307+
this.setState(old => ({
308+
...old,
309+
schema: undefined,
310+
selectedObject: '',
311+
selectedObjectData: undefined
312+
}));
297313
}
298314
};
299315

packages/base/src/panelview/rightpanel.tsx

+50-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import {
22
IJCadFormSchemaRegistry,
3+
IJupyterCadClientState,
4+
IJupyterCadModel,
35
IJupyterCadTracker,
6+
ISelection,
47
JupyterCadDoc
58
} from '@jupytercad/schema';
69
import { SidePanel } from '@jupyterlab/ui-components';
@@ -24,11 +27,57 @@ export class RightPanelWidget extends SidePanel {
2427
tracker: options.tracker
2528
});
2629

30+
const updateTitle = (
31+
sender: IJupyterCadModel,
32+
clients: Map<number, IJupyterCadClientState>
33+
) => {
34+
const localState = sender.localState;
35+
if (!localState) {
36+
return;
37+
}
38+
39+
let selection: { [key: string]: ISelection } = {};
40+
if (localState.remoteUser) {
41+
// We are in following mode.
42+
// Sync selections from a remote user
43+
const remoteState = clients.get(localState.remoteUser);
44+
45+
if (remoteState?.selected?.value) {
46+
selection = remoteState?.selected?.value;
47+
}
48+
} else if (localState.selected?.value) {
49+
selection = localState.selected.value;
50+
}
51+
const selectionNames = Object.keys(selection);
52+
if (selectionNames.length === 1) {
53+
const selected = selectionNames[0];
54+
if (selected.startsWith('edge-') && selection[selected].parent) {
55+
header.title.label = selection[selected].parent;
56+
} else {
57+
header.title.label = selected;
58+
}
59+
} else {
60+
header.title.label = 'No selection';
61+
}
62+
};
63+
64+
let currentModel: IJupyterCadModel | undefined = undefined;
2765
this.addWidget(properties);
2866
this._model.documentChanged.connect((_, changed) => {
2967
if (changed) {
68+
if (currentModel) {
69+
currentModel.clientStateChanged.disconnect(updateTitle);
70+
}
71+
3072
if (changed.context.model.sharedModel.editable) {
31-
header.title.label = changed.context.localPath;
73+
currentModel = changed.context.model;
74+
const clients = currentModel.sharedModel.awareness.getStates() as Map<
75+
number,
76+
IJupyterCadClientState
77+
>;
78+
updateTitle(currentModel, clients);
79+
currentModel.clientStateChanged.connect(updateTitle);
80+
3281
properties.show();
3382
} else {
3483
header.title.label = `${changed.context.localPath} - Read Only`;

ui-tests/tests/ui.spec.ts

-5
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,6 @@ test.describe('UI Test', () => {
203203
.locator('[data-test-id="react-tree-root"]')
204204
.getByText('box2')
205205
.click();
206-
await page
207-
.locator('[data-test-id="react-tree-root"]')
208-
.getByText('Shape')
209-
.click();
210206
await page.getByLabel('Height*').click();
211207
await page.getByLabel('Height*').fill('32');
212208
await page.getByRole('button', { name: 'Submit' }).click();
@@ -310,7 +306,6 @@ test.describe('UI Test', () => {
310306
await page.getByTitle('New Box').getByRole('button').click();
311307
await page.getByRole('button', { name: 'Submit' }).click();
312308
await page.waitForTimeout(1000);
313-
await page.getByText('Box 1').click();
314309
await page.locator('#tab-key-1-6').click();
315310

316311
await page.waitForTimeout(1000);
Loading

0 commit comments

Comments
 (0)