mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
- web ui features to add a new cost schedules, and root cost items
- improved ui for cost schedules - sharing more css across files - refactor get_predefined_types(cost_schedule)
This commit is contained in:
@@ -176,6 +176,11 @@ class BlenderNamespace(socketio.AsyncNamespace):
|
||||
blender_messages[sid]["cost_value"] = data
|
||||
await sio.emit("cost_value", {"blenderId": sid, "data": data}, namespace="/web")
|
||||
|
||||
async def on_predefined_types(self, sid, data):
|
||||
print(f"Predefined types from Blender client {sid}")
|
||||
blender_messages[sid]["predefined_types"] = data
|
||||
await sio.emit("predefined_types", {"blenderId": sid, "data": data}, namespace="/web")
|
||||
|
||||
async def schedules(request):
|
||||
with open("templates/index.html", "r") as f:
|
||||
template = f.read()
|
||||
|
||||
@@ -5,24 +5,19 @@
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
/* prevent text from being selceted */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
td:not(:first-child) {
|
||||
text-align: center;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
td {
|
||||
|
||||
border-right: 1px solid #ddd;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
|
||||
}
|
||||
|
||||
.nested {
|
||||
@@ -39,22 +34,15 @@ td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
border: 1px solid #e1e4e8;
|
||||
input, select {
|
||||
background-color: var(--blender-button-background, var(--bg-color));
|
||||
color: var(--blender-button-text, var(--text-color));
|
||||
border-color: var(--blender-button-border, var(--border-color));
|
||||
transition: filter 0.2s ease;
|
||||
border-radius: 6px;
|
||||
background-color:inherit;
|
||||
padding: 6px 8px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color:inherit;
|
||||
transition: border-color 0.2s cubic-bezier(0.3, 0, 0.5, 1);
|
||||
height: inherit;
|
||||
margin-left: 0.5em;
|
||||
@@ -62,12 +50,11 @@ input {
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #0366d6;
|
||||
border-color: #28a745;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px rgba(3, 102, 214, 0.3);
|
||||
box-shadow: 0 0 0 3px #28a745;
|
||||
}
|
||||
|
||||
|
||||
#cost-items tr:hover, .highlighted {
|
||||
background-color: #ffb936;
|
||||
color : black;
|
||||
@@ -87,13 +74,17 @@ input:focus {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.cost-values-form {
|
||||
.floating-form {
|
||||
min-width: 40%;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
background-color: #363636;
|
||||
border: 1px solid black;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
z-index: 9999;
|
||||
cursor: move;
|
||||
padding: 20px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.cost-values-table {
|
||||
@@ -120,18 +111,20 @@ input:focus {
|
||||
}
|
||||
|
||||
.action-button {
|
||||
background-color: #28a745; /* GitHub green color */
|
||||
background-color: #28a745;
|
||||
border: none;
|
||||
color: #fff; /* White text color */
|
||||
padding: 0.5em 1em; /* Adjust padding as needed */
|
||||
color: #fff;
|
||||
padding: 0.5em 1em;
|
||||
cursor: pointer;
|
||||
border-radius: 6px; /* Slightly rounded corners */
|
||||
font-weight: bold; /* Make the text bold */
|
||||
text-decoration: none; /* Remove underline */
|
||||
display: inline-block; /* Make the button inline */
|
||||
transition: background-color 0.3s ease; /* Add a smooth transition */
|
||||
border-radius: 6px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
transition: background-color 0.3s ease;
|
||||
width: fit-content;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
background-color: #218838; /* Darker green color on hover */
|
||||
background-color: #218838;
|
||||
}
|
||||
|
||||
@@ -1,288 +1,166 @@
|
||||
@import url("./components/card.css");
|
||||
|
||||
:root {
|
||||
--font-family: Arial, sans-serif;
|
||||
--base-font-size: 16px;
|
||||
--margin-tiny: 0.125rem;
|
||||
--margin-small: 0.625rem;
|
||||
--margin-medium: 1.25rem;
|
||||
--margin-large: 2.5rem;
|
||||
--padding-tiny: 0.125rem;
|
||||
--padding-small: 0.625rem;
|
||||
--padding-medium: 1rem;
|
||||
--font-size-small: 1rem;
|
||||
--font-size-large: 1.2rem;
|
||||
--logo-height: 1.5rem;
|
||||
--nav-height: 0.625rem;
|
||||
--border-radius: 0.3rem;
|
||||
--folder-collapse-font-size: 0.75rem;
|
||||
--folder-collapse-font-family: Courier, "Courier New", monospace;
|
||||
--box-shadow: 0 0 0.7rem #5f5f5f66;
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
color-scheme: dark;
|
||||
--bg-color: #252525;
|
||||
--primary-text-color: #e0e0e0;
|
||||
--secondary-text-color: #c7c7c7;
|
||||
--nav-bg-color: #121212;
|
||||
--nav-border-color: #25682a;
|
||||
--nav-link-color: #fff;
|
||||
--nav-link-hover-color: #3fb449;
|
||||
--warning-color: #FFDB8F;
|
||||
--border-color: #464444;
|
||||
--hover-bg-color: #3a3a3a;
|
||||
--highlight-color: #009136;
|
||||
--task-complete-bg-color: #777777;
|
||||
--milestone-border-color: #ffffff;
|
||||
--group-item-bg-color: #4b4b4b;
|
||||
--input-bg-color: #3b3b3b;
|
||||
--input-border-color: #000;
|
||||
--border-color: #464444;
|
||||
}
|
||||
|
||||
:root.light {
|
||||
color-scheme: light;
|
||||
--bg-color: #ffffff;
|
||||
--primary-text-color: #000000;
|
||||
--nav-bg-color: #f8f8f8;
|
||||
--nav-border-color: #cccccc;
|
||||
--nav-link-color: #000000;
|
||||
--nav-link-hover-color: #38a63d;
|
||||
--warning-color: #FF4500;
|
||||
--border-color: #222;
|
||||
}
|
||||
|
||||
|
||||
*:not(td, tr, td, .gmain) {
|
||||
border-radius: var(--border-radius) !important;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: var(--base-font-size);
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--blender-window-background, var(--bg-color));
|
||||
color: var(--blender-text, var(--primary-text-color));
|
||||
margin: 0;
|
||||
font-family: var(--font-family);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#container {
|
||||
flex: 1;
|
||||
padding: var(--margin-small);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
height: var(--nav-height);
|
||||
padding: var(--padding-medium) 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-bottom: 2px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
margin-left: var(--margin-large);
|
||||
height: var(--logo-height);
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-right: var(--margin-large);
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
}
|
||||
|
||||
nav ul li a:hover,
|
||||
nav ul li a.active {
|
||||
color: var(--blender-selected-object, var(--nav-link-hover-color));
|
||||
}
|
||||
|
||||
.warning,
|
||||
.warning-icon {
|
||||
color: var(--blender-info-warning, var(--warning-color));
|
||||
}
|
||||
@import url("./shared.css");
|
||||
|
||||
.table-description {
|
||||
margin-bottom: var(--margin-medium);
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border-color: var(--blender-tab-outline, var(--border-color));
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: var(--box-shadow);
|
||||
text-align: center;
|
||||
margin-bottom: var(--margin-medium);
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
border-color: var(--blender-tab-outline, var(--border-color));
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
border-radius: 0.25rem;
|
||||
box-shadow: var(--box-shadow);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-description tr {
|
||||
display: table-row;
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
display: table-row;
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
}
|
||||
|
||||
.table-description tr:nth-child(even) {
|
||||
background-color: var(--blender-even-row);
|
||||
background-color: var(--blender-even-row);
|
||||
}
|
||||
|
||||
.table-description tr:nth-child(odd) {
|
||||
background-color: var(--blender-odd-row);
|
||||
background-color: var(--blender-odd-row);
|
||||
}
|
||||
|
||||
#toggle-theme {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-large);
|
||||
margin-right: var(--margin-medium);
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-large);
|
||||
margin-right: var(--margin-medium);
|
||||
}
|
||||
|
||||
#toggle-theme:focus {
|
||||
outline: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#client-list {
|
||||
position: absolute;
|
||||
top: calc(0 + var(--nav-height));
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: calc(0 + var(--nav-height));
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#client-list.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#connected-list-div {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.client {
|
||||
padding: var(--margin-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
cursor: pointer;
|
||||
padding: var(--margin-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.client-details {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding-left: var(--padding-small);
|
||||
transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
margin-top: var(--margin-tiny);
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding-left: var(--padding-small);
|
||||
transition: max-height 0.2s ease-out, padding 0.2s ease-out,
|
||||
opacity 0.1s ease-out;
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
margin-top: var(--margin-tiny);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.client-details.show {
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.client-detail {
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
padding: var(--padding-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
#show-connected-button {
|
||||
width: auto;
|
||||
background-color: var(--blender-panel-header, var(--bg-color));
|
||||
font-size: var(--base-font-size);
|
||||
width: auto;
|
||||
background-color: var(--blender-panel-header, var(--bg-color));
|
||||
font-size: var(--base-font-size);
|
||||
}
|
||||
|
||||
#show-connected-button:hover,
|
||||
.scroll-button:hover {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.scroll-button {
|
||||
font-size: var(--base-font-size);
|
||||
margin-left: var(--margin-tiny);
|
||||
margin-top: var(--margin-small);
|
||||
font-size: var(--base-font-size);
|
||||
margin-left: var(--margin-tiny);
|
||||
margin-top: var(--margin-small);
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
text-align: right;
|
||||
padding: var(--padding-tiny);
|
||||
border-top: 1px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
text-align: right;
|
||||
padding: var(--padding-tiny);
|
||||
border-top: 1px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
margin-right: var(--margin-small);
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
margin-right: var(--margin-small);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.gantt-info {
|
||||
margin: 0.5rem;
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: bold;
|
||||
margin: 0.5rem;
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 0.5rem;
|
||||
font-size: var(--font-size-small);
|
||||
cursor: pointer;
|
||||
margin: 0.5rem;
|
||||
font-size: var(--font-size-small);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media print {
|
||||
.no-print {
|
||||
display: none;
|
||||
}
|
||||
.no-print {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
button,
|
||||
select {
|
||||
background-color: var(--blender-button-background, var(--bg-color));
|
||||
color: var(--blender-button-text, var(--text-color));
|
||||
border-color: var(--blender-button-border, var(--border-color));
|
||||
transition: filter 0.2s ease;
|
||||
background-color: var(--blender-button-background, var(--bg-color));
|
||||
color: var(--blender-button-text, var(--text-color));
|
||||
border-color: var(--blender-button-border, var(--border-color));
|
||||
transition: filter 0.2s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
filter: brightness(1.2);
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
/* ------------ Overwriting JSGantt CSS rules ------------ */
|
||||
/* ------------------- for dark theme ------------------- */
|
||||
|
||||
:root.dark div.gantt {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--secondary-text-color);
|
||||
background-color: var(--bg-color);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
:root.dark .gantt table,
|
||||
:root.dark .gantt td {
|
||||
border-color: var(--border-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
/* Headings and cell defaults */
|
||||
@@ -295,8 +173,8 @@ button:hover {
|
||||
:root.dark .gname,
|
||||
:root.dark .ggroupitem,
|
||||
:root.dark .gtaskheading {
|
||||
background-color: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.dark .gtaskheading,
|
||||
@@ -312,129 +190,128 @@ button:hover {
|
||||
:root.dark .gchartlbl,
|
||||
:root.dark .gcontainercol,
|
||||
:root.dark .genddate {
|
||||
color: var(--secondary-text-color);
|
||||
border-color: var(--border-color);
|
||||
color: var(--secondary-text-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.dark .gtaskname>div {
|
||||
color: var(--secondary-text-color);
|
||||
:root.dark .gtaskname > div {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
:root.dark .gtaskbarcontainer.gplan,
|
||||
:root.dark .gchartlbl.gcontainercol {
|
||||
background: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
background: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.dark .gtaskname div,
|
||||
:root.dark .gtaskheading div,
|
||||
:root.dark .gtaskname span {
|
||||
color: var(--secondary-text-color);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
:root.dark .gtasklist,
|
||||
:root.dark .gadditional {
|
||||
border: var(--border-color) 1px solid;
|
||||
border: var(--border-color) 1px solid;
|
||||
}
|
||||
|
||||
:root.dark .gchartgrid {
|
||||
background-color: var(--bg-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
:root.dark .glistgrid,
|
||||
:root.dark .glistlbl {
|
||||
background-color: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--bg-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
/* Dark mode scrollbar */
|
||||
:root.dark .frame::-webkit-scrollbar-thumb,
|
||||
:root.dark .frame::-webkit-scrollbar-track {
|
||||
background-color: var(--bg-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
/* Highlight row */
|
||||
:root.dark .gitemhighlight td {
|
||||
background-color: var(--highlight-color);
|
||||
color: var(--nav-link-color);
|
||||
background-color: var(--highlight-color);
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
|
||||
/* Differentiate Group, Milestone and Ordinary task items (applied to row) */
|
||||
:root.dark .ggroupitem {
|
||||
background-color: var(--bg-color);
|
||||
font-weight: bold;
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--bg-color);
|
||||
font-weight: bold;
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.dark .gmileitem,
|
||||
:root.dark .glineitem {
|
||||
background-color: var(--bg-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
/* Task bar caption text styles */
|
||||
:root.dark .gmilecaption,
|
||||
:root.dark .ggroupcaption,
|
||||
:root.dark .gcaption {
|
||||
color: var(--nav-link-color);
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
|
||||
/* Task complete %age bar */
|
||||
:root.dark .gtaskcomplete {
|
||||
background-color: var(--task-complete-bg-color);
|
||||
background-color: var(--task-complete-bg-color);
|
||||
}
|
||||
|
||||
/* Milestones */
|
||||
:root.dark .gmdtop,
|
||||
:root.dark .gmdbottom {
|
||||
border-bottom: 5px solid var(--milestone-border-color);
|
||||
border-bottom: 5px solid var(--milestone-border-color);
|
||||
}
|
||||
|
||||
:root.dark .gfoldercollapse {
|
||||
color: var(--secondary-text-color);
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: var(--folder-collapse-font-size);
|
||||
font-family: var(--folder-collapse-font-family);
|
||||
color: var(--secondary-text-color);
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: var(--folder-collapse-font-size);
|
||||
font-family: var(--folder-collapse-font-family);
|
||||
}
|
||||
|
||||
/* Highlight for collapsible row */
|
||||
:root.dark .gname.ggroupitem {
|
||||
background-color: var(--group-item-bg-color);
|
||||
background-color: var(--group-item-bg-color);
|
||||
}
|
||||
|
||||
/* Form label and selected highlighting */
|
||||
:root.dark .gformlabel {
|
||||
background-color: var(--formlabel-bg-color);
|
||||
color: var(--secondary-text-color);
|
||||
border: var(--formlabel-border-color) 1px solid;
|
||||
background-color: var(--formlabel-bg-color);
|
||||
color: var(--secondary-text-color);
|
||||
border: var(--formlabel-border-color) 1px solid;
|
||||
}
|
||||
|
||||
:root.dark span.gformlabel:hover {
|
||||
background-color: var(--hover-bg-color);
|
||||
border-color: var(--border-color);
|
||||
background-color: var(--hover-bg-color);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.dark span.gselected {
|
||||
background-color: var(--formlabel-selected-bg-color);
|
||||
border-color: var(--task-complete-bg-color);
|
||||
color: var(--nav-link-color);
|
||||
background-color: var(--formlabel-selected-bg-color);
|
||||
border-color: var(--task-complete-bg-color);
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
|
||||
:root.dark .gantt-inputtable {
|
||||
background-color: var(--input-bg-color);
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--input-border-color);
|
||||
color: var(--secondary-text-color);
|
||||
background-color: var(--input-bg-color);
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--input-border-color);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
/* ------------------- for blender generated theme ------------------- */
|
||||
|
||||
|
||||
:root.blender div.gantt,
|
||||
:root.blender .gantt table,
|
||||
:root.blender .gantt td {
|
||||
color: var(--blender-text);
|
||||
border-color: var(--blender-tab-outline);
|
||||
color: var(--blender-text);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gchartgrid,
|
||||
@@ -443,11 +320,10 @@ button:hover {
|
||||
:root.blender .gchartlbl.gcontainercol,
|
||||
:root.blender .gminorheading,
|
||||
:root.blender .gtaskcell {
|
||||
background-color: var(--blender-odd-row);
|
||||
border-color: var(--blender-tab-outline);
|
||||
background-color: var(--blender-odd-row);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
|
||||
/* Headings and cell defaults */
|
||||
:root.blender .gtaskheading,
|
||||
:root.blender .gchartlbl.gcontainercol .gmajorheading,
|
||||
@@ -460,13 +336,13 @@ button:hover {
|
||||
:root.blender .gchartlbl.gcontainercol .ggroupitem,
|
||||
:root.blender .glistlbl.gcontainercol .gtaskname,
|
||||
:root.blender .glistlbl.gcontainercol .gtasklist {
|
||||
background-color: var(--blender-panel-header);
|
||||
border-color: var(--blender-tab-outline);
|
||||
background-color: var(--blender-panel-header);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gtaskcellcurrent {
|
||||
background-color: var(--blender-odd-row);
|
||||
border-color: var(--blender-tab-outline);
|
||||
background-color: var(--blender-odd-row);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gtaskheading,
|
||||
@@ -482,103 +358,102 @@ button:hover {
|
||||
:root.blender .gchartlbl,
|
||||
:root.blender .gcontainercol,
|
||||
:root.blender .genddate {
|
||||
color: var(--blender-text);
|
||||
border-color: var(--blender-tab-outline);
|
||||
color: var(--blender-text);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gtaskname>div,
|
||||
:root.blender .gtaskname > div,
|
||||
:root.blender .gtaskname div,
|
||||
:root.blender .gtaskheading div,
|
||||
:root.blender .gtaskname span {
|
||||
color: var(--blender-text);
|
||||
color: var(--blender-text);
|
||||
}
|
||||
|
||||
:root.blender .gantt-chart tr:not(.gname.glineitem):not(.gname.ggroupitem) {
|
||||
background-color: var(--blender-odd-row);
|
||||
background-color: var(--blender-odd-row);
|
||||
}
|
||||
|
||||
:root.blender .gtasklist,
|
||||
:root.blender .gadditional {
|
||||
border: var(--blender-tab-outline) 1px solid;
|
||||
border: var(--blender-tab-outline) 1px solid;
|
||||
}
|
||||
|
||||
:root.blender .glistgrid,
|
||||
:root.blender .glistlbl {
|
||||
/* This is a border that needs background color, somehow. */
|
||||
background-color: var(--blender-tab-outline);
|
||||
border-color: var(--blender-tab-outline);
|
||||
/* This is a border that needs background color, somehow. */
|
||||
background-color: var(--blender-tab-outline);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
|
||||
/* Highlight row */
|
||||
:root.blender .gitemhighlight td,
|
||||
:root.blender .gitemhighlight .gantt-inputtable,
|
||||
:root.blender .gitemhighlight .gcaption,
|
||||
:root.blender .gitemhighlight .ggroupcaption {
|
||||
background-color: var(--blender-active-highlight) !important;
|
||||
color: var(--blender-active-text-highlight) !important;
|
||||
background-color: var(--blender-active-highlight) !important;
|
||||
color: var(--blender-active-text-highlight) !important;
|
||||
}
|
||||
|
||||
/* Differentiate Group, Milestone and Ordinary task items (applied to row) */
|
||||
:root.blender .ggroupitem {
|
||||
font-weight: bold;
|
||||
border-color: var(--border-color);
|
||||
font-weight: bold;
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
|
||||
:root.blender .gmileitem,
|
||||
:root.blender .glineitem {
|
||||
background-color: var(--blender-odd-row);
|
||||
background-color: var(--blender-odd-row);
|
||||
}
|
||||
|
||||
/* Task bar caption text styles */
|
||||
:root.blender .gmilecaption,
|
||||
:root.blender .ggroupcaption,
|
||||
:root.blender .gcaption {
|
||||
color: var(--blender-text);
|
||||
color: var(--blender-text);
|
||||
}
|
||||
|
||||
/* Milestones */
|
||||
:root.blender .gmdtop,
|
||||
:root.blender .gmdbottom {
|
||||
border-bottom: 5px solid var(--blender-tab-outline);
|
||||
border-bottom: 5px solid var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gfoldercollapse {
|
||||
color: var(--blender-text);
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: var(--folder-collapse-font-size);
|
||||
font-family: var(--folder-collapse-font-family);
|
||||
color: var(--blender-text);
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: var(--folder-collapse-font-size);
|
||||
font-family: var(--folder-collapse-font-family);
|
||||
}
|
||||
|
||||
/* Highlight for collapsible row */
|
||||
:root.blender .gname.ggroupitem {
|
||||
background-color: var(--blender-panel-background);
|
||||
background-color: var(--blender-panel-background);
|
||||
}
|
||||
|
||||
/* Form label and selected highlighting */
|
||||
:root.blender .gformlabel {
|
||||
background-color: var(--blender-panel-header);
|
||||
color: var(--blender-text);
|
||||
border: var(--blender-tab-outline) 1px solid;
|
||||
background-color: var(--blender-panel-header);
|
||||
color: var(--blender-text);
|
||||
border: var(--blender-tab-outline) 1px solid;
|
||||
}
|
||||
|
||||
:root.blender span.gformlabel:hover,
|
||||
:root.blender span.gselected {
|
||||
background-color: var(--blender-active-highlight);
|
||||
color: var(--blender-active-text-highlight);
|
||||
border-color: var(--blender-tab-outline);
|
||||
background-color: var(--blender-active-highlight);
|
||||
color: var(--blender-active-text-highlight);
|
||||
border-color: var(--blender-tab-outline);
|
||||
}
|
||||
|
||||
:root.blender .gantt-inputtable {
|
||||
background-color: var(--blender-panel-header);
|
||||
box-sizing: border-box;
|
||||
border: 2px solid var(--blender-button-border);
|
||||
color: var(--blender-text);
|
||||
background-color: var(--blender-panel-header);
|
||||
box-sizing: border-box;
|
||||
border: 2px solid var(--blender-button-border);
|
||||
color: var(--blender-text);
|
||||
}
|
||||
|
||||
/* Dark mode scrollbar */
|
||||
:root.blender .frame::-webkit-scrollbar-thumb,
|
||||
:root.blender .frame::-webkit-scrollbar-track {
|
||||
background-color: var(--blender-window-background);
|
||||
}
|
||||
background-color: var(--blender-window-background);
|
||||
}
|
||||
|
||||
@@ -1,214 +1,239 @@
|
||||
:root {
|
||||
--font-family: Arial, sans-serif;
|
||||
--base-font-size: 16px;
|
||||
--margin-tiny: 0.125rem;
|
||||
--margin-small: 0.625rem;
|
||||
--margin-medium: 1.25rem;
|
||||
--margin-large: 2.5rem;
|
||||
--padding-tiny: 0.125rem;
|
||||
--padding-small: 0.625rem;
|
||||
--padding-medium: 1rem;
|
||||
--font-size-large: 1.2rem;
|
||||
--logo-height: 1.5rem;
|
||||
--nav-height: 0.625rem;
|
||||
--border-radius: 0.3rem;
|
||||
--font-family: Arial, sans-serif;
|
||||
--base-font-size: 16px;
|
||||
--margin-tiny: 0.125rem;
|
||||
--margin-small: 0.625rem;
|
||||
--margin-medium: 1.25rem;
|
||||
--margin-large: 2.5rem;
|
||||
--padding-tiny: 0.125rem;
|
||||
--padding-small: 0.625rem;
|
||||
--padding-medium: 1rem;
|
||||
--font-size-small: 1rem;
|
||||
--font-size-large: 1.2rem;
|
||||
--logo-height: 1.5rem;
|
||||
--nav-height: 0.625rem;
|
||||
--border-radius: 0.3rem;
|
||||
--folder-collapse-font-size: 0.75rem;
|
||||
--folder-collapse-font-family: Courier, "Courier New", monospace;
|
||||
--box-shadow: 0 0 0.7rem #5f5f5f66;
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
color-scheme: dark;
|
||||
--bg-color: #252525;
|
||||
--text-color: #e0e0e0;
|
||||
--nav-bg-color: #121212;
|
||||
--nav-border-color: #25682a;
|
||||
--nav-link-color: #fff;
|
||||
--nav-link-hover-color: #3fb449;
|
||||
--warning-color: #FFDB8F;
|
||||
--border-color: #464444;
|
||||
color-scheme: dark;
|
||||
--bg-color: #252525;
|
||||
--primary-text-color: #e0e0e0;
|
||||
--secondary-text-color: #c7c7c7;
|
||||
--nav-bg-color: #121212;
|
||||
--nav-border-color: #25682a;
|
||||
--nav-link-color: #fff;
|
||||
--nav-link-hover-color: #3fb449;
|
||||
--warning-color: #ffdb8f;
|
||||
--border-color: #464444;
|
||||
--hover-bg-color: #3a3a3a;
|
||||
--highlight-color: #009136;
|
||||
--task-complete-bg-color: #777777;
|
||||
--milestone-border-color: #ffffff;
|
||||
--group-item-bg-color: #4b4b4b;
|
||||
--input-bg-color: #3b3b3b;
|
||||
--input-border-color: #000;
|
||||
--border-color: #464444;
|
||||
}
|
||||
|
||||
:root.light {
|
||||
color-scheme: light;
|
||||
--bg-color: #ffffff;
|
||||
--text-color: #000000;
|
||||
--nav-bg-color: #f8f8f8;
|
||||
--nav-border-color: #cccccc;
|
||||
--nav-link-color: #000000;
|
||||
--nav-link-hover-color: #38a63d;
|
||||
--warning-color: #FF4500;
|
||||
--border-color: #222;
|
||||
color-scheme: light;
|
||||
--bg-color: #ffffff;
|
||||
--primary-text-color: #000000;
|
||||
--nav-bg-color: #f8f8f8;
|
||||
--nav-border-color: #cccccc;
|
||||
--nav-link-color: #000000;
|
||||
--nav-link-hover-color: #38a63d;
|
||||
--warning-color: #ff4500;
|
||||
--border-color: #222;
|
||||
}
|
||||
|
||||
*:not(.tabulator-cell) {
|
||||
border-radius: var(--border-radius) !important;
|
||||
*:not(td, tr, td, .gmain) {
|
||||
border-radius: var(--border-radius) !important;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: var(--base-font-size);
|
||||
font-size: var(--base-font-size);
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--blender-window-background, var(--bg-color));
|
||||
color: var(--blender-text, var(--text-color));
|
||||
margin: 0;
|
||||
font-family: var(--font-family);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
background-color: var(--blender-window-background, var(--bg-color));
|
||||
color: var(--blender-text, var(--primary-text-color));
|
||||
margin: 0;
|
||||
font-family: var(--font-family);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#container {
|
||||
position: relative;
|
||||
padding: var(--margin-small);
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
padding: var(--margin-small);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
height: var(--nav-height);
|
||||
padding: var(--padding-medium) 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-bottom: 2px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
height: var(--nav-height);
|
||||
padding: var(--padding-medium) 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-bottom: 2px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
}
|
||||
|
||||
nav .logo {
|
||||
margin-left: var(--margin-large);
|
||||
height: var(--logo-height);
|
||||
margin-left: var(--margin-large);
|
||||
height: var(--logo-height);
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
margin-right: var(--margin-large);
|
||||
margin-right: var(--margin-large);
|
||||
}
|
||||
|
||||
nav ul li a {
|
||||
text-decoration: none;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
text-decoration: none;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
}
|
||||
|
||||
nav ul li a:hover,
|
||||
nav ul li a.active {
|
||||
color: var(--blender-selected-object, var(--nav-link-hover-color));
|
||||
color: var(--blender-selected-object, var(--nav-link-hover-color));
|
||||
}
|
||||
|
||||
.warning,
|
||||
.warning-icon {
|
||||
color: var(--blender-info-warning, var(--warning-color));
|
||||
}
|
||||
|
||||
#toggle-theme {
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-large);
|
||||
margin-right: var(--margin-medium);
|
||||
color: var(--blender-info-warning, var(--warning-color));
|
||||
}
|
||||
|
||||
#toggle-theme:focus {
|
||||
outline: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#client-list {
|
||||
position: absolute;
|
||||
top: calc(0 + var(--nav-height));
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: calc(0 + var(--nav-height));
|
||||
overflow-y: auto;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
||||
border: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#client-list.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
#connected-list-div {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.client {
|
||||
padding: var(--margin-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
cursor: pointer;
|
||||
padding: var(--margin-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.client-details {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding-left: var(--padding-small);
|
||||
transition: max-height 0.2s ease-out, padding 0.2s ease-out, opacity 0.1s ease-out;
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
margin-top: var(--margin-tiny);
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding-left: var(--padding-small);
|
||||
transition: max-height 0.2s ease-out, padding 0.2s ease-out,
|
||||
opacity 0.1s ease-out;
|
||||
background-color: var(--blender-panel-background, var(--nav-bg-color));
|
||||
margin-top: var(--margin-tiny);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.client-details.show {
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.client-detail {
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
padding: var(--padding-small);
|
||||
border-bottom: 1px solid var(--blender-tab-outline, var(--border-color));
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
#show-connected-button {
|
||||
width: auto;
|
||||
background-color: var(--blender-panel-header, var(--bg-color));
|
||||
font-size: var(--base-font-size);
|
||||
color: var(--blender-text, var(--text-color))
|
||||
width: auto;
|
||||
background-color: var(--blender-panel-header, var(--bg-color));
|
||||
font-size: var(--base-font-size);
|
||||
color: var(--blender-text, var(--text-color));
|
||||
}
|
||||
|
||||
#show-connected-button:hover,
|
||||
.scroll-button:hover {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.scroll-button {
|
||||
font-size: var(--base-font-size);
|
||||
margin-left: var(--margin-tiny);
|
||||
margin-top: var(--margin-small);
|
||||
font-size: var(--base-font-size);
|
||||
margin-left: var(--margin-tiny);
|
||||
margin-top: var(--margin-small);
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
text-align: right;
|
||||
padding: var(--padding-tiny);
|
||||
border-top: 1px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
background-color: var(--blender-top-bar-header, var(--nav-bg-color));
|
||||
text-align: right;
|
||||
padding: var(--padding-tiny);
|
||||
border-top: 1px solid var(--blender-tab-outline, var(--nav-border-color));
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
margin-right: var(--margin-small);
|
||||
font-size: 0.8rem;
|
||||
margin: 0;
|
||||
color: var(--blender-text, var(--nav-link-color));
|
||||
margin-right: var(--margin-small);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
background-color: var(--blender-button-background, var(--bg-color));
|
||||
color: var(--blender-button-text, var(--text-color));
|
||||
border-color: var(--blender-button-border, var(--border-color));
|
||||
transition: filter 0.2s ease;
|
||||
background-color: var(--blender-button-background, var(--bg-color));
|
||||
color: var(--blender-button-text, var(--text-color));
|
||||
border-color: var(--blender-button-border, var(--border-color));
|
||||
transition: filter 0.2s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.row-container {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.column-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-right: var(--margin-small);
|
||||
margin-bottom: var(--margin-small);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { CostUI } from './utilities/costui.js';
|
||||
import { CostUI } from "./utilities/costui.js";
|
||||
|
||||
const connectedClients = {};
|
||||
let socket;
|
||||
|
||||
let isScheduleLoad = {};
|
||||
|
||||
$(document).ready(function () {
|
||||
var defaultTheme = "blender";
|
||||
var theme = localStorage.getItem("theme") || defaultTheme;
|
||||
@@ -21,12 +23,28 @@ function connectSocket() {
|
||||
socket.on("connected_clients", handleConnectedClients);
|
||||
socket.on("theme_data", handleThemeData);
|
||||
socket.on("connect", handleWebConnect);
|
||||
socket.on("predefined_types", handlePredefinedTypes);
|
||||
socket.on("cost_schedules", handleCostSchedulesData);
|
||||
socket.on("cost_items", handleCostItemsData);
|
||||
socket.on("cost_values", handleCostValuesData);
|
||||
socket.on("cost_value", handleCostValueData);
|
||||
}
|
||||
|
||||
function handlePredefinedTypes(data) {
|
||||
CostUI.enableAddingCostSchedule(
|
||||
data.data["predefined_types"],
|
||||
addCostSchedule
|
||||
);
|
||||
}
|
||||
|
||||
function addCostSchedule(name, predefinedType) {
|
||||
executeOperator({
|
||||
type: "addCostSchedule",
|
||||
name: name,
|
||||
predefinedType: predefinedType,
|
||||
});
|
||||
}
|
||||
|
||||
function handleBlenderConnect(blenderId) {
|
||||
if (!connectedClients.hasOwnProperty(blenderId)) {
|
||||
connectedClients[blenderId] = { shown: false, ifc_file: "" };
|
||||
@@ -35,7 +53,6 @@ function handleBlenderConnect(blenderId) {
|
||||
$("#blender-count").text(function (i, text) {
|
||||
return parseInt(text, 10) + 1;
|
||||
});
|
||||
console.log("Blender connected", blenderId);
|
||||
}
|
||||
|
||||
function handleBlenderDisconnect(blenderId) {
|
||||
@@ -53,24 +70,24 @@ function removeTableElement(blenderId) {
|
||||
$("#cost-items-" + blenderId).remove();
|
||||
}
|
||||
|
||||
|
||||
const costValueCallbacks = {
|
||||
'editCostValues': editCostValues,
|
||||
'addCostValue': addCostValue,
|
||||
'deleteCostValue': deleteCostValue,
|
||||
editCostValues: editCostValues,
|
||||
addCostValue: addCostValue,
|
||||
deleteCostValue: deleteCostValue,
|
||||
};
|
||||
|
||||
function handleCostValueData(data) {
|
||||
|
||||
const costItemId = data.data["cost_value"]["cost_item_id"];
|
||||
const costValueId = data.data["cost_value"]["cost_value_id"];
|
||||
console.log("Handling cost value data", costItemId, costValueId);
|
||||
CostUI.addNewCostValueRow(costItemId, costValueId, costValueCallbacks);
|
||||
|
||||
}
|
||||
|
||||
function deleteCostValue(costItemId, costValueId) {
|
||||
executeOperator({ type: "deleteCostValue", costItemId: costItemId, costValueId: costValueId });
|
||||
executeOperator({
|
||||
type: "deleteCostValue",
|
||||
costItemId: costItemId,
|
||||
costValueId: costValueId,
|
||||
});
|
||||
}
|
||||
|
||||
function handleConnectedClients(data) {
|
||||
@@ -86,14 +103,13 @@ function handleCostValuesData(data) {
|
||||
costValues: data.data["cost_values"]["cost_values"],
|
||||
costItemId: data.data["cost_values"]["cost_item_id"],
|
||||
callbacks: {
|
||||
'editCostValues': editCostValues,
|
||||
'addCostValue': addCostValue,
|
||||
'deleteCostValue': deleteCostValue,
|
||||
editCostValues: editCostValues,
|
||||
addCostValue: addCostValue,
|
||||
deleteCostValue: deleteCostValue,
|
||||
},
|
||||
});
|
||||
|
||||
CostUI.highlightCostItem(data.data["cost_values"]["cost_item_id"]);
|
||||
|
||||
}
|
||||
|
||||
function addCostValue(costItemId) {
|
||||
@@ -101,10 +117,10 @@ function addCostValue(costItemId) {
|
||||
}
|
||||
|
||||
function editCostValues(costItemId, costValues) {
|
||||
executeOperator({
|
||||
type: "editCostValues",
|
||||
costItemId: costItemId,
|
||||
costValues: costValues
|
||||
executeOperator({
|
||||
type: "editCostValues",
|
||||
costItemId: costItemId,
|
||||
costValues: costValues,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -159,7 +175,11 @@ function addCostItem(costItemId) {
|
||||
}
|
||||
|
||||
function editCostItemName(costItemId, name) {
|
||||
executeOperator({ type: "editCostItemName", costItemId: costItemId, name: name });
|
||||
executeOperator({
|
||||
type: "editCostItemName",
|
||||
costItemId: costItemId,
|
||||
name: name,
|
||||
});
|
||||
}
|
||||
|
||||
function selectAssignedElements(costItemId) {
|
||||
@@ -167,44 +187,52 @@ function selectAssignedElements(costItemId) {
|
||||
}
|
||||
|
||||
function handleWebConnect() {
|
||||
executeOperator({ type: "getPredefinedTypes" });
|
||||
getCostSchedules();
|
||||
}
|
||||
|
||||
function addSummaryCostItem(costScheduleId) {
|
||||
executeOperator({
|
||||
type: "addSummaryCostItem",
|
||||
costScheduleId: costScheduleId,
|
||||
});
|
||||
}
|
||||
|
||||
function handleCostSchedulesData(data) {
|
||||
const blenderId = data.blenderId;
|
||||
const costSchedules = data.data["cost_schedules"]["cost_schedules"];
|
||||
const currency = data.data["cost_schedules"]["currency"]["name"];
|
||||
const costScheduleDiv = $("#cost-schedules");
|
||||
if (costSchedules.length === 0) {
|
||||
return;
|
||||
}
|
||||
const currency = data.data["cost_schedules"]["currency"]
|
||||
? data.data["cost_schedules"]["currency"]["name"]
|
||||
: "Undefined";
|
||||
const costScheduleDiv = document.getElementById("cost-schedules");
|
||||
costScheduleDiv.innerHTML = "";
|
||||
costSchedules.forEach((costSchedule) => {
|
||||
costSchedule.UpdateDate = new Date(costSchedule.UpdateDate);
|
||||
const mainContainer = CostUI.text("Updated On: " + costSchedule.UpdateDate);
|
||||
const callback = () => loadCostSchedule(costSchedule.id, blenderId);
|
||||
|
||||
|
||||
const card = CostUI.createCard(costSchedule.Name, mainContainer, callback);
|
||||
costScheduleDiv.append(card);
|
||||
});
|
||||
|
||||
const firstCostSchedule = costSchedules[0];
|
||||
if (firstCostSchedule) {
|
||||
loadCostSchedule(firstCostSchedule.id, blenderId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function handleCostItemsData(data) {
|
||||
console.log("Handling cost items data", data);
|
||||
CostUI.createCostSchedule({
|
||||
data: data.data["cost_items"],
|
||||
data: data.data["cost_items"]["cost_items"],
|
||||
costScheduleId: data.data["cost_items"]["cost_schedule_id"],
|
||||
blenderID: data.blenderId,
|
||||
callbacks: {
|
||||
"addCostItem": addCostItem,
|
||||
"deleteCostItem": deleteCostItem,
|
||||
"duplicateCostItem": duplicateCostItem,
|
||||
"selectAssignedElements": selectAssignedElements,
|
||||
'editCostItemName': editCostItemName,
|
||||
'enableEditingCostValues': enableEditingCostValues,
|
||||
}
|
||||
addCostItem: addCostItem,
|
||||
deleteCostItem: deleteCostItem,
|
||||
duplicateCostItem: duplicateCostItem,
|
||||
selectAssignedElements: selectAssignedElements,
|
||||
editCostItemName: editCostItemName,
|
||||
enableEditingCostValues: enableEditingCostValues,
|
||||
addSummaryCostItem: addSummaryCostItem,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -224,7 +252,10 @@ function executeOperator(operator, blenderId) {
|
||||
}
|
||||
|
||||
function loadCostSchedule(costScheduleId, blenderId) {
|
||||
executeOperator({ type: "loadCostSchedule", costScheduleId: costScheduleId }, blenderId);
|
||||
executeOperator(
|
||||
{ type: "loadCostSchedule", costScheduleId: costScheduleId },
|
||||
blenderId
|
||||
);
|
||||
}
|
||||
|
||||
function getCostSchedules(blenderId) {
|
||||
@@ -232,5 +263,5 @@ function getCostSchedules(blenderId) {
|
||||
}
|
||||
|
||||
function enableEditingCostValues(costItemId) {
|
||||
executeOperator({ type: "enableEditingCostValues", costItemId: costItemId});
|
||||
executeOperator({ type: "enableEditingCostValues", costItemId: costItemId });
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -84,8 +84,14 @@
|
||||
</button>
|
||||
<div id="client-list"></div>
|
||||
</div>
|
||||
<div id="cost-schedules"></div>
|
||||
<div id="UI"></div>
|
||||
<h1>Costing</h1>
|
||||
<div id="" >
|
||||
<li id="add-cost-schedule" class="action-button fas fa-plus"> </li>
|
||||
Add New Schedule
|
||||
</div>
|
||||
|
||||
<div id="cost-schedules" class="row-container"></div>
|
||||
<div id="UI" class="row-container"></div>
|
||||
<div id="cost-items"></div>
|
||||
|
||||
<footer>
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
</button>
|
||||
<div id="client-list" class="no-print"></div>
|
||||
</div>
|
||||
<div id="work_schedules"></div>
|
||||
<div id="container"></div>
|
||||
<div id="work_schedules" class="row-container"></div>
|
||||
<div id="container" ></div>
|
||||
<footer>
|
||||
<p>Bonsai Version: {{version}}</p>
|
||||
</footer>
|
||||
|
||||
@@ -279,19 +279,9 @@ class CostSchedulesData:
|
||||
|
||||
@classmethod
|
||||
def get_cost_schedule_types(cls):
|
||||
results = []
|
||||
declaration = tool.Ifc().schema().declaration_by_name("IfcCostSchedule")
|
||||
version = tool.Ifc.get_schema()
|
||||
for attribute in declaration.attributes():
|
||||
if attribute.name() == "PredefinedType":
|
||||
results.extend(
|
||||
[
|
||||
(e, e, get_predefined_type_doc(version, "IfcCostSchedule", e))
|
||||
for e in attribute.type_of_attribute().declared_type().enumeration_items()
|
||||
]
|
||||
)
|
||||
break
|
||||
return results
|
||||
types = ifcopenshell.util.cost.get_cost_schedule_types(tool.Ifc.get())
|
||||
return [(t['name'], t['name'], t['description']) for t in types]
|
||||
|
||||
|
||||
|
||||
class CostItemRatesData:
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ifcopenshell.util.cost
|
||||
import bpy
|
||||
from bonsai.bim.module.web.data import WebData
|
||||
import bonsai.core.tool
|
||||
@@ -341,9 +342,26 @@ class Web(bonsai.core.tool.Web):
|
||||
Args:
|
||||
operator_data (dict): A dictionary containing the operator data.
|
||||
"""
|
||||
print("Handling cost operator")
|
||||
ifc_file = tool.Ifc.get()
|
||||
if operator_data["type"] == "getPredefinedTypes":
|
||||
print('getting predefined types')
|
||||
predefined_types = ifcopenshell.util.cost.get_cost_schedule_types(ifc_file)
|
||||
cls.send_webui_data(data=predefined_types, data_key="predefined_types", event="predefined_types")
|
||||
if operator_data["type"] == "addCostSchedule":
|
||||
bonsai.core.cost.add_cost_schedule(
|
||||
tool.Ifc,
|
||||
name=operator_data["name"],
|
||||
predefined_type=operator_data["type"]
|
||||
)
|
||||
cost_schedules = ifc_file.by_type("IfcCostSchedule")
|
||||
cost_schedules_json = [cs.get_info(recursive=True) for cs in cost_schedules]
|
||||
currency = tool.Cost.currency()
|
||||
cls.send_webui_data(data={
|
||||
"cost_schedules": cost_schedules_json,
|
||||
"currency": currency
|
||||
}, data_key="cost_schedules", event="cost_schedules")
|
||||
if operator_data["type"] == "getCostSchedules":
|
||||
print('getting cost schedules')
|
||||
cost_schedules = ifc_file.by_type("IfcCostSchedule")
|
||||
cost_schedules_json = [cs.get_info(recursive=True) for cs in cost_schedules]
|
||||
currency = tool.Cost.currency()
|
||||
@@ -353,13 +371,23 @@ class Web(bonsai.core.tool.Web):
|
||||
event="cost_schedules",
|
||||
)
|
||||
if operator_data["type"] == "loadCostSchedule":
|
||||
print('loading cost schedule')
|
||||
cost_schedule = ifc_file.by_id(operator_data["costScheduleId"])
|
||||
bonsai.core.cost.enable_editing_cost_items(tool.Cost, cost_schedule=cost_schedule)
|
||||
cls.load_cost_schedule_web_ui(cost_schedule)
|
||||
if operator_data["type"] == "selectAssignedElements":
|
||||
print('selecting assigned elements')
|
||||
cost_item = tool.Ifc.get().by_id(operator_data["costItemId"])
|
||||
products = tool.Cost.get_cost_item_products(cost_item, is_deep=True)
|
||||
tool.Spatial.select_products(products, unhide=True)
|
||||
if operator_data["type"] == "addSummaryCostItem":
|
||||
cost_schedule=ifc_file.by_id(operator_data["costScheduleId"])
|
||||
bonsai.core.cost.add_summary_cost_item(
|
||||
tool.Ifc,
|
||||
tool.Cost,
|
||||
cost_schedule=cost_schedule
|
||||
)
|
||||
cls.load_cost_schedule_web_ui(cost_schedule)
|
||||
if operator_data["type"] == "addCostItem":
|
||||
bpy.ops.bim.add_cost_item(cost_item=operator_data["costItemId"])
|
||||
cost_schedule = tool.Cost.get_cost_schedule(cost_item=tool.Ifc.get().by_id(operator_data["costItemId"]))
|
||||
@@ -424,7 +452,10 @@ class Web(bonsai.core.tool.Web):
|
||||
@classmethod
|
||||
def load_cost_schedule_web_ui(cls, cost_schedule):
|
||||
json_data = tool.Cost.create_cost_schedule_json(cost_schedule)
|
||||
cls.send_webui_data(data=json_data, data_key="cost_items", event="cost_items")
|
||||
cls.send_webui_data(data={
|
||||
"cost_items": json_data,
|
||||
"cost_schedule_id": cost_schedule.id()
|
||||
}, data_key="cost_items", event="cost_items")
|
||||
|
||||
@classmethod
|
||||
def handle_gantt_operator(cls, operator_data: dict) -> None:
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
import lark
|
||||
import ifcopenshell
|
||||
from typing import Optional, Union, Literal, Generator, Any
|
||||
|
||||
import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper
|
||||
from ifcopenshell.util.doc import get_predefined_type_doc
|
||||
|
||||
arithmetic_operator_symbols = {"ADD": "+", "DIVIDE": "/", "MULTIPLY": "*", "SUBTRACT": "-"}
|
||||
symbol_arithmetic_operators = {"+": "ADD", "/": "DIVIDE", "*": "MULTIPLY", "-": "SUBTRACT"}
|
||||
@@ -265,6 +266,20 @@ def get_cost_values(cost_item: ifcopenshell.entity_instance) -> list[dict[str, s
|
||||
print(results)
|
||||
return results
|
||||
|
||||
def get_cost_schedule_types(file):
|
||||
schema: ifcopenshell_wrapper.schema_definition = ifcopenshell_wrapper.schema_by_name(file.schema)
|
||||
results = []
|
||||
declaration = schema.declaration_by_name("IfcCostSchedule")
|
||||
version = file.schema_identifier
|
||||
for attribute in declaration.attributes():
|
||||
if attribute.name() == "PredefinedType":
|
||||
for enumeration in attribute.type_of_attribute().declared_type().enumeration_items():
|
||||
results.append({
|
||||
"name": enumeration,
|
||||
'description': get_predefined_type_doc(version, "IfcCostSchedule",enumeration),
|
||||
})
|
||||
break
|
||||
return results
|
||||
|
||||
class CostValueUnserialiser:
|
||||
def parse(self, formula: str):
|
||||
|
||||
Reference in New Issue
Block a user