feat: add Chart.js and Flatpickr with CDN fallback strategy

Add optional libraries with local fallback for offline development:

Vendor files added:
- static/shared/js/vendor/chart.umd.min.js (Chart.js 4.4.1)
- static/shared/js/vendor/flatpickr.min.js (Flatpickr 4.6.13)
- static/shared/css/vendor/flatpickr.min.css

Template updates:
- admin/base.html: Add optional blocks for chartjs_script, flatpickr_script, flatpickr_css
- shared/includes/optional-libs.html: CDN fallback loaders for both libraries

Usage in page templates:
  {% block flatpickr_css %}
    {% from 'shared/includes/optional-libs.html' import flatpickr_css_loader %}
    {{ flatpickr_css_loader() }}
  {% endblock %}

  {% block chartjs_script %}
    {% from 'shared/includes/optional-libs.html' import chartjs_loader %}
    {{ chartjs_loader() }}
  {% endblock %}

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-06 19:09:06 +01:00
parent b0db4d26d8
commit ffa15aee2b
5 changed files with 150 additions and 1 deletions

View File

@@ -18,6 +18,9 @@
[x-cloak] { display: none !important; }
</style>
<!-- Flatpickr CSS with CDN fallback (loaded on demand via block) -->
{% block flatpickr_css %}{% endblock %}
{% block extra_head %}{% endblock %}
</head>
<body x-cloak>
@@ -74,7 +77,13 @@
})();
</script>
<!-- 7. LAST: Page-specific scripts -->
<!-- 7. OPTIONAL: Chart.js with CDN fallback (loaded on demand via block) -->
{% block chartjs_script %}{% endblock %}
<!-- 8. OPTIONAL: Flatpickr with CDN fallback (loaded on demand via block) -->
{% block flatpickr_script %}{% endblock %}
<!-- 9. LAST: Page-specific scripts -->
{% block extra_scripts %}{% endblock %}
</body>
</html>

View File

@@ -0,0 +1,105 @@
{#
Optional Libraries with CDN Fallback
=====================================
Include these blocks in pages that need Chart.js or Flatpickr.
Usage in a page template:
{% extends "admin/base.html" %}
{# For Flatpickr CSS (in head) #}
{% block flatpickr_css %}
{% include 'shared/includes/optional-libs.html' with context %}
{{ flatpickr_css_loader() }}
{% endblock %}
{# For Chart.js #}
{% block chartjs_script %}
{% include 'shared/includes/optional-libs.html' with context %}
{{ chartjs_loader() }}
{% endblock %}
{# For Flatpickr JS #}
{% block flatpickr_script %}
{% include 'shared/includes/optional-libs.html' with context %}
{{ flatpickr_loader() }}
{% endblock %}
#}
{#
Chart.js Loader with CDN Fallback
=================================
Loads Chart.js from CDN, falls back to local copy if CDN fails.
#}
{% macro chartjs_loader() %}
<script>
(function() {
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js';
script.onerror = function() {
console.warn('Chart.js CDN failed, loading local copy...');
var fallbackScript = document.createElement('script');
fallbackScript.src = '{{ url_for("static", path="shared/js/vendor/chart.umd.min.js") }}';
document.head.appendChild(fallbackScript);
};
document.head.appendChild(script);
})();
</script>
{% endmacro %}
{#
Flatpickr CSS Loader with CDN Fallback
======================================
Loads Flatpickr CSS from CDN, falls back to local copy if CDN fails.
#}
{% macro flatpickr_css_loader() %}
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css"
onerror="this.onerror=null; this.href='{{ url_for('static', path='shared/css/vendor/flatpickr.min.css') }}';"
/>
{% endmacro %}
{#
Flatpickr JS Loader with CDN Fallback
=====================================
Loads Flatpickr JS from CDN, falls back to local copy if CDN fails.
#}
{% macro flatpickr_loader() %}
<script>
(function() {
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.js';
script.onerror = function() {
console.warn('Flatpickr CDN failed, loading local copy...');
var fallbackScript = document.createElement('script');
fallbackScript.src = '{{ url_for("static", path="shared/js/vendor/flatpickr.min.js") }}';
document.head.appendChild(fallbackScript);
};
document.head.appendChild(script);
})();
</script>
{% endmacro %}
{#
Combined Loaders
================
Convenience macros to load multiple libraries at once.
#}
{# Load Chart.js + Flatpickr together #}
{% macro all_optional_libs_css() %}
{{ flatpickr_css_loader() }}
{% endmacro %}
{% macro all_optional_libs_js() %}
{{ chartjs_loader() }}
{{ flatpickr_loader() }}
{% endmacro %}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long