Skip to content

Commit e74b0f0

Browse files
Merge 25.11 to 26.3
2 parents 7fae000 + 8f72088 commit e74b0f0

179 files changed

Lines changed: 18714 additions & 4712 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CageUI/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* * Copyright (c) 2025 Board of Regents of the University of Wisconsin System
3+
* * Copyright (c) 2026 Board of Regents of the University of Wisconsin System
44
* *
55
* * Licensed under the Apache License, Version 2.0 (the "License");
66
* * you may not use this file except in compliance with the License.
@@ -22,7 +22,10 @@ plugins {
2222
id 'org.labkey.build.module'
2323
}
2424
dependencies {
25+
implementation project(path: "${project.parent.path}:DBUtils", configuration: "apiJarFile")
26+
2527
BuildUtils.addLabKeyDependency(project: project, config: "implementation", depProjectPath: ":server:modules:LabDevKitModules:LDK", depProjectConfig: "apiJarFile")
2628
BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:LabDevKitModules:LDK", depProjectConfig: 'published', depExtension: 'module')
2729
BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: ":server:modules:ehrModules:ehr", depProjectConfig: 'published', depExtension: 'module')
30+
BuildUtils.addLabKeyDependency(project: project, config: "modules", depProjectPath: "${project.parent.path}:DBUtils", depProjectConfig: 'published', depExtension: 'module')
2831
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<!--
2+
~ /*
3+
~ * Copyright (c) 2026 Board of Regents of the University of Wisconsin System
4+
~ *
5+
~ * Licensed under the Apache License, Version 2.0 (the "License");
6+
~ * you may not use this file except in compliance with the License.
7+
~ * You may obtain a copy of the License at
8+
~ *
9+
~ * http://www.apache.org/licenses/LICENSE-2.0
10+
~ *
11+
~ * Unless required by applicable law or agreed to in writing, software
12+
~ * distributed under the License is distributed on an "AS IS" BASIS,
13+
~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ * See the License for the specific language governing permissions and
15+
~ * limitations under the License.
16+
~ */
17+
-->
18+
19+
<!DOCTYPE html>
20+
<html lang="en">
21+
<head>
22+
<meta charset="UTF-8">
23+
<title>CageUI Layout Editor Rules</title>
24+
</head>
25+
<body>
26+
<h3>Workflow</h3>
27+
<ol>
28+
<li>When initially loading the page select the grid size. For larger rooms with more cages you would want to select
29+
a larger grid to ensure that all the items can be placed on the layout. This grid size cannot be changed later.
30+
</li>
31+
<li>Move items to the layout by dragging and dropping them in position</li>
32+
<li>Open an items context menu by right-clicking the item.
33+
<ol>
34+
<li>
35+
Different items have different context menus, but they are all accessed the same way.
36+
</li>
37+
</ol>
38+
</li>
39+
<li>Place cages next to each other to merge them into the same rack or connect the racks.
40+
<ol>
41+
<li>
42+
Cages cannot be merged unless they share the same type.
43+
</li>
44+
<li>
45+
Generally you should create your racks before assigning them a rack type.
46+
</li>
47+
</ol>
48+
</li>
49+
</ol>
50+
<h3>Context Menus</h3>
51+
<div>
52+
<h4>Cage context menus support the following actions</h4>
53+
<ol>
54+
<li>
55+
Removing the cage or rack from the layout.
56+
</li>
57+
<li>
58+
Changing the rack.
59+
<ul>
60+
<li>
61+
In this menu you can also create new racks. Open the menu and enter the rack type and rack id, and it
62+
will be automatically assigned to that rack when you save.
63+
</li>
64+
</ul>
65+
</li>
66+
<li>
67+
Changing the cage number.
68+
</li>
69+
<li>
70+
Rotating the rack group.
71+
<ul>
72+
<li>
73+
Rotations start at 90 degrees.
74+
</li>
75+
<li>
76+
Rotations are done clockwise. For the starting rotation and position this means that the top of the rack group
77+
is the right side of the group.
78+
</li>
79+
<li>
80+
Rack groups are all the cages/racks that are connected to each other.
81+
</li>
82+
</ul>
83+
</li>
84+
</ol>
85+
</div>
86+
<div>
87+
<h4>Room Object context menus support the following actions</h4>
88+
<ol>
89+
<li>
90+
Removing the room object from the layout.
91+
</li>
92+
<li>Gate objects have have two additonal actions.
93+
<ol>
94+
<li>
95+
Set the room that the gate is connected to. This indicates that the two rooms have a connection that animals can go through.
96+
</li>
97+
<li>
98+
Closing/opening the gate, indicating if the gate is open or closed and if animals are able to go between rooms.
99+
</li>
100+
</ol>
101+
</li>
102+
</ol>
103+
</div>
104+
105+
<h3>Creating Templates</h3>
106+
<div>
107+
<h4>Rules for creating templates</h4>
108+
<ul>
109+
<li>
110+
All racks/cages in a room must have a default rack type. By default, this is what they are when placed in the room.
111+
This ensures that real racks/cages are not placed in rooms that "do not exist."
112+
</li>
113+
</ul>
114+
</div>
115+
<h3>Creating Real Rooms</h3>
116+
<div>
117+
<h4>Rules for creating real room layouts</h4>
118+
<ul>
119+
<li>
120+
All racks/cages in a room must have a real rack type.
121+
This ensures that racks/cages that "do not exist" are not placed in rooms that are real.
122+
</li>
123+
<li>No duplicate cage numbers.</li>
124+
</ul>
125+
</div>
126+
<h3>Additional Notes for Both Types of Layouts</h3>
127+
<div>
128+
Both real rooms and template rooms have a resizeable border that determines the border of the room.
129+
This helps compact the size of the layout into a more realistic room size when working with different size starting
130+
grids. Ensure that no room objects or cages are placed outside this border as they will not be shown when viewing the
131+
room from the display page.
132+
</div>
133+
<div>
134+
<h4>Additional Actions</h4>
135+
<ol>
136+
<li>The Grid Enabled button turns off the grid lines to show a better view of what the room will look like on
137+
the display page.
138+
</li>
139+
<li>Clear Layout wipes all the items from the layout, allowing you to start over.</li>
140+
</ol>
141+
</div>
142+
</body>
143+
</html>
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Layout Editor Documentation
2+
3+
This readme explains how the layout editor works and how to set up new room objects.
4+
5+
You can access the view with this url within your main container
6+
7+
`/cageui/WNPRC/EHR/layoutEditor.view`
8+
9+
If you are running the dev server just edit it slightly.
10+
11+
`/cageui/WNPRC/EHR/layoutEditorDev.view`
12+
13+
In order to use this project, make sure to enable the module in your folder set up within labkey.
14+
15+
This project was built for the Chrome browser. If you use a different browser, it may not work as expected. Additionally,
16+
the layout editor was not built for mobile devices. The idea behind this is that once the users build the rooms, they can
17+
be modified on mobile from different endpoints but the act of room creation is better done on desktop.
18+
19+
20+
# Workflow in detail
21+
22+
## Context Manager
23+
24+
The main layout editor entry point is `LayoutEditor.tsx`. This file loads in previous room data if required or simply starts
25+
a new room layout. When starting a new room layout, the user can select a room size from a list of predefined sizes. These sizes
26+
are present in the `constants.ts` file. Once a room is created with a certain size, this cannot be changed.
27+
28+
The layout editor initializes with a context manager `LayoutEditorContextManager.tsx` with its types described in
29+
`layoutEditorContextTypes.ts`. This context manager serves as a place to store the room state and has functions
30+
for any edits that might occur to the room state.
31+
32+
In the context manager (CM) there are two Room objects, **localRoom** and **room**, **room** serves as the initial room or
33+
previous room, and **localRoom** is the room that has changes applied to. This allows development to work with the previous room and
34+
the current room that has local changes applied to it. You can use **room** when saving to check for changes or apply previous room data
35+
to the **localRoom** that is being saved, **room** should not be modified at all during development.
36+
37+
**unitLocs** is another important state within the CM. This state tracks cage positional data within the layout and
38+
serves it in an easy-to-access object. Its keys are rack types and the values contain the x and y global coords of the cage object.
39+
This state tracks the locations of the cages, by rack type. This is used within the editor to determine if two cages are
40+
adjacent to each other. Any action that changes the cage location in the editor should update this state with the
41+
new locations. Please note that the coordinates here are global coords.
42+
43+
The last important state in the CM is **cageConnections** this state tracks which cages
44+
are connected/merged to other cages and is used within the CM when deleting cages to split cages into new groups.
45+
An example this is what happens when you have a row of three connected cages and delete the middle cage? The system will
46+
have to split up the remaining two cages on either side into new groups to handle this correctly. This is a complicated
47+
group of functions that hopefully shouldn't need to be updated as it should be working, but it's worth noting here. Additionally,
48+
it can be avoided by proper room creation or by deleting the entire group of cages/racks and rebuilding them if needed.
49+
50+
### **Important**
51+
52+
While the CM manages the state, this doesn't automatically handle the changes completely. There is a lot of DOM
53+
manipulation with adding new objects, merging cages, connecting racks, etc. These DOM changes cannot
54+
be performed within the CM and have to be done on the same file that the layout-grid SVG is served from. That is why the
55+
`Editor.tsx` file is very long.
56+
57+
## Editor
58+
59+
The `Editor.tsx` file is another important file here in the layout editor portion of the project.
60+
This file manages all the SVG DOM manipulation and changes that occur when adding and moving objects around the room.
61+
The file is also where the majority of the code is written for the layout editor.
62+
By pairing this file with the context manager and any used functions within the helper files you essentially have the
63+
entire layout editor. The editor file uses effects to track changes to the unitLocs state to determine if a merge or connect
64+
is requested, if the room should be reloaded with new changes to **localRoom** or when objects/cages are added to the layout.
65+
It uses D3.js and basic DOM functions to handle the dragging and placement of the objects within the editor.
66+
67+
## Templates vs Real layouts
68+
69+
The layout editor supports two styles of rooms, templates and real. While similar in building they differ on a couple
70+
fundamentals. Template rooms are created with the idea that they do not represent a real physcial location. They are merely
71+
a layout that will be loaded into the editor in the future for easier building by users. The major difference and key point
72+
here is that when a cage is dragged onto the layout it is considered to be a "default" of that cage type. "Defaults" do not
73+
represent real racks or cages and as such they cannot be saved in real rooms. So in order to save a room as a template,
74+
it's racks must all be a "default" type, otherwise it will throw an error. Likewise in order for a real room to be saved
75+
it cannot have any "default" types and the user must assign a real physical rack to that position. The system will not show
76+
racks that are already in other rooms preventing double assignment.
77+
78+
## Editor Context Menu
79+
80+
Every object that can be placed within the room has a context menu that the user can access via right-clicking.
81+
Room objects and cages have different menus, but they use the same component. Developers can add additional components to the
82+
context menu via the "menuItems" prop. Refer to the `CageUI Insturctions.html` file on what each current menu item will do.
83+
84+
## Adding New Objects
85+
86+
If you would like to add additional room objects or cage sizes that is also possible. Here is what you will have to do to
87+
make this possible.
88+
89+
1. Create your SVG file within an editor, I used Adobe Illustrator for this and exported it as an SVG. Once you create this
90+
file that will be used as your object add it to `CageUI/resources/web/CageUI/static`.
91+
1. If you encounter issues with loading the file after adding it here try going to `localhost:8080/cageui/static/{filename}.svg`
92+
to ensure that it works and is loaded in correctly.
93+
2. Add your object under the correct enum in `typings.ts`.
94+
1. If your new object is a rack/cage type add it under RackTypes, create a default as well.
95+
2. If your new object is a room object (ex. door) then add it under RoomObjectTypes.
96+
3. Add your new object to ehr_lookups.cageui_item_types. Ensure your enum value and table values are matching. Additionally,
97+
if your item is a caging type, give it a size in the description field of the table. The size is the number of cells of the object both length and width.
98+
This is untested for caging types that aren't perfect squares.
99+
3. Next you should add your object into the `Editor.tsx` file via the **RoomItemTemplate** component. Look to others for examples.
100+
101+
If done correctly, your new object should be available to be placed within the editor.
102+
103+
## Important Notes
104+
105+
Here are some additional things to keep in mind when using the layout editor.
106+
107+
1. When cages are placed within the layout they are assigned a rack group, rack and then their cage number/id
108+
2. Users can merge two cages. When this is done, it moves the dragged cage into the target cages rack.
109+
3. Users can connect two cages. When this is done, it moves the dragged cage and rack into the target cages rack group.
110+
4. Merging and connecting is created with the idea that it lets users build racks and then connect racks, all from single cages. These
111+
changes are reflected within the DOM as well as the state.
112+
1. To get a grasp on what goes on here, I would suggest inspecting the 'layout-grid' SVG within the DOM and using an
113+
effect to console log the localRoom state variable from the Editor.tsx file.
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
3+
# Housing Changes
4+
5+
### 1. Add New Cage Column
6+
#### A.
7+
We have to remove the old cage table that is used in ehr_lookups with the new cage table in the cageui module.
8+
For the WNPRC this change needed to be done in the following files.
9+
10+
1. >WNPRC_EHR/resources/queries/study/Housing.query.xml
11+
2. >WNPRC_EHR/resources/queries/study/Housing/.qview.xml
12+
3. >WNPRC_EHR/resources/queries/study/Housing/Active Housing.qview.xml
13+
4. >WNPRC_EHR/resources/queries/study/Housing/Current Housing Plus Weight.qview.xml
14+
5. >WNPRC_EHR/resources/referenceStudy/study/datasets/datasets_metadata.xml
15+
6. >WNPRC_EHR/resources/web/ehr/metadata/Default.js
16+
7. >WNPRC_EHR/resources/web/ehr/metadata/Metadata.js
17+
8. >WNPRC_EHR/resources/web/wnprc_ehr/wnprcOverRides.js
18+
19+
#### B.
20+
After changing these files, go into the table definition editor in EHR and rename the cage column to cageOld.
21+
Then add a new column named cage. This will rename the previous cage column while preserving the data and
22+
allowing us to work with the new cage column under the old name.
23+
24+
As we add new data to the housing table we should insert it under the new column if using the new housing system.
25+
If using the old housing system, insert it under the old column. This will allow us to use the old housing system while
26+
testing the new system until we are ready to switch over to the new housing system.
27+
28+
At the WNPRC we will only be using the new system in a select few rooms for testing. Unfortunately, the users will have
29+
to submit their housing changes under both systems during this phase until we are ready to switch over. This will ensure
30+
data integrity.
31+
32+
### 3. Cage Details
33+
Add override for cageDetails.html and cageDetails.view.xml including new cages table instead of cages from ehr_lookups.
34+
35+
36+
Next go through and update the links so they point to your module instead of "ehr".
37+
Add rooms.query.xml file to your ehr_lookups schema and edit the url there as well.
38+
39+
Old:
40+
>/ehr/WNPRC/EHR/cageDetails.view?room=a140a&cage=0001
41+
42+
New:
43+
>/wnprc_ehr/WNPRC/EHR/cageDetails.view?room=a140a&cage=0001
44+
45+

0 commit comments

Comments
 (0)