Skip to content

Commit

Permalink
feat: add new height option auto (min-height)
Browse files Browse the repository at this point in the history
if rectangle is only ( basically no element is overlapping with it) or last element inside row or column, row and column layout is computed for children.
- if rectangle is overlapping with other element and we make it relative placement of other element will be broken so for now it is set to compute layout as per above condition

created patch that will convert isDynamicHeight Boolean to heightType with value "fixed" or "auto".

updated default objects and  control in Properties Panel.

changed schema version number to 1.2.0 as schema is changed and is incompatible with old formats (1.1.0)  we need to handle old formats.

updated jinja render template
- modified relative_containers to be recursive
- updated all templates to use heightType properties
- updated logic to include min-height
- added logic for backwards compatibility.
- also introduced dynamic height for static text if it has parseJinja enabled.
- updated rectangle template to be dynamic height

misc:
    is_older_schema now handles really old formats which don't have schema_version
    reverted styles for relative column
  • Loading branch information
maharshivpatel committed Apr 30, 2024
1 parent 36f8606 commit 8a4d958
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 54 deletions.
1 change: 1 addition & 0 deletions print_designer/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ print_designer.patches.introduce_dynamic_containers
print_designer.patches.introduce_dynamic_height
print_designer.patches.remove_unused_rectangle_gs_properties
execute:from print_designer.patches.create_custom_fields import custom_field_patch; custom_field_patch()
print_designer.patches.change_dynamic_height_variable
24 changes: 24 additions & 0 deletions print_designer/patches/change_dynamic_height_variable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import frappe

from print_designer.patches.patch_utils import patch_formats


def execute():
"""changing isDynamicHeight property to heightType property in text and table elements"""

def element_callback(el):
if el.get("type") == "text" and not (el.get("isDynamic") or el.get("parseJinja")):
return

if not "isDynamicHeight" in el:
el["isDynamicHeight"] = False

if el["isDynamicHeight"]:
el["heightType"] = "auto"
else:
el["heightType"] = "fixed"

patch_formats(
{"element": element_callback},
types=["text", "table"],
)
2 changes: 1 addition & 1 deletion print_designer/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def pdf_body_html(print_format, jenv, args, template):


def is_older_schema(settings, current_version):
format_version = settings.get("schema_version")
format_version = settings.get("schema_version", "1.0.0")
format_version = format_version.split(".")
current_version = current_version.split(".")
if int(format_version[0]) < int(current_version[0]):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% from 'print_designer/page/print_designer/jinja/macros/spantag.html' import span_tag with context %}

{% macro dynamictext(element, send_to_jinja, is_parent_dynamic_height) -%}
<div style="position:{%- if is_parent_dynamic_height -%}relative{% else %}absolute{%- endif -%}; {%- if not is_parent_dynamic_height -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px;{% if element.isFixedSize %}width:{{ element.width }}px; {%- if not is_parent_dynamic_height -%}height:{{ element.height }}px; {%- endif -%} {% else %} width:fit-content; height:fit-content; white-space:nowrap; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX) + 2 }}px;{%endif%}" class="
<div style="position:{%- if is_parent_dynamic_height != 'fixed' -%}relative{% else %}absolute{%- endif -%}; {%- if is_parent_dynamic_height == 'fixed' -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px;{% if element.isFixedSize %}width:{{ element.width }}px; {%- if is_parent_dynamic_height == 'fixed' -%}height:{{ element.height }}px; {%- endif -%} {% else %} width:fit-content; height:fit-content; white-space:nowrap; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX) + 2 }}px;{%endif%}" class="
{{ element.classes | join(' ') }}">
<div style="{% if element.isFixedSize %}width:{{ element.width }}px; {%- if not is_parent_dynamic_height -%}height:{{ element.height }}px; {%- endif -%}{% else %}width:fit-content; height:fit-content; white-space:nowrap; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX) + 2 }}px;{%endif%} {{convert_css(element.style)}}"
class="dynamicText {{ element.classes | join(' ') }}">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{% macro rectangle(element, render_element, send_to_jinja) -%}
<div id="{{ element.id }}" style="position:absolute; top:{{ element.startY }}px; left:{{ element.startX }}px; width:{{ element.width }}px; height:{{ element.height }}px; {{convert_css(element.style)}}"
{% macro rectangle(element, render_element, send_to_jinja, is_parent_dynamic_height) -%}
{%- set heightType = element.get("heightType") -%}
{%- if settings.get("schema_version") == "1.1.0" -%}
{%- set heightType = "auto" if element.get("isDynamicHeight", False) else "fixed" -%}
{%- endif -%}
<div id="{{ element.id }}" style="position:{%- if is_parent_dynamic_height != 'fixed' -%}relative{% else %}absolute{%- endif -%}; {%- if is_parent_dynamic_height == 'fixed' -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px; width:{{ element.width }}px; {%- if heightType != 'auto' -%} {%- if heightType == 'auto-min-height' -%}min-{%- endif -%}height:{{ element.height }}px; {%- endif -%} {{convert_css(element.style)}}"
class="rectangle {{ element.classes | join(' ') }}">
{% if element.childrens %}
{% for object in element.childrens %}
{{ render_element(object, send_to_jinja) }}
{{ render_element(object, send_to_jinja, is_parent_dynamic_height) }}
{% endfor %}
{% endif %}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
{% from 'print_designer/page/print_designer/jinja/macros/render_element.html' import render_element with context %}

{% macro relative_columns(element, send_to_jinja) -%}
<div style="position:relative; top: 0px; width:{{ element.width }}px; {%- if not element.isDynamicHeight -%} height:{{ element.height }}px; {%- endif -%} {{convert_css(element.style)}}"
{%- set heightType = element.get("heightType") -%}
{%- if settings.get("schema_version") == "1.1.0" -%}
{%- set heightType = "auto" if element.get("isDynamicHeight", False) else "fixed" -%}
{%- endif -%}
<div style="position:relative; top: 0px; {%- if element.rectangleContainer -%}margin-top:{{element.startY}}px; margin-left:{{element.startX}}px;{%- endif -%} width:{{ element.width }}px; {%- if heightType != 'auto' -%}{%- if heightType == 'auto-min-height' -%}min-{%- endif -%}height:{{ element.height }}px; {%- endif -%} {{convert_css(element.style)}}"
class="rectangle {{ element.classes | join(' ') }}">
{% if element.childrens %}
{% for object in element.childrens %}
{{ render_element(object, send_to_jinja, element.get("isDynamicHeight", false)) }}
{%- if object.layoutType == "row" -%}
{{ relative_containers(object, send_to_jinja) }}
{%- elif object.layoutType == "column" -%}
{{ relative_columns(object, send_to_jinja) }}
{%- else -%}
{{ render_element(object, send_to_jinja, heightType) }}
{%- endif -%}
{% endfor %}
{% endif %}
</div>
{%- endmacro %}

{% macro relative_containers(element, send_to_jinja) -%}
<div style="position:relative; left:{{ element.startX }}px; {%- if not element.isDynamicHeight -%} height:{{ element.height }}px; {%- endif -%} {{convert_css(element.style)}}"
{%- set heightType = element.get("heightType") -%}
{%- if settings.get("schema_version") == "1.1.0" -%}
{%- set heightType = "auto" if element.get("isDynamicHeight", False) else "fixed" -%}
{%- endif -%}
<div style="position:relative; left:{{ element.startX }}px; {%- if heightType != 'auto' -%}{%- if heightType == 'auto-min-height' -%}min-{%- endif -%}height:{{ element.height }}px; {%- endif -%} {{convert_css(element.style)}}"
class="rectangle relative-row {{ element.classes | join(' ') }}">
{% if element.childrens %}
{% for object in element.childrens %}
{{ relative_columns(object, send_to_jinja) }}
{%- if object.layoutType == "column" -%}
{{ relative_columns(object, send_to_jinja) }}
{%- elif object.layoutType == "row" -%}
{{ relative_containers(object, send_to_jinja) }}
{%- else -%}
{{ render_element(object, send_to_jinja, heightType) }}
{%- endif -%}
{% endfor %}
{% endif %}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
{% from 'print_designer/page/print_designer/jinja/macros/table.html' import table with context %}


{% macro render_element(element, send_to_jinja, is_parent_dynamic_height = false) -%}
{% macro render_element(element, send_to_jinja, is_parent_dynamic_height = 'fixed') -%}
{% if element.type == "rectangle" %}
{{ rectangle(element, render_element, send_to_jinja) }}
{{ rectangle(element, render_element, send_to_jinja, is_parent_dynamic_height) }}
{% elif element.type == "image" %}
{{image(element)}}
{% elif element.type == "table" %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<!-- third Arg in render_user_text is row which is not sent outside table -->
{% macro statictext(element, send_to_jinja, dynamic_containers) -%}
<div style="position:{%- if dynamic_containers -%}relative{% else %}absolute{%- endif -%}; top:{{ element.startY }}px; left:{{ element.startX }}px;{% if element.isFixedSize %}width:{{ element.width }}px;{%- if not is_parent_dynamic_height -%}height:{{ element.height }}px; {%- endif -%}{% else %}width:fit-content; height:fit-content; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX) + 2 }}px; white-space:nowrap; {%endif%}" class="
{% macro statictext(element, send_to_jinja, is_parent_dynamic_height) -%}
<div style="position:{%- if is_parent_dynamic_height != 'fixed' -%}relative{% else %}absolute{%- endif -%}; {%- if is_parent_dynamic_height == 'fixed' -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px;{% if element.isFixedSize %}width:{{ element.width }}px;{%- if is_parent_dynamic_height == 'fixed' -%}height:{{ element.height }}px; {%- endif -%}{% else %}width:fit-content; height:fit-content; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX) + 2 }}px; white-space:nowrap; {%endif%}" class="
{{ element.classes | join(' ') }}">
<p style="{% if element.isFixedSize %}width:{{ element.width }}px; {%- if not is_parent_dynamic_height -%}height:{{ element.height }}px; {%- endif -%}{% else %}width:fit-content; height:fit-content; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX ) + 2 }}px; white-space:nowrap;{%endif%} {{convert_css(element.style)}}"
<p style="{% if element.isFixedSize %}width:{{ element.width }}px; {%- if is_parent_dynamic_height == 'fixed' -%}height:{{ element.height }}px; {%- endif -%}{% else %}width:fit-content; height:fit-content; max-width: {{ (settings.page.width - settings.page.marginLeft - settings.page.marginRight - element.startX ) + 2 }}px; white-space:nowrap;{%endif%} {{convert_css(element.style)}}"
class="staticText {{ element.classes | join(' ') }}">
{% if element.parseJinja %}
{{ render_user_text(element.content, doc, {}, send_to_jinja).get("message", "") }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@
border-width: 0 !important;
}
.relative-column {
border-width: 1px !important;
border-color: white !important;
border-width: 0px !important;
border-color: transparent !important;
}
* {
-webkit-box-sizing: border-box;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{% macro table(element, send_to_jinja, is_parent_dynamic_height) -%}
<table style="position:{%- if is_parent_dynamic_height -%}relative{% else %}absolute{%- endif -%}; {%- if not is_parent_dynamic_height -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px; width:{{ element.width }}px;{%- if is_parent_dynamic_height and not element.isDynamicHeight -%} height:{{ element.height }}px; {%- endif -%} max-width:{{ element.width }}px;" class="table-container printTable {{ element.classes | join(' ') }}">
{%- set heightType = element.get("heightType") -%}
{%- if settings.get("schema_version") == "1.1.0" -%}
{%- set heightType = "auto" if element.get("isDynamicHeight", False) else "fixed" -%}
{%- endif -%}
<table style="position:{%- if is_parent_dynamic_height != 'fixed' -%}relative{% else %}absolute{%- endif -%}; {%- if is_parent_dynamic_height == 'fixed' -%}top: {%- else -%}margin-top: {%- endif -%}{{ element.startY }}px; left:{{ element.startX }}px; width:{{ element.width }}px;{%- if is_parent_dynamic_height != 'fixed' and heightType != 'auto' -%}{%- if heightType == 'auto-min-height' -%}min-{%- endif -%}height:{{ element.height }}px;{%- endif -%} max-width:{{ element.width }}px;" class="table-container printTable {{ element.classes | join(' ') }}">
<thead>
{% if element.columns %}
<tr>
Expand Down
22 changes: 6 additions & 16 deletions print_designer/public/js/print_designer/PropertiesPanelState.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,15 +437,15 @@ export const createPropertiesPanel = () => {
[
{
label: "Height",
name: "isDynamicHeight",
name: "heightType",
isLabelled: true,
labelDirection: "column",
condtional: () => {
const currentEl = MainStore.getCurrentElementsValues[0];
if (
(currentEl.parent === ElementStore.Elements &&
currentEl?.type === "table") ||
(currentEl.type === "text" && currentEl.isDynamic)
currentEl?.type === "table" ||
(currentEl.type === "text" &&
(currentEl.isDynamic || currentEl.parseJinja))
) {
return true;
}
Expand All @@ -459,23 +459,13 @@ export const createPropertiesPanel = () => {
fieldtype: "Select",
requiredData: [MainStore.getCurrentElementsValues[0]],
reactiveObject: () => MainStore.getCurrentElementsValues[0],
propertyName: "isDynamicHeight",
propertyName: "heightType",
isStyle: false,
options: () => [
{ label: "Auto", value: "auto" },
{ label: "Auto ( min-height)", value: "auto-min-height" },
{ label: "Fixed", value: "fixed" },
],
formatValue: (object, property, isStyle) => {
if (!object) return;
return object[property] ? "auto" : "fixed";
},
onChangeCallback: (value = null) => {
if (value && MainStore.getCurrentElementsValues[0]) {
MainStore.getCurrentElementsValues[0]["isDynamicHeight"] =
value === "auto";
MainStore.frappeControls[name].$input.blur();
}
},
});
},
flex: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ const {
selectedColumn,
selectedDynamicText,
DOMRef,
isDynamicHeight,
} = toRefs(props.object);
watch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,11 +639,12 @@ watch(
background-color: transparent !important;
border: none !important;
z-index: 9999 !important;
outline: 1px double var(--primary) !important;
}
.relative-column {
background-color: transparent !important;
outline: 1px double var(--primary) !important;
border: none !important;
z-index: 9999 !important;
outline: 1px solid var(--primary) !important;
}
</style>
4 changes: 2 additions & 2 deletions print_designer/public/js/print_designer/defaultObjects.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export const createTable = (cordinates, parent = null) => {
labelStyle: {},
headerStyle: {},
altStyle: {},
isDynamicHeight: true,
heightType: "auto",
classes: [],
};

Expand Down Expand Up @@ -259,7 +259,7 @@ export const createDynamicText = (cordinates, parent = null) => {
labelDisplayStyle: "standard",
style: {},
labelStyle: {},
isDynamicHeight: true,
heightType: "auto",
classes: [],
};
parent !== ElementStore.Elements
Expand Down
90 changes: 75 additions & 15 deletions print_designer/public/js/print_designer/store/ElementStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,19 @@ export const useElementStore = defineStore("ElementStore", {
footer: [],
};
// {childrens: []} is passed because we update parent in createRectangle function.
let headerElements = { childrens: [] };
let bodyElements = { childrens: [] };
let footerElements = { childrens: [] };
// WARNING: 2 lines below are for debugging purpose only.
// this.Elements.length = 0;
// headerElements = bodyElements = footerElements = this.Elements;
if (header) {
layout.header = this.computeRowLayout(header, { childrens: [] }, "header");
layout.header = this.computeRowLayout(header, headerElements, "header");
}
// it will throw error if body is empty so no need to check here
layout.body = this.computeRowLayout(body, { childrens: [] }, "body");
layout.body = this.computeRowLayout(body, bodyElements, "body");
if (footer) {
layout.footer = this.computeRowLayout(footer, { childrens: [] }, "footer");
layout.footer = this.computeRowLayout(footer, footerElements, "footer");
}

objectToSave.print_designer_print_format = JSON.stringify(layout);
Expand Down Expand Up @@ -742,12 +748,12 @@ export const useElementStore = defineStore("ElementStore", {
},
updateChildrenInRowWrapper(wrapper, children) {
wrapper.childrens = children;
if (
wrapper.childrens.some(
(el) => el.layoutType == "column" || el.isDynamicHeight == true
)
) {
wrapper.isDynamicHeight = true;
if (wrapper.childrens.some((el) => el.heightType == "auto-min-height")) {
wrapper.heightType = "auto-min-height";
} else if (wrapper.childrens.some((el) => el.heightType == "auto")) {
wrapper.heightType = "auto";
} else {
wrapper.heightType = "fixed";
}
wrapper.childrens.sort((a, b) => (a.startY < b.startY ? -1 : 1));
wrapper.startX = 0;
Expand Down Expand Up @@ -781,10 +787,18 @@ export const useElementStore = defineStore("ElementStore", {
wrapper.startY = 0;
if (
wrapper.childrens.some(
(el) => el.layoutType == "row" || el.isDynamicHeight == true
(el) => el.layoutType == "row" || el.heightType == "auto-min-height"
)
) {
wrapper.isDynamicHeight = true;
wrapper.heightType = "auto-min-height";
} else if (
wrapper.childrens.some(
(el) => el.layoutType == "column" || el.heightType == "auto"
)
) {
wrapper.heightType = "auto";
} else {
wrapper.heightType = "fixed";
}
},
createRowWrapperElement(dimension, currentRow, parent) {
Expand Down Expand Up @@ -816,13 +830,35 @@ export const useElementStore = defineStore("ElementStore", {
wrapper.layoutType = "row";
this.updateRowChildrenDimensions(wrapper, currentRow, parent);
let childElements = [...currentRow];
if (currentRow.length > 1) {
let columnEls = this.computeColumnLayout(childElements, wrapper);
if (columnEls) {
childElements = columnEls;
const columnEls = this.computeColumnLayout(childElements, wrapper);
if (columnEls) {
childElements = columnEls;
} else {
if (childElements.at(-1).type == "rectangle") {
const el = childElements.at(-1);
if (el.type == "rectangle") {
el.childrens = this.computeRowLayout(el.childrens, el);
el.layoutType = "column";
el.classes.push("relative-column");
el.rectangleContainer = true;
if (el.childrens.some((e) => e.heightType == "auto-min-height")) {
el.heightType = "auto-min-height";
} else if (el.childrens.some((e) => e.heightType == "auto")) {
el.heightType = "auto";
} else {
el.heightType = "fixed";
}
}
}
}
this.updateChildrenInRowWrapper(wrapper, childElements);
if (childElements.some((el) => el.heightType == "auto-min-height")) {
wrapper.heightType = "auto-min-height";
} else if (childElements.some((el) => el.heightType == "auto")) {
wrapper.heightType = "auto";
} else {
wrapper.heightType = "fixed";
}
},
createColumnWrapperElement(dimension, currentColumn, parent) {
const coordinates = {
Expand All @@ -848,8 +884,32 @@ export const useElementStore = defineStore("ElementStore", {
const rowEls = this.computeRowLayout(childElements, wrapper);
if (rowEls) {
childElements = rowEls;
} else {
if (childElements.at(-1).type == "rectangle") {
const el = childElements.at(-1);
if (el.type == "rectangle") {
el.childrens = this.computeRowLayout(el.childrens, el);
el.layoutType = "column";
el.classes.push("relative-column");
el.rectangleContainer = true;
if (el.childrens.some((e) => e.heightType == "auto-min-height")) {
el.heightType = "auto-min-height";
} else if (el.childrens.some((e) => e.heightType == "auto")) {
el.heightType = "auto";
} else {
el.heightType = "fixed";
}
}
}
}
this.updateChildrenInColumnWrapper(wrapper, childElements);
if (childElements.some((el) => el.heightType == "auto-min-height")) {
wrapper.heightType = "auto-min-height";
} else if (childElements.some((el) => el.heightType == "auto")) {
wrapper.heightType = "auto";
} else {
wrapper.heightType = "fixed";
}
},
async printFormatCopyOnOlderSchema(objectToSave) {
// TODO: have better message.
Expand Down
Loading

0 comments on commit 8a4d958

Please sign in to comment.