Complete system for getting + saving Product Categories with new database, server, and client architecture.

This commit is contained in:
2024-09-01 21:57:46 +01:00
parent ba50aec9c9
commit b3e801e1ec
303 changed files with 4358 additions and 2885 deletions

View File

@@ -0,0 +1 @@
<div class="{{ model.FLAG_SLIDER }}"></div>

View File

@@ -1 +0,0 @@
<div class="{{ model.FLAG_BUTTON_SLIDER }}"></div>

View File

@@ -14,24 +14,37 @@
</div>
<script>
var idOverlayConfirm = "#{{ model.ID_OVERLAY_CONFIRM }}";
function hookupOverlayConfirm(callbackSuccess) {
let overlay = $("#{{ model.ID_OVERLAY_CONFIRM }}");
let textarea = overlay.find('#{{ model.ID_TEXTAREA_CONFIRM }}');
let buttonCancel = overlay.find('#{{ model.ID_BUTTON_CANCEL }}');
let buttonConfirm = overlay.find('#{{ model.ID_BUTTON_CONFIRM }}');
/*
let overlay = document.querySelector("#{{ model.ID_OVERLAY_CONFIRM }}");
let textarea = overlay.querySelector('#{{ model.ID_TEXTAREA_CONFIRM }}');
let buttonCancel = overlay.querySelector('#{{ model.ID_BUTTON_CANCEL }}');
let buttonConfirm = overlay.querySelector('#{{ model.ID_BUTTON_CONFIRM }}');
*/
let selectorTextarea = idOverlayConfirm + ' textarea';
let selectorButtonCancel = idOverlayConfirm + ' button.' + flagCancel;
let selectorButtonConfirm = idOverlayConfirm + ' button.' + flagSubmit;
buttonCancel.onclick = function() {
overlay.style.visibility = 'hidden';
};
buttonConfirm.onclick = function() {
overlay.style.visibility = 'hidden';
callbackSuccess(textarea.value);
};
initialiseEventHandler(selectorButtonCancel, flagInitialised, function(buttonCancel) {
buttonCancel.addEventListener('click', function() {
let overlay = document.querySelector(idOverlayConfirm);
overlay.style.visibility = 'hidden';
});
});
initialiseEventHandler(selectorButtonConfirm, flagInitialised, function(buttonConfirm) {
buttonConfirm.addEventListener('click', function() {
let overlay = document.querySelector(idOverlayConfirm);
let textarea = overlay.querySelector('textarea');
overlay.style.visibility = 'hidden';
callbackSuccess(textarea.value);
});
});
}
function showOverlayConfirm() {
let overlay = $("#{{ model.ID_OVERLAY_CONFIRM }}");
let overlay = document.querySelector(idOverlayConfirm);
overlay.classList.remove(flagCollapsed);
overlay.style.visibility = 'visible';
}
</script>

View File

@@ -1,4 +1,4 @@
<div class="{{ model.FLAG_OVERLAY }} {{ model.FLAG_COLLAPSED }} {{ model.FLAG_CARD }}" id="{{ model.ID_OVERLAY_CONFIRM }}" style="visibility: hidden;" z-index="2">
<div class="{{ model.FLAG_OVERLAY }} {{ model.FLAG_COLLAPSED }} {{ model.FLAG_CARD }}" id="{{ model.ID_OVERLAY_ERROR }}" style="visibility: hidden;" z-index="2">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<h2>Error:</h2>
<div id="{{ model.ID_LABEL_ERROR }}"></div>
@@ -10,20 +10,23 @@
</div>
<script>
function hookupOverlayConfirm() {
let overlay = $("#{{ model.ID_OVERLAY_CONFIRM }}");
let buttonCancel = overlay.find('#{{ model.ID_BUTTON_CANCEL }}');
var idOverlayError = "#{{ model.ID_OVERLAY_ERROR}}";
function hookupOverlayError() {
let overlay = document.querySelector(idOverlayError);
let selectorButtonCancel = idOverlayError + ' button.' + flagCancel;
buttonCancel.onclick = function() {
overlay.style.visibility = 'hidden';
};
initialiseEventHandler(selectorButtonCancel, flagInitialised, function(buttonCancel) {
buttonCancel.onclick = function() {
overlay.style.visibility = 'hidden';
};
});
}
hookupOverlayConfirm();
hookupOverlayError();
function showOverlayError(msgError) {
let overlay = $("#{{ model.ID_OVERLAY_CONFIRM }}");
let labelError = overlay.find('#{{ model.ID_LABEL_ERROR }}');
labelError.text(msgError);
let overlay = document.querySelector("#{{ model.ID_OVERLAY_ERROR }}");
let labelError = overlay.querySelector('#{{ model.ID_LABEL_ERROR }}');
labelError.innerText = msgError;
overlay.style.visibility = 'visible';
}
</script>

View File

@@ -0,0 +1,5 @@
{% if id_access_level is defined %}
<select class="{{ model.FLAG_ACCESS_LEVEL }}" {{ model.ATTR_VALUE_CURRENT }}="{{ id_access_level }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ id_access_level }}" value="{{ id_access_level }}"></select>
{% else %}
<select class="{{ model.FLAG_ACCESS_LEVEL }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></select>
{% endif %}

View File

@@ -0,0 +1,5 @@
{% if display_order is defined %}
<div class="{{ model.FLAG_SLIDER }} {{ model.FLAG_DISPLAY_ORDER }}" {{ model.ATTR_VALUE_CURRENT }}="{{ display_order }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ display_order }}"></div>
{% else %}
<div class="{{ model.FLAG_SLIDER }} {{ model.FLAG_DISPLAY_ORDER }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></div>
{% endif %}

View File

@@ -1,16 +1,19 @@
{% if is_blank_row %}
<tr class="{{ model.FLAG_ROW_NEW }}" {{ model.ATTR_ID_CATEGORY }}>
<td class="{{ model.FLAG_DISPLAY_ORDER }}">
{% include '_block_button_slider.html' %}
{% include '_block_slider_display_order.html' %}
</td>
<td class="{{ model.FLAG_CODE }}">
<textarea class="{{ model.FLAG_CODE }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></select>
<textarea class="{{ model.FLAG_CODE }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></textarea>
</td>
<td class="{{ model.FLAG_NAME }}">
<textarea class="{{ model.FLAG_NAME }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></textarea>
</td>
<td class="{{ model.FLAG_DESCRIPTION }}">
<textarea class="{{ model.FLAG_DESCRIPTION }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}>
<textarea class="{{ model.FLAG_DESCRIPTION }}" {{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }}></textarea>
</td>
<td class="{{ model.FLAG_ACCESS_LEVEL }}">
{% include '_block_select_access_level.html' %}
</td>
<td class="{{ model.FLAG_ACTIVE }}">
<input class="{{ model.FLAG_ACTIVE }}" type="checkbox" checked {{ model.ATTR_VALUE_CURRENT }}="true" {{ model.ATTR_VALUE_PREVIOUS }}="true">
@@ -19,19 +22,24 @@
{% else %}
<tr {{ model.ATTR_ID_CATEGORY }}="{{ category.id_category }}">
<td class="{{ model.FLAG_DISPLAY_ORDER }}">
{% include '_block_button_slider.html' %}
{% set display_order = category.display_order %}
{% include '_block_slider_display_order.html' %}
</td>
<td class="{{ model.FLAG_CODE }}">
<textarea class="{{ model.FLAG_CODE }}" value="{{ category.code }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.code }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.code }}"></select>
<textarea class="{{ model.FLAG_CODE }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.code }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.code }}">{{ category.code }}</textarea>
</td>
<td class="{{ model.FLAG_NAME }}">
<textarea class="{{ model.FLAG_NAME }}" value="{{ category.name }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.name }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.name }}"></textarea>
<textarea class="{{ model.FLAG_NAME }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.name }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.name }}">{{ category.name }}</textarea>
</td>
<td class="{{ model.FLAG_DESCRIPTION }}">
<textarea class="{{ model.FLAG_DESCRIPTION }}" value="{{ category.description }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.description }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.description }}">
<textarea class="{{ model.FLAG_DESCRIPTION }}" {{ model.ATTR_VALUE_CURRENT }}="{{ category.description }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.description }}">{{ category.description }}</textarea>
</td>
<td class="{{ model.FLAG_ACCESS_LEVEL }}">
{% set id_access_level = category.id_access_level_required %}
{% include '_block_select_access_level.html' %}
</td>
<td class="{{ model.FLAG_ACTIVE }}">
<input class="{{ model.FLAG_ACTIVE }}" type="checkbox" {% if category.active %}checked{% endif %} {{ model.ATTR_VALUE_CURRENT }}="{{ str(category.active).lower() }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ str(category.active).lower() }}">
<input class="{{ model.FLAG_ACTIVE }}" type="checkbox" {% if category.active %}checked{% endif %} {{ model.ATTR_VALUE_CURRENT }}="{{ category.active | lower }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ category.active | lower }}">
</td>
</tr>
{% endif %}

View File

@@ -1,9 +1,14 @@
{% if block_id == 'button_save' %}
<button id="{{ model.ID_BUTTON_SAVE }}" type="button" class="{{ model.FLAG_BUTTON_SUBMIT }}">Save</button>
<button id="{{ model.ID_BUTTON_SAVE }}" type="button" class="{{ model.FLAG_SUBMIT }} {{ model.FLAG_SAVE }}">Save</button>
{% elif block_id == 'button_cancel' %}
<button id="{{ model.ID_BUTTON_CANCEL }}" type="button" class="{{ model.FLAG_BUTTON_CANCEL }}">Cancel</button>
<button id="{{ model.ID_BUTTON_CANCEL }}" type="button" class="{{ model.FLAG_CANCEL }}">Cancel</button>
{% elif block_id == 'button_add' %}
<button id="{{ model.ID_BUTTON_ADD }}" type="button" class="{{ model.FLAG_ADD }}">Add new</button>
{% elif block_id == 'button_confirm' %}
<button id="{{ model.ID_BUTTON_CONFIRM }}" type="button" class="{{ model.FLAG_BUTTON_SUBMIT }}">Confirm</button>
<button id="{{ model.ID_BUTTON_CONFIRM }}" type="button" class="{{ model.FLAG_SUBMIT }}">Confirm</button>
{% elif block_id == 'button_get_in_touch' %}
<button class="{{ model.FLAG_NAV_CONTACT_US }}" alt="Get in touch" aria-label="Get in touch">Get in touch</button>
{% elif block_id == 'button_apply_filters' %}
<button id="{{ model.ID_BUTTON_APPLY_FILTERS }}" type="button" class="{{ model.FLAG_SUBMIT }}">Apply filters</button>
{% elif block_id == 'button_clear_filters' %}
{% endif %}

View File

@@ -5,10 +5,10 @@
{% include '_shared_store.html' %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/pages/page_store_product_categories.css') }}">
<form id="{{ model.ID_FORM_FILTERS_CATEGORIES }}" class="{{ model.FLAG_ROW }} {{ model.FLAG_CARD }}" action="{{ url_for('routes_store.category_save') }}" method="POST"> <!-- {{ model.FLAG_CONTAINER }} -->
<form id="{{ model.ID_FORM_FILTERS_PRODUCT_CATEGORY }}" class="{{ model.FLAG_FILTER }} {{ model.FLAG_ROW }} {{ model.FLAG_CARD }}" action="{{ url_for('routes_store_product_category.save_category') }}" method="POST"> <!-- {{ model.FLAG_CONTAINER }} -->
{{ model.form_filters.hidden_tag() }}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_ROW }}">
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_ROW }} {{ model.FLAG_FILTER }}">
{{ model.form_filters.is_not_empty.label }}
{{ model.form_filters.is_not_empty() }}
{% for error in model.form_filters.is_not_empty.errors %}
@@ -16,6 +16,21 @@
{% endfor %}
</div>
</div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_ROW }} {{ model.FLAG_FILTER }}">
{{ model.form_filters.active.label }}
{{ model.form_filters.active() }}
{% for error in model.form_filters.active.errors %}
<p class="error">{{ error }}</p>
{% endfor %}
</div>
</div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_ROW }}">
{% set block_id = 'button_apply_filters' %}
{% include '_blocks_button_save_cancel.html' %}
</div>
</div>
<!--
-->
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
@@ -43,6 +58,8 @@
</div>
-->
</form>
<table id="{{ model.ID_TABLE_MAIN }}" class="{{ model.FLAG_ROW }} {{ model.FLAG_CARD }}">
<thead>
<tr class="{{ model.FLAG_PRODUCT_CATEGORY }}">
@@ -50,6 +67,8 @@
<th class="{{ model.FLAG_CODE }}">Code</th>
<th class="{{ model.FLAG_NAME }}">Name</th>
<th class="{{ model.FLAG_DESCRIPTION }}">Description</th>
<th class="{{ model.FLAG_ACCESS_LEVEL }}">Access Level Required</th>
<th class="{{ model.FLAG_ACTIVE}}">Active</th>
</tr>
</thead>
<tbody>
@@ -68,14 +87,15 @@
{% set block_id = 'scripts' %}
{% include '_shared_store.html' %}
<!-- Include JavaScript -->
<script type="module" src="{{ url_for('static', filename='js/pages/page_store_product_permutations.js') }}"></script>
<!-- Include JavaScript
<script type="module" src="{{ url_for('static', filename='js/pages/page_store_product_categories.js') }}"></script>
-->
<script>
// pass arguments from model to JS
var idFormFiltersProductCategories = "#{{ model.ID_FORM_FILTERS_PRODUCT_CATEGORIES }}";
var flagIsNotEmpty = "{{ model.FLAG_IS_NOT_EMPTY }}";
var idFormFiltersProductCategory = "#{{ model.ID_FORM_FILTERS_PRODUCT_CATEGORY }}";
var keyProductCategory = "{{ model.KEY_PRODUCT_CATEGORY }}";
var listCategories = {{ model.category_list.to_list_categories() | tojson | safe }};
var listCategories = {{ model.category_list.to_list_category_options() | tojson | safe }};
</script>
{% endblock %}

View File

@@ -1,4 +1 @@
{% if block_id == 'button_get_in_touch' %}
<button class="{{ model.FLAG_NAV_CONTACT_US }}" alt="Get in touch" aria-label="Get in touch">Get in touch</button>
{% endif %}

View File

@@ -6,8 +6,9 @@
<!-- Include Stylesheet -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/sections/store.css') }}">
{% elif block_id == 'scripts' %}
<!-- Include JavaScript -->
<!-- Include JavaScript
<script src="{{ url_for('static', filename='js/store_shared.js') }}"></script>
-->
<!-- Variables from Model_View_Store + model-->
<script>
var attrFormType = "{{ model.ATTR_FORM_TYPE }}";
@@ -27,6 +28,10 @@
var flagQuantityMax = "{{ model.FLAG_QUANTITY_MAX }}";
var flagQuantityStock = "{{ model.FLAG_QUANTITY_STOCK }}";
var flagVariations = "{{ model.FLAG_VARIATIONS }}";
var hashGetStoreProductCategory = "{{ model.HASH_GET_STORE_PRODUCT_CATEGORY }}";
var hashGetStoreProductPermutation = "{{ model.HASH_GET_STORE_PRODUCT_PERMUTATION }}";
var hashSaveStoreProductCategory = "{{ model.HASH_SAVE_STORE_PRODUCT_CATEGORY }}";
var hashSaveStoreProductPermutation = "{{ model.HASH_SAVE_STORE_PRODUCT_PERMUTATION }}";
var hashStoreBasketAdd = "{{ model.HASH_STORE_BASKET_ADD }}";
var hashStoreBasketDelete = "{{ model.HASH_STORE_BASKET_DELETE }}";
var hashStoreBasketEdit = "{{ model.HASH_STORE_BASKET_EDIT }}";

View File

@@ -44,29 +44,36 @@
<script src="{{ url_for('static', filename='js/lib/local_storage.js') }}"></script>
<script src="{{ url_for('static', filename='js/lib/utils.js') }}"></script>
<script src="{{ url_for('static', filename='js/lib/validation.js') }}"></script>
<script type="module" src="{{ url_for('static', filename='js/app.js') }}"></script>
<script>
// var attrFor = "{{ model.ATTR_FOR }}";
var attrTextCollapsed = "{{ model.ATTR_TEXT_COLLAPSED }}";
var attrTextExpanded = "{{ model.ATTR_TEXT_EXPANDED }}";
var attrValueCurrent = "{{ model.ATTR_VALUE_CURRENT }}";
var attrValuePrevious = "{{ model.ATTR_VALUE_PREVIOUS }}";
var attrValueNew = "{{ model.ATTR_VALUE_NEW }}";
var flagActive = "{{ model.FLAG_ACTIVE }}";
var flagAdd = "{{ model.FLAG_ADD }}";
var flagCancel = "{{ model.FLAG_CANCEL }}";
var flagCard = "{{ model.FLAG_CARD }}";
var flagCode = "{{ model.FLAG_CODE }}";
var flagCollapsed = "{{ model.FLAG_COLLAPSED }}";
var flagCollapsible = "{{ model.FLAG_COLLAPSIBLE }}";
var flagColumn = "{{ model.FLAG_COLUMN }}";
var flagComment = "{{ model.FLAG_COMMENT }}";
// var flagContactUs = "{{ model.FLAG_CONTACT_US }}";
var flagContainer = "{{ model.FLAG_CONTAINER }}";
var flagContainerInput = "{{ model.FLAG_CONTAINER_INPUT }}";
var flagDelete = "{{ model.FLAG_DELETE }}";
var flagDescription = "{{ model.FLAG_DESCRIPTION }}";
var flagDetail = "{{ model.FLAG_DETAIL }}";
var flagDirty = "{{ model.FLAG_DIRTY }}";
var flagDisplayOrder = "{{ model.FLAG_DISPLAY_ORDER }}";
var flagExpanded = "{{ model.FLAG_EXPANDED }}";
var flagFilter = "{{ model.FLAG_FILTER }}";
var flagImageLogo = "{{ model.FLAG_IMAGE_LOGO }}";
var flagInitialised = "{{ model.FLAG_INITIALISED }}";
var flagName = "{{ model.FLAG_NAME }}";
var flagNavAdminHome = "{{ model.FLAG_NAV_ADMIN_HOME }}";
var flagNavAdminStoreStripePrices = "{{ model.FLAG_NAV_ADMIN_STORE_STRIPE_PRICES }}";
var flagNavAdminStoreStripeProducts = "{{ model.FLAG_NAV_ADMIN_STORE_STRIPE_PRODUCTS }}";
@@ -88,7 +95,9 @@
var flagOverlayClose = "{{ model.FLAG_OVERLAY_CLOSE }}";
var flagRow = "{{ model.FLAG_ROW }}";
var flagRowNew = "{{ model.FLAG_ROW_NEW }}";
var flagSave = "{{ model.FLAG_SAVE }}";
var flagScrollable = "{{ model.FLAG_SCROLLABLE }}";
var flagSlider = "{{ model.FLAG_SLIDER }}";
var flagSubmit = "{{ model.FLAG_SUBMIT }}";
var flagSubmitted = "{{ model.FLAG_SUBMITTED }}";
var hashApplyFiltersStoreProductPermutation = "{{ model.HASH_APPLY_FILTERS_STORE_PRODUCT_PERMUTATION }}";
@@ -115,7 +124,7 @@
var hashPageUserAdmin = "{{ model.HASH_PAGE_USER_ADMIN }}";
var hashPageUserLogin = "{{ model.HASH_PAGE_USER_LOGIN }}";
var hashPageUserLogout = "{{ model.HASH_PAGE_USER_LOGOUT }}";
var hashSaveStoreProductPermutation = "{{ model.HASH_SAVE_STORE_PRODUCT_PERMUTATION }}";
var idButtonApplyFilters = "#{{ model.ID_BUTTON_APPLY_FILTERS }}";
/*
var idButtonAdd = "#{{ model.ID_BUTTON_ADD }}";
var idButtonCancel = "#{{ model.ID_BUTTON_CANCEL }}";
@@ -150,6 +159,7 @@
var idOverlayHamburger = "#{{ model.ID_OVERLAY_HAMBURGER }}";
var idPageBody = "#{{ model.ID_PAGE_BODY }}";
var idTableMain = "#{{ model.ID_TABLE_MAIN }}";
var idTextareaConfirm = "#{{ model.ID_TEXTAREA_CONFIRM }}";
var isUserLoggedIn = "{{ model.output_bool(model.IS_USER_LOGGED_IN) }}";
var keyBasket = "{{ model.KEY_BASKET }}";
var keyCallback = "{{ model.KEY_CALLBACK }}";
@@ -288,6 +298,9 @@
</div>
</div>
<!--<script type="module" src="{{ url_for('static', filename='js/pages/page_base.js') }}"></script>-->
<script type="module" src="{{ url_for('static', filename='js/app.js') }}"></script>
</body>
</html>