Skip to content

TwigException "Unexpected end of object" when re-render compiled template #901

Open
@dmitry-k-asb

Description

@dmitry-k-asb

I have template and run "test" function 2 times. First time it work, second time i have TwigException "Unexpected end of object". What i doing wrong?

Test function:

function test()
{   
    var task = {}
    task.id = 'TEST_TASK_ID'
    task.status = TASK_STATUS_SUCCESS
    task.name = 'TEST TASK NAME'
    task.result_count = 0
    task.create_at = 1725445537
    task.start_at = 1725445537
    task.end_at = 1725448000
    task.random = 123456789
    task.node_info = 'localhost'
    task.description = 'TEST DESCRIPTION'
    task.important = 1

    var env = {
        'page_type': 'tools',
        'select': 1,
        'can_select': 1,
        'status_onclick': 'test_status_onclick_func()'
    }

    var _DATA = {
        'task': task,
        'env':  env
    }

    TwigTemplateStorage.render('history_task_item', _DATA).then(rendered => console.log(rendered))
}

My class:

class TwigTemplateStorage {

    static _config = {
        'history_task_item': '/templates/task_item.twig',

    }

    static templates = {}

    static async _load(template_id, path)
    {
        const response = await fetch(path)
        const text = await response.text()

        TwigTemplateStorage.templates[template_id] = Twig.twig({
            'data': text.trim(),
        });
    };

    static async render(template_id, data)
    {
        if (!(template_id in TwigTemplateStorage.templates)) {
            if (template_id in TwigTemplateStorage._config) {     
                let path = TwigTemplateStorage._config[template_id]
                await TwigTemplateStorage._load(template_id, path)
            } else {
                throw new Error(template_id + ' not registered in TwigTemplateStorage _config')
            }
        }

        var compiled = TwigTemplateStorage.templates[template_id]
        var out = compiled.render({ '_DATA': data })
        return out.trim()
    }
}

My template:

{% set TASK_STATUS_WAIT    = 0  %}
{% set TASK_STATUS_RUN     = 1  %}
{% set TASK_STATUS_FAIL    = 9  %}
{% set TASK_STATUS_SUCCESS = 10 %}

{% set TASK_CAN_SELECT    = 0 %}
{% set TASK_SELECTED      = 1 %}
{% set TASK_CANNOT_SELECT = 2 %}

{% set status_icon_map = {
	'cases': {
		(TASK_STATUS_WAIT): {
			(TASK_CANNOT_SELECT): 'si si-clock',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-check'
		},
		(TASK_STATUS_RUN): {
			(TASK_CANNOT_SELECT): 'si si-clock',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-check'
		},
		(TASK_STATUS_FAIL): {
			(TASK_CANNOT_SELECT): 'icon-exclamation'
		},
		(TASK_STATUS_SUCCESS): {
			(TASK_CANNOT_SELECT): 'si si-check',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-check'
		},
	},
	'tools': {
		(TASK_STATUS_WAIT): {
			(TASK_CANNOT_SELECT): 'si si-clock',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-close'
		},
		(TASK_STATUS_RUN): {
			(TASK_CANNOT_SELECT): 'si si-clock',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-close'
		},
		(TASK_STATUS_FAIL): {
			(TASK_CANNOT_SELECT): 'icon-exclamation',
		},
		(TASK_STATUS_SUCCESS): {
			(TASK_CANNOT_SELECT): 'si si-check',
			(TASK_CAN_SELECT): 'si si-plus',
			(TASK_SELECTED): 'si si-close'
		},
	},
	'my_tasks': {
		(TASK_STATUS_WAIT): {
			(TASK_CANNOT_SELECT): 'si si-clock',
		},
		(TASK_STATUS_RUN): {
			(TASK_CANNOT_SELECT): 'si si-clock',
		},
		(TASK_STATUS_FAIL): {
			(TASK_CANNOT_SELECT): 'icon-exclamation'
		},
		(TASK_STATUS_SUCCESS): {
			(TASK_CANNOT_SELECT): 'si si-check',
		},
	},
} %}
{% if status_icon_map[_DATA.env.page_type][_DATA.task.status][_DATA.env.select] is empty %}
	{% set icon_class = 'icon-question' %}
{% else %}
	{% set icon_class = status_icon_map[_DATA.env.page_type][_DATA.task.status][_DATA.env.select] %}
{% endif %}


{% if _DATA.task.status == TASK_STATUS_SUCCESS and _DATA.task.result_count > 0 %}
    {% set group = 'ok' %}
{% elseif _DATA.task.status == TASK_STATUS_SUCCESS and _DATA.task.result_count == 0 %}
    {% set group = 'empty' %}
{% elseif _DATA.task.status == TASK_STATUS_FAIL %}
	{% set group = 'fail' %}
{% elseif _DATA.task.status == TASK_STATUS_RUN or _DATA.task.status == TASK_STATUS_WAIT %}
	{% set group = 'wait' %}
{% endif %}

{% set status_group_map = {
	'ok': {
		'icon_color_class': 'task2-status-blue-icon',
		'history2_group': 'history2-description-status-ok'
	},
	'empty': {
		'icon_color_class': 'task2-status-red-icon',
		'history2_group': 'history2-description-status-empty'
	},
	'fail': {
		'icon_color_class': 'task2-status-red-icon',
		'history2_group': 'history2-description-status-fail'
	},
	'wait': {
		'icon_color_class': 'task2-status-grey-icon',
		'history2_group': 'history2-description-status-wait'
	}
} %}
{% if status_group_map[group] is empty %}
	{% set icon_color_class = 'task2-status-red-icon' %}
	{% set history2_group = 'history2-description-status-fail' %}
{% else %}
	{% set icon_color_class = status_group_map[group]['icon_color_class'] %}
	{% set history2_group = status_group_map[group]['history2_group'] %}
{% endif %}

{% if _DATA.task.end_at is not empty and _DATA.task.start_at is not empty %}
	{% set work_time  = _DATA.task.end_at - _DATA.task.start_at %}
	{% set work_hours = work_time > 3600 ? (work_time // 3600) : 0 %}
	{% set work_mins  = (work_time % 3600) // 60 %}
	{% set work_secs  = (work_time % 3600)  % 60 %}

	{% set work_hours = "%02d"|format(work_hours) %}
	{% set work_mins  = "%02d"|format(work_mins)  %}
	{% set work_secs  = "%02d"|format(work_secs)  %}

	{% set work_time = (work_hours > 0) ? work_hours ~ ':' ~ work_mins ~ ':' ~ work_secs : work_mins ~ ':' ~ work_secs %}
{% else %}
	{% set work_time = 'err' %}
{% endif %}

{% if _DATA.task.create_at is not empty %}
	{% set create_at      =  _DATA.task.create_at|date('d.m.Y') %}
	{% set create_at_full =  _DATA.task.create_at|date('H:i d.m.Y') %}
{% else %}
	{% set create_at      =  'err' %}
	{% set create_at_full =  'err' %}
{% endif %}

<div class="history2-one-task" data-id="{{_DATA.task.id}}">
	<div class="history2-card-and-toolbar">
		<div class="history2-card">
			<div class="history2-base-row">
				<span
                    class="task-icon {{icon_color_class}} task2-status-tooltip"
                    data-info="{}"
                    data-status="{{_DATA.task.status}}"
                    data-id="{{_DATA.task.id}}"
                    data-output=""
                    data-time="{{create_at_full}}"
                    data-name="{{_DATA.task.name}}"
                    data-count="{{_DATA.task.result_count|default('err')}}"
                    data-select="{{_DATA.env.select}}"
                    onclick="{{_DATA.env.status_onclick}}"
                    data-history2-group="{{history2_group}}"
					{% if _DATA.env.can_select == 1 %}
                    	style="cursor: pointer"
					{% endif %}
                >
					<i class="{{ icon_class }}"></i>
				</span>
				<div class="history2-name">
					{% if _DATA.task.status == TASK_STATUS_SUCCESS and _DATA.task.result_count > 0 %}
						<a class="link-primary" onclick="view.open('vk_users_array_id','{{_DATA.task.id}}','')">{{_DATA.task.name}}</a>
					{% else %}
						{{_DATA.task.name}}
					{% endif %}
				</div>
			</div>
			<div class="history2-info-row" data-id="{{_DATA.task.id}}">

				{% if _DATA.task.status in [TASK_STATUS_RUN, TASK_STATUS_WAIT] %}
					<div class="task-description" data-id="{{_DATA.task.id}}">{{_DATA.task.description|default('err')}}</div>
				{% else %}
					<span title="{{create_at_full}}">
						<i class="si si-calendar" style="padding-right: 2px;"></i>
						{{create_at}}
					</span>
					<div>
						<i class="si si-docs"></i>
						{{_DATA.task.result_count |default('err')}}
					</div>
					<div title="Время выполнения задачи">
						<i class="si si-reload"></i>
						{{work_time}}
					</div>
				{% endif %}
			</div>
			{% if _DATA.task.node_info is not empty %}
				{{_DATA.task.id}} / {{_DATA.task.node_info}}
			{% endif %}
		</div>
		<div class="history2-toolbar">
			{% if _DATA.task.important == 0 %}
				<i title="Пометить как важную" class="si si-star history2-toolbar-items" onclick="task.important(this,'{{_DATA.task.id}}');"></i>
			{% else %}
				<i title="Важная задача" class="fa fa-star task-important history2-toolbar-items" onclick="task.important(this,'{{_DATA.task.id}}');"></i>
			{% endif %}
			<i class="si si-equalizer history2-toolbar-items" title="Параметры задачи" onclick="task.params('{{_DATA.task.id}}');"></i>
			<i class="si si-reload history2-toolbar-items" title="Перезагрузить" onclick="task.restart('{{_DATA.task.id}}');"></i>
			<i class="si si-trash history2-toolbar-items" title="Удалить задачу" onclick="task.delete('{{_DATA.task.id}}');"></i>
		</div>
	</div>
	<div class="history2-progress-bar">
		<div class="progress progress-mini">
			<div class="progress-bar task-progress" data-id="{{_DATA.task.id}}" data-random="{{_DATA.task.random}}"></div>
		</div>
	</div>
</div>

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions