diff --git a/src/blenderbim/blenderbim/bim/data/gantt/index.mustache b/src/blenderbim/blenderbim/bim/data/gantt/index.mustache index a368889cc2..6ee49cefde 100644 --- a/src/blenderbim/blenderbim/bim/data/gantt/index.mustache +++ b/src/blenderbim/blenderbim/bim/data/gantt/index.mustache @@ -6,7 +6,7 @@ var json_data = `{{{json_data}}}`; -
+

Choose a language: -

- +

+
+ -
+
+
\ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/sequence/gantt/index.js b/src/blenderbim/blenderbim/bim/module/sequence/gantt/index.js index 05096293da..ab03471d2d 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/gantt/index.js +++ b/src/blenderbim/blenderbim/bim/module/sequence/gantt/index.js @@ -23,6 +23,7 @@ function create_gantt_chart(json_data) { JSGantt.parseJSONString(json_data, g); g.Draw(); } + function set_language(e){ lang = e && e.target ? e.target.value : "en"; g.setOptions({ @@ -31,7 +32,27 @@ function set_language(e){ g.Draw(); } -function setupPage(name){ + +function draw_table(json_object){ + let table = document.createElement("table"); + table.classList.add("table-description"); + for (let key in json_object){ + let row = document.createElement("tr"); + let key_cell = document.createElement("td"); + let key_text = document.createTextNode(key); + key_cell.appendChild(key_text); + row.appendChild(key_cell); + let value_cell = document.createElement("td"); + let value_text = document.createTextNode(json_object[key]); + value_cell.appendChild(value_text); + row.appendChild(value_cell); + table.appendChild(row); + } + return table; +} + +function setupPage(workScheduleData){ + workScheduleData = JSON.parse(workScheduleData); let print_button = document.createElement("button"); print_button.id = "print-schedule"; print_button.innerHTML = "Print"; @@ -40,18 +61,37 @@ function setupPage(name){ g.Draw(); var values = document.getElementById("print_page_size").value.split(",") let css = - "@media print {\n @page {\n size: " + values[0] + "mm " + values[1] + "mm;\n }\n /* set gantt container to the same width as the page */\n .gantt {\n width: " + values[0] + "mm;\n }\n };"; + "@media print {\n @page {\n size: " + values[0] + "mm " + values[1] + "mm;\n }\n"; g.printChart(values[0], values[1], css); g.setTotalHeight(900); g.Draw(); }); document.getElementById("print_options").appendChild(print_button); - // add a nice layout to show the schedule name - let schedule_name = document.createElement("h1"); - // create string to say "Schedule: " - let schedule_name_string = document.createTextNode("Schedule: " + name); - // add the string to the h1 element + let table = draw_table(workScheduleData) + document.getElementById("schedule-data").appendChild(table); + table.style.display = "none"; + let toggle_button = document.createElement("button"); + toggle_button.id = "toggle-table"; + toggle_button.innerHTML = "Show Schedule Information"; + toggle_button.onclick = function(){ + if (table.style.display === "none"){ + table.style.display = "table"; + toggle_button.innerHTML = "Hide Schedule Information"; + } else { + toggle_button.innerHTML = "Show Schedule Information"; + table.style.display = "none"; + } + } + document.getElementById("options").appendChild(toggle_button); + + let schedule_name = document.createElement("h2"); + let schedule_name_string = document.createTextNode("Schedule: " + workScheduleData.Name); schedule_name.appendChild(schedule_name_string); - document.getElementById("schedule-data").appendChild(schedule_name); + document.getElementById("schedule-header").appendChild(schedule_name); + + let creation_date = document.createElement("h2"); + let creation_date_string = document.createTextNode("Created: " + new Date(workScheduleData.CreationDate).toLocaleDateString()); + creation_date.appendChild(creation_date_string); + document.getElementById("schedule-header").appendChild(creation_date); } \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/sequence/gantt/main.css b/src/blenderbim/blenderbim/bim/module/sequence/gantt/main.css index cb76c9c069..857565f492 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/gantt/main.css +++ b/src/blenderbim/blenderbim/bim/module/sequence/gantt/main.css @@ -24,11 +24,6 @@ background: #D4B483; } -.gmainleft { - overflow: visible; - flex: 0 1 auto; -} - .gname.ggroupitem { background-color: #4c92ec; font-weight: bold; @@ -63,8 +58,7 @@ .gmainleft { resize: horizontal; height:100%; - overflow-x: visible; - flex: 0 1 auto; + /* flex: 0 1 auto; */ } .gmainright { @@ -113,10 +107,66 @@ button, .sweet_button { box-shadow: 0 0 0.7rem rgba(95, 95, 95, 0.4); } +h1 { + font-size: 2rem; + font-weight: 500; + line-height: 1.25; + color: black; + margin: 0.5rem; +} +h2 { + font-size: 1.5rem; + font-weight: 500; + line-height: 1.25; + color: black; + margin: 0.5rem; +} + h4 { font-size: 1.2rem; font-weight: 500; line-height: 1.25; color: black; + margin: 0.5rem; } +.table-description { +/* create a github style table similar to a wild car */ + margin-bottom: 1rem; + width : 50%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; + border-color: grey; + border: 1px solid #e1e1e1; + border-radius: 0.25rem; + box-shadow: 0 0 0.7rem rgba(95, 95, 95, 0.4); + text-align: center; +} + +.table-description tr { + display: table-row; + vertical-align: inherit; + border-color: inherit; + border-bottom: 1px solid #e1e1e1; +} + +.table-description thead { + display: table-header-group; + vertical-align: middle; + border-color: inherit; + background-color: #95A5A6; +} + +.top-right { + position: absolute; + top: 8px; + right: 16px; +} + +#schedule-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} \ No newline at end of file diff --git a/src/blenderbim/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py index d238fd8bb2..63277d5f5d 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -485,10 +485,13 @@ class BIM_PT_work_schedules(Panel): baseline_row.label( text="{} @ {}".format(baseline["name"], baseline["date"]), icon="RESTRICT_INSTANCED_OFF" ) - baseline_row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = baseline["id"] + baseline_row.operator("bim.generate_gantt_chart", text="Compare", icon="NLA").work_schedule = baseline[ + "id" + ] baseline_row.operator( "bim.enable_editing_work_schedule_tasks", text="", icon="ACTION" ).work_schedule = baseline["id"] + baseline_row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = baseline["id"] def draw_readonly_work_schedule_ui(self, work_schedule_id): if self.props.active_work_schedule_id == work_schedule_id: @@ -515,6 +518,7 @@ class BIM_PT_work_schedules(Panel): "active_task_index", ) + class BIM_PT_task_icom(Panel): bl_label = "IFC Task ICOM" bl_idname = "BIM_PT_task_icom" diff --git a/src/blenderbim/blenderbim/core/sequence.py b/src/blenderbim/blenderbim/core/sequence.py index d400a6bedd..f27fbc71b2 100644 --- a/src/blenderbim/blenderbim/core/sequence.py +++ b/src/blenderbim/blenderbim/core/sequence.py @@ -543,7 +543,7 @@ def visualise_work_schedule_date(sequence, work_schedule=None): def generate_gantt_chart(sequence, work_schedule): json = sequence.create_tasks_json(work_schedule) - sequence.generate_gantt_browser_chart(json) + sequence.generate_gantt_browser_chart(json, work_schedule) def load_product_related_tasks(sequence, product=None): diff --git a/src/blenderbim/blenderbim/tool/sequence.py b/src/blenderbim/blenderbim/tool/sequence.py index 2e3e18eb08..c33b940ec4 100644 --- a/src/blenderbim/blenderbim/tool/sequence.py +++ b/src/blenderbim/blenderbim/tool/sequence.py @@ -1171,7 +1171,6 @@ class Sequence(blenderbim.core.tool.Sequence): @classmethod def show_snapshot(cls, product_states): - print(product_states) bpy.context.scene.frame_start = 1 bpy.context.scene.frame_end = 2 for obj in bpy.data.objects: @@ -1312,7 +1311,6 @@ class Sequence(blenderbim.core.tool.Sequence): def clear_object_animation(cls, obj): if obj.animation_data: obj.animation_data_clear() - print("Cleared animation for", obj.name) @classmethod def clear_objects_animation(cls, include_blender_objects=True): @@ -1475,32 +1473,60 @@ class Sequence(blenderbim.core.tool.Sequence): "USERDEFINED": "FS", "NOTDEFINED": "FS", } - + is_baseline = False + if work_schedule.PredefinedType == "BASELINE": + is_baseline = True tasks_json = [] for task in ifcopenshell.util.sequence.get_root_tasks(work_schedule): - cls.create_new_task_json(task, tasks_json, sequence_type_map) + cls.create_new_task_json(task, tasks_json, sequence_type_map, is_baseline=is_baseline) return tasks_json @classmethod - def create_new_task_json(cls, task, json, type_map=None): + def create_new_task_json(cls, task, json, type_map=None, is_baseline=False): task_time = task.TaskTime + resources = ifcopenshell.util.sequence.get_task_resources(task, is_deep=False) + + string_resources = "" + resources_usage = "" + for resource in resources: + string_resources += resource.Name + ", " + resources_usage += str(resource.Usage.ScheduleUsage) + ", " if resource.Usage else "-, " + + schedule_start = task_time.ScheduleStart if task_time else "" + schedule_finish = task_time.ScheduleFinish if task_time else "" + + declared_by_task = task.IsDeclaredBy[0].RelatingObject if is_baseline else None + if declared_by_task and declared_by_task.TaskTime: + compare_start = declared_by_task.TaskTime.ScheduleStart + compare_finish = declared_by_task.TaskTime.ScheduleFinish + else: + compare_start = schedule_start + compare_finish = schedule_finish + data = { "pID": task.id(), "pName": task.Name, "pCaption": task.Name, - "pStart": task_time.ScheduleStart if task_time else "", - "pEnd": task_time.ScheduleFinish if task_time else "", - "pPlanStart": task_time.ScheduleStart if task_time else "", - "pPlanEnd": task_time.ScheduleFinish if task_time else "", + "pStart": declared_by_task.TaskTime.ScheduleStart + if declared_by_task and declared_by_task.TaskTime + else schedule_start, + "pEnd": declared_by_task.TaskTime.ScheduleFinish + if declared_by_task and declared_by_task.TaskTime + else schedule_finish, + "pPlanStart": schedule_start, + "pPlanEnd": schedule_finish, "pMile": 1 if task.IsMilestone else 0, + "pRes": string_resources, "pComp": 0, "pGroup": 1 if task.IsNestedBy else 0, "pParent": task.Nests[0].RelatingObject.id() if task.Nests else 0, "pOpen": 1, "pCost": 1, - "ifcduration": str(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleDuration)) if (task_time and task_time.ScheduleDuration) else "", + "ifcduration": str(ifcopenshell.util.date.ifc2datetime(task_time.ScheduleDuration)) + if (task_time and task_time.ScheduleDuration) + else "", + "resourceUsage": resources_usage, } - if task_time and task_time.IsCritical: data["pClass"] = "gtaskred" elif data["pGroup"]: @@ -1515,14 +1541,17 @@ class Sequence(blenderbim.core.tool.Sequence): ) json.append(data) for nested_task in ifcopenshell.util.sequence.get_nested_tasks(task): - cls.create_new_task_json(nested_task, json, type_map) + cls.create_new_task_json(nested_task, json, type_map, is_baseline) @classmethod - def generate_gantt_browser_chart(cls, task_json): - active_work_schedule = cls.get_active_work_schedule() + def generate_gantt_browser_chart(cls, task_json, work_schedule): with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html"), "w") as f: with open(os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.mustache"), "r") as t: - f.write(pystache.render(t.read(), {"json_data": json.dumps(task_json), "name":active_work_schedule.Name or "Unnamed"})) + f.write( + pystache.render( + t.read(), {"json_data": json.dumps(task_json), "data": json.dumps(work_schedule.get_info())} + ) + ) webbrowser.open("file://" + os.path.join(bpy.context.scene.BIMProperties.data_dir, "gantt", "index.html")) @classmethod