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

fix(position-manager): account for quadrant moves #529

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion amd/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "templates-common-library",
"version": "0.0.529",
"version": "0.0.532",
"files": [
"/*"
],
Expand Down
2 changes: 1 addition & 1 deletion esm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "templates-common-library",
"version": "0.0.529-esm",
"version": "0.0.532-esm",
"files": [
"/*"
],
Expand Down
69 changes: 48 additions & 21 deletions src/functionality/positionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ interface PositionManagerBatch {

const positionManagerBatch: PositionManagerBatch = {};

const lastPositionValue: Map<string, string> = new Map(); // positionKey => serializedPosition
const serializePosition = ({ position, index }: IWidgetPosition = { position: "manual", index: 0 }) => `${position}-${index}`;

/**
* Deals with issue where widgets load at different times and the positions in the
* Map UI end up not matching what's prescribed in the Position Manager.
* https://devtopia.esri.com/WebGIS/arcgis-template-configuration/issues/3105
*
* Use debug === true to find the proper positionKeyLookup values
* (note widgets must be present in the UI, which means turned on in the config)
* @param view
* @param config
* @param positionKeyLookup
Expand All @@ -40,51 +46,62 @@ export function assertWidgetOrdering(
() => {
view.when(() => {
const watchWidgetOrdering = (quadrant: __esri.UIPosition) => {
let widgets = view.ui.getComponents(quadrant);
let firstAssertion = true;
watch(
() => config.updateCount,
() => {
const widgetsNew = view.ui.getComponents(quadrant);

const positionsHaveChanged: boolean =
widgets.length !== widgetsNew.length ||
widgets.some((el, i) => {
return el?.id !== widgetsNew[i]?.id;
let widgets = view.ui.getComponents(quadrant);
let positionsHaveChanged = widgets.some((el)=>{
// check last config value for positionValue
const positionKey = getPositionKey(el.id, positionKeyLookup);
const positionValue: IWidgetPosition = config[positionKey];
if(positionValue != null && positionValue?.position !== quadrant){
// major side effect - but if the app code doesn't handle moving between quadrants, then this is necessary
view.ui.move(el, positionValue);
}
const serializedPosition = serializePosition(positionValue);

return lastPositionValue.get(positionKey) !== serializedPosition;
});

if (positionsHaveChanged || firstAssertion) {
widgets = widgetsNew;
firstAssertion = false;
setTimeout(() => {
widgets = view.ui.getComponents(quadrant);
const sortedPositionList = widgets
.map((el) => {
const id =
positionKeyLookup.get(el.id) != null
? positionKeyLookup.get(el.id)
: el.id;
let positionKey = `${id}Position`;
let positionKey = getPositionKey(el.id, positionKeyLookup);
let positionValue = config[positionKey];
lastPositionValue.set(positionKey, serializePosition(positionValue));
if (debug) {
console.log(
`id: ${id}, ====> looking in config for: ` +
`id: ${el.id}, ====> looking in config for: ` +
`%c${positionKey}`,
"font-weight: bold; color: blue;"
);
if(positionValue == null){
console.log(
`%c${positionKey} doesn't seem to be a key. Check the ConfigSettings to find what it should be, and update positionKeyLookup with necessary override.`,
"font-weight: bold; color: red;"
);
}
}
return [el.id, config[positionKey]] as [
return [el.id, positionValue] as [
string,
{ index: number; position: string }
IWidgetPosition
];
})
.sort((a, b) => {
return a[1]?.index - b[1]?.index;
});
sortedPositionList.forEach((sortedPair, index) => {
const [id, positionLookup] = sortedPair;
positionLookup.index = index; // override to directly match sorted list
const el = widgets.find((elem) => elem.id === id);
view.ui.move({ component: el, ...positionLookup } as any);
updateExpandGroup(el, positionLookup);
const [id, positionValue] = sortedPair;
if(positionValue){
positionValue.index = index; // override to directly match sorted list
const el = widgets.find((elem) => elem.id === id);
view.ui.move({ component: el, ...positionValue } as any);
updateExpandGroup(el, positionValue);
}
});
}, 200);
}
Expand All @@ -98,10 +115,20 @@ export function assertWidgetOrdering(
watchWidgetOrdering("bottom-left");
watchWidgetOrdering("bottom-right");
});
}, {
initial: true
}
);
}

function getPositionKey(
id: string,
positionKeyLookup: Map<string, string>
): string {
const correctId = positionKeyLookup.get(id) != null ? positionKeyLookup.get(id) : id;
return `${correctId}Position`
}

/**
* This function handles the batch positioning of widgets in a view. Replace the `view.ui.move` method with this function to batch the positioning of widgets.
* @param {__esri.MapView | __esri.SceneView} view - The view in which the widgets are located.
Expand Down
Loading