From e72cc37d128594fe004581f7cd23a887fe24b68e Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Thu, 1 Aug 2024 16:59:36 +0000 Subject: [PATCH 01/12] feat(templates): status badges; - Added status badges. --- ckanext/xloader/config_declaration.yaml | 16 ++++ ckanext/xloader/helpers.py | 79 +++++++++++++++++++ ckanext/xloader/plugin.py | 2 + .../static/badges/en/datastore-active.svg | 1 + .../static/badges/en/datastore-complete.svg | 1 + .../static/badges/en/datastore-error.svg | 1 + .../static/badges/en/datastore-inactive.svg | 1 + .../static/badges/en/datastore-pending.svg | 1 + .../static/badges/en/datastore-running.svg | 1 + .../static/badges/en/datastore-unknown.svg | 1 + .../static/badges/fr/datastore-active.svg | 1 + .../static/badges/fr/datastore-complete.svg | 1 + .../static/badges/fr/datastore-error.svg | 1 + .../static/badges/fr/datastore-inactive.svg | 1 + .../static/badges/fr/datastore-pending.svg | 1 + .../static/badges/fr/datastore-running.svg | 1 + .../static/badges/fr/datastore-unknown.svg | 1 + .../templates/package/resource_read.html | 8 ++ .../package/snippets/resource_info.html | 6 ++ .../package/snippets/resource_item.html | 5 ++ 20 files changed, 130 insertions(+) create mode 100644 ckanext/xloader/public/static/badges/en/datastore-active.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-complete.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-error.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-inactive.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-pending.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-running.svg create mode 100644 ckanext/xloader/public/static/badges/en/datastore-unknown.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-active.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-complete.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-error.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-inactive.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-pending.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-running.svg create mode 100644 ckanext/xloader/public/static/badges/fr/datastore-unknown.svg create mode 100644 ckanext/xloader/templates/package/snippets/resource_info.html diff --git a/ckanext/xloader/config_declaration.yaml b/ckanext/xloader/config_declaration.yaml index 73120218..6d85e896 100644 --- a/ckanext/xloader/config_declaration.yaml +++ b/ckanext/xloader/config_declaration.yaml @@ -136,5 +136,21 @@ groups: that is not in ckanext.xloader.formats after a Resource is updated. type: bool required: false + - key: ckanext.xloader.show_badges + default: True + example: False + description: | + Controls whether or not the status badges display in the front end. + type: bool + required: false + - key: ckanext.xloader.debug_badges + default: False + example: True + description: | + Controls whether or not the status badges display all of the statuses. By default, + the badges will display "pending", "running", and "error". With debug_badges enabled, + they will also display "complete", "active", "inactive", and "unknown". + type: bool + required: false diff --git a/ckanext/xloader/helpers.py b/ckanext/xloader/helpers.py index 5712c81c..59de42d0 100644 --- a/ckanext/xloader/helpers.py +++ b/ckanext/xloader/helpers.py @@ -1,5 +1,7 @@ import ckan.plugins.toolkit as toolkit from ckanext.xloader.utils import XLoaderFormats +from markupsafe import Markup +from html import escape as html_escape def xloader_status(resource_id): @@ -42,3 +44,80 @@ def is_resource_supported_by_xloader(res_dict, check_access=True): else: is_supported_url_type = True return (is_supported_format or is_datastore_active) and user_has_access and is_supported_url_type + + +def xloader_badge(resource): + # type: (dict) -> str + """ + Displays a custom badge for the status of Xloader and DataStore for the specified resource. + """ + if not toolkit.asbool(toolkit.config.get('ckanext.xloader.show_badges', True)): + return '' + + if not XLoaderFormats.is_it_an_xloader_format(resource.get('format')): + # we only want to show badges for supported xloader formats + return '' + + is_datastore_active = resource.get('datastore_active', False) + + try: + xloader_job = toolkit.get_action("xloader_status")({'ignore_auth': True}, + {"resource_id": resource.get('id')}) + except toolkit.ObjectNotFound: + xloader_job = {} + + if xloader_job.get('status') == 'complete': + # the xloader task is complete, show datastore active or inactive. + # xloader will delete the datastore table at the beggining of the job run. + # so this will only be true if the job is fully finished. + status = 'active' if is_datastore_active else 'inactive' + elif xloader_job.get('status') in ['submitting', 'pending', 'running', 'running_but_viewable', 'error']: + # the job is running or pending or errored + # show the xloader status + status = xloader_job.get('status') + if status == 'running_but_viewable': + # treat running_but_viewable the same as running + status = 'running' + elif status == 'submitting': + # treat submitting the same as pending + status = 'pending' + else: + # we do not know what the status is + status = 'unknown' + + messages = { + 'pending': toolkit._('Data awaiting load to DataStore'), + 'running': toolkit._('Loading data into DataStore'), + 'complete': toolkit._('Data loaded into DataStore'), + 'error': toolkit._('Failed to load data into DataStore'), + 'active': toolkit._('Data available in DataStore'), + 'inactive': toolkit._('Resource not active in DataStore'), + 'unknown': toolkit._('DataStore status unknown'), + } + debug_level_statuses = ['complete', 'active', 'inactive', 'unknown'] + + if status in debug_level_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)): + return '' + + badge_url = toolkit.h.url_for_static('/static/badges/{lang}/datastore-{status}.svg'.format( + lang=toolkit.h.lang(), status=status)) + + title = toolkit.h.render_datetime(xloader_job.get('last_updated'), with_hours=True) \ + if xloader_job.get('last_updated') else '' + + try: + toolkit.check_access('resource_update', {'user': toolkit.g.user}, {'id': resource.get('id')}) + pusher_url = toolkit.h.url_for('xloader.resource_data', + id=resource.get('package_id'), + resource_id=resource.get('id')) + + return Markup(u'{alt}'.format( + pusher_url=pusher_url, + badge_url=badge_url, + alt=html_escape(messages[status], quote=True), + title=html_escape(title, quote=True))) + except toolkit.NotAuthorized: + return Markup(u'{alt}'.format( + badge_url=badge_url, + alt=html_escape(messages[status], quote=True), + title=html_escape(title, quote=True))) diff --git a/ckanext/xloader/plugin.py b/ckanext/xloader/plugin.py index 05d629c8..aef1fd98 100644 --- a/ckanext/xloader/plugin.py +++ b/ckanext/xloader/plugin.py @@ -51,6 +51,7 @@ def get_blueprint(self): def update_config(self, config): toolkit.add_template_directory(config, 'templates') + toolkit.add_public_directory(config, 'public') # IConfigurable @@ -206,6 +207,7 @@ def get_helpers(self): "xloader_status": xloader_helpers.xloader_status, "xloader_status_description": xloader_helpers.xloader_status_description, "is_resource_supported_by_xloader": xloader_helpers.is_resource_supported_by_xloader, + "xloader_badge": xloader_helpers.xloader_badge, } diff --git a/ckanext/xloader/public/static/badges/en/datastore-active.svg b/ckanext/xloader/public/static/badges/en/datastore-active.svg new file mode 100644 index 00000000..4a1d1ce9 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-active.svg @@ -0,0 +1 @@ +datastore: activedatastoreactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-complete.svg b/ckanext/xloader/public/static/badges/en/datastore-complete.svg new file mode 100644 index 00000000..7cbfd824 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-complete.svg @@ -0,0 +1 @@ +datastore: completedatastorecomplete \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-error.svg b/ckanext/xloader/public/static/badges/en/datastore-error.svg new file mode 100644 index 00000000..fe74ebe3 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-error.svg @@ -0,0 +1 @@ +datastore: errordatastoreerror \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-inactive.svg b/ckanext/xloader/public/static/badges/en/datastore-inactive.svg new file mode 100644 index 00000000..5de623d0 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-inactive.svg @@ -0,0 +1 @@ +datastore: inactivedatastoreinactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-pending.svg b/ckanext/xloader/public/static/badges/en/datastore-pending.svg new file mode 100644 index 00000000..49867a51 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-pending.svg @@ -0,0 +1 @@ +datastore: pendingdatastorepending \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-running.svg b/ckanext/xloader/public/static/badges/en/datastore-running.svg new file mode 100644 index 00000000..ab3cce1e --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-running.svg @@ -0,0 +1 @@ +datastore: runningdatastorerunning \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-unknown.svg b/ckanext/xloader/public/static/badges/en/datastore-unknown.svg new file mode 100644 index 00000000..a190db75 --- /dev/null +++ b/ckanext/xloader/public/static/badges/en/datastore-unknown.svg @@ -0,0 +1 @@ +datastore: unknowndatastoreunknown \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-active.svg b/ckanext/xloader/public/static/badges/fr/datastore-active.svg new file mode 100644 index 00000000..4a1d1ce9 --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-active.svg @@ -0,0 +1 @@ +datastore: activedatastoreactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-complete.svg b/ckanext/xloader/public/static/badges/fr/datastore-complete.svg new file mode 100644 index 00000000..f0e226d4 --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-complete.svg @@ -0,0 +1 @@ +datastore: complètedatastorecomplète \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-error.svg b/ckanext/xloader/public/static/badges/fr/datastore-error.svg new file mode 100644 index 00000000..48f14fb6 --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-error.svg @@ -0,0 +1 @@ +datastore: erreurdatastoreerreur \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg b/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg new file mode 100644 index 00000000..5de623d0 --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg @@ -0,0 +1 @@ +datastore: inactivedatastoreinactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-pending.svg b/ckanext/xloader/public/static/badges/fr/datastore-pending.svg new file mode 100644 index 00000000..29acb160 --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-pending.svg @@ -0,0 +1 @@ +datastore: en attentedatastoreen attente \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-running.svg b/ckanext/xloader/public/static/badges/fr/datastore-running.svg new file mode 100644 index 00000000..230db15f --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-running.svg @@ -0,0 +1 @@ +datastore: en cours d'exécutiondatastoreen cours d'exécution \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg b/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg new file mode 100644 index 00000000..91f4285f --- /dev/null +++ b/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg @@ -0,0 +1 @@ +datastore: inconnuedatastoreinconnue \ No newline at end of file diff --git a/ckanext/xloader/templates/package/resource_read.html b/ckanext/xloader/templates/package/resource_read.html index 3ab1476e..09183a3f 100644 --- a/ckanext/xloader/templates/package/resource_read.html +++ b/ckanext/xloader/templates/package/resource_read.html @@ -1,5 +1,13 @@ {% ckan_extends %} +{% block resource_read_url %} + {% set badge = h.xloader_badge(res) %} + {% if badge %} + {{ badge }}

+ {% endif %} + {{ super() }} +{% endblock %} + {% block action_manage_inner %} {{ super() }} {% if h.is_resource_supported_by_xloader(res) %} diff --git a/ckanext/xloader/templates/package/snippets/resource_info.html b/ckanext/xloader/templates/package/snippets/resource_info.html new file mode 100644 index 00000000..2bdea4d3 --- /dev/null +++ b/ckanext/xloader/templates/package/snippets/resource_info.html @@ -0,0 +1,6 @@ +{% ckan_extends %} + +{% block resource_info %} + {{ super() }} + {{ h.xloader_badge(res) }} +{% endblock %} diff --git a/ckanext/xloader/templates/package/snippets/resource_item.html b/ckanext/xloader/templates/package/snippets/resource_item.html index 70bf99c4..8226bd1f 100644 --- a/ckanext/xloader/templates/package/snippets/resource_item.html +++ b/ckanext/xloader/templates/package/snippets/resource_item.html @@ -13,3 +13,8 @@ {% endif %} {{ super() }} {% endblock %} + +{% block resource_item_title %} + {{ super() }} + {{ h.xloader_badge(res) }} +{% endblock %} From e7eee6d923f9a7f1caebcf189a3790eff6f00db5 Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Fri, 9 Aug 2024 14:21:05 +0000 Subject: [PATCH 02/12] fix(logic): reverse debug logic; - Reverse debug badge logic. --- ckanext/xloader/helpers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ckanext/xloader/helpers.py b/ckanext/xloader/helpers.py index 59de42d0..864d0731 100644 --- a/ckanext/xloader/helpers.py +++ b/ckanext/xloader/helpers.py @@ -86,17 +86,19 @@ def xloader_badge(resource): status = 'unknown' messages = { + # Default messages 'pending': toolkit._('Data awaiting load to DataStore'), 'running': toolkit._('Loading data into DataStore'), - 'complete': toolkit._('Data loaded into DataStore'), 'error': toolkit._('Failed to load data into DataStore'), + # Debug messages + 'complete': toolkit._('Data loaded into DataStore'), 'active': toolkit._('Data available in DataStore'), 'inactive': toolkit._('Resource not active in DataStore'), 'unknown': toolkit._('DataStore status unknown'), } - debug_level_statuses = ['complete', 'active', 'inactive', 'unknown'] + basic_statuses = ['pending', 'running', 'error'] - if status in debug_level_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)): + if status not in basic_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)): return '' badge_url = toolkit.h.url_for_static('/static/badges/{lang}/datastore-{status}.svg'.format( From 8535a187b84b04aab5023e4598287f47c1558967 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Tue, 15 Oct 2024 14:17:12 +1000 Subject: [PATCH 03/12] Pin setuptools only for 2.9 to allow CICD to pass --- .github/workflows/test.yml | 2 ++ README.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 92a95972..a65aed65 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,6 +53,8 @@ jobs: steps: - uses: actions/checkout@v4 + - if: ${{ matrix.ckan-version == 2.9 }} + run: pip install "setuptools>=44.1.0,<71" - name: Install requirements run: | pip install -r requirements.txt diff --git a/README.rst b/README.rst index aed6f4b2..5a4ca6c0 100644 --- a/README.rst +++ b/README.rst @@ -128,7 +128,7 @@ CKAN version Compatibility =============== ============= 2.7 no longer supported (last supported version: 0.12.2) 2.8 no longer supported (last supported version: 0.12.2) -2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2)) +2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2)), Must: ``pip install "setuptools>=44.1.0,<71"`` 2.10 yes 2.11 yes =============== ============= From 71e4a9ca51a73a80c34998bfefa1b66f335e3486 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Wed, 16 Oct 2024 07:14:01 +1000 Subject: [PATCH 04/12] feat: Add pypi cicd publish via github action via environment controls Uses GitHub CICD Provider Auth for publishing: project_name: ckanext-xloader owner: ckan repository: ckanext-xloader workflow_filename: publish.yml environment: pypi provider: github --- .github/workflows/publish.yml | 161 ++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..9591e461 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,161 @@ +--- +name: Publish to pypi +on: + push: + #On versioned releases + tags: + - v*.*.* + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + inputs: + force: + type: choice + description: Retry Publish Version + options: + - No + - Yes + environment: + description: 'Deployment environment' + required: true + default: 'pypi' + type: choice + options: + - pypi + - testpypi + dryRun: + description: 'Dry Run deployment (set to false to deploy)' + required: true + type: boolean + default: true + + + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: Install requirements + run: pip install flake8 pycodestyle + - name: Check syntax + run: flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics --extend-exclude ckan + + test: + needs: lint + strategy: + matrix: + ckan-version: ["2.11", "2.10", 2.9] + fail-fast: false + + name: CKAN ${{ matrix.ckan-version }} + runs-on: ubuntu-latest + container: + image: ckan/ckan-dev:${{ matrix.ckan-version }} + services: + solr: + image: ckan/ckan-solr:${{ matrix.ckan-version }}-solr9 + postgres: + image: ckan/ckan-postgres-dev:${{ matrix.ckan-version }} + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + redis: + image: redis:3 + env: + CKAN_SQLALCHEMY_URL: postgresql://ckan_default:pass@postgres/ckan_test + CKAN_DATASTORE_WRITE_URL: postgresql://datastore_write:pass@postgres/datastore_test + CKAN_DATASTORE_READ_URL: postgresql://datastore_read:pass@postgres/datastore_test + CKAN_SOLR_URL: http://solr:8983/solr/ckan + CKAN_REDIS_URL: redis://redis:6379/1 + + steps: + - uses: actions/checkout@v4 + - if: ${{ matrix.ckan-version == 2.9 }} + run: pip install "setuptools>=44.1.0,<71" + - name: Install requirements + run: | + pip install -r requirements.txt + pip install -r dev-requirements.txt + pip install -e . + pip install -U requests[security] + # Replace default path to CKAN core config file with the one on the container + sed -i -e 's/use = config:.*/use = config:\/srv\/app\/src\/ckan\/test-core.ini/' test.ini + - name: Setup extension (CKAN >= 2.9) + run: | + ckan -c test.ini db init + - name: Run tests + run: pytest --ckan-ini=test.ini --cov=ckanext.xloader --disable-warnings ckanext/xloader/tests + + publish: + needs: test + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + name: Publish ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} to ${{ steps.version.outputs.url }} + environment: + name: ${{ github.event.inputs.environment }} + url: ${{ steps.version.outputs.url }} + concurrency: + group: ${{ github.event.inputs.environment }}-deployment + cancel-in-progress: false + steps: + + - name: Get Git Tag and set url from environment + id: version + run: | + #!/bin/bash + + ENVIRONMENT=$1 + TAG_VALUE=${GITHUB_REF/refs\/tags\//} + echo "version=${TAG_VALUE}" >> $GITHUB_ENV + + # Extract the repository name (minus the owner/org) + repo_name=$(basename $GITHUB_REPOSITORY) + echo "repo_name=${repo_name}" >> $GITHUB_OUTPUT + + if [ "$ENVIRONMENT" == "pypi" ]; then + url="https://pypi.com/p/$repo_name" + elif [ "$1" == "testpypi" ]; then + url="https://test.pypi.com/p/$repo_name" + else + url="" + fi + + echo "url=${url}" >> $GITHUB_OUTPUT + + - name: Checkout repository + uses: actions/checkout@v4 + - name: Build package ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} + run: | + pip install build + pip install twine + python -m build + - name: Publish package distributions to PyPI + if: ${{ startsWith(github.ref, 'refs/tags') && (github.event.inputs.environment == 'pypi' || github.event.inputs.environment == 'publish' ) && github.event.inputs.dryRun == 'false'}} + uses: pypa/gh-action-pypi-publish@release/v1 + with: +# skip-existing: true +# verbose: true +# print-hash: true + - name: Test Publish package distributions to PyPI + if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.environment == 'testpypi' && github.event.inputs.dryRun == 'false'}} + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ +# skip-existing: true +# verbose: true +# print-hash: true + - name: Summary output + if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.dryRun == 'false'}} + run: + echo "Published ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} to ${{ steps.version.outputs.url }}" >> $GITHUB_STEP_SUMMARY + - name: (TEST RUN) Test Publish package distributions to PyPI + if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.dryRun == 'true'}} + run: + echo "Dry run deployment, did not publish" >> $GITHUB_STEP_SUMMARY From 140ee9ea468fd67ec0296b0766eeb2ef32adc773 Mon Sep 17 00:00:00 2001 From: william dutton Date: Wed, 16 Oct 2024 10:23:59 +1000 Subject: [PATCH 05/12] fix: cicd yaml spacing --- .github/workflows/publish.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9591e461..3f5238a3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,11 +22,11 @@ on: options: - pypi - testpypi - dryRun: - description: 'Dry Run deployment (set to false to deploy)' - required: true - type: boolean - default: true + dryRun: + description: 'Dry Run deployment (set to false to deploy)' + required: true + type: boolean + default: true From a8bfda1b70567b19de12bde48c483a21da894f93 Mon Sep 17 00:00:00 2001 From: william dutton Date: Wed, 16 Oct 2024 10:43:16 +1000 Subject: [PATCH 06/12] fix: cicd yaml typo --- .github/workflows/publish.yml | 52 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3f5238a3..917856a5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,19 +14,19 @@ on: options: - No - Yes - environment: - description: 'Deployment environment' - required: true - default: 'pypi' - type: choice - options: - - pypi - - testpypi - dryRun: - description: 'Dry Run deployment (set to false to deploy)' - required: true - type: boolean - default: true + environment: + description: 'Deployment environment' + required: true + default: 'pypi' + type: choice + options: + - pypi + - testpypi + dryRun: + description: 'Dry Run deployment (set to false to deploy)' + required: true + type: boolean + default: true @@ -97,15 +97,16 @@ jobs: needs: test permissions: id-token: write # IMPORTANT: this permission is mandatory for trusted publishing - name: Publish ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} to ${{ steps.version.outputs.url }} + name: Publish Package + runs-on: ubuntu-latest environment: name: ${{ github.event.inputs.environment }} url: ${{ steps.version.outputs.url }} concurrency: group: ${{ github.event.inputs.environment }}-deployment cancel-in-progress: false - steps: + steps: - name: Get Git Tag and set url from environment id: version run: | @@ -116,13 +117,13 @@ jobs: echo "version=${TAG_VALUE}" >> $GITHUB_ENV # Extract the repository name (minus the owner/org) - repo_name=$(basename $GITHUB_REPOSITORY) - echo "repo_name=${repo_name}" >> $GITHUB_OUTPUT + reponame=$(basename $GITHUB_REPOSITORY) + echo "reponame=${reponame}" >> $GITHUB_OUTPUT if [ "$ENVIRONMENT" == "pypi" ]; then - url="https://pypi.com/p/$repo_name" + url="https://pypi.com/p/$reponame" elif [ "$1" == "testpypi" ]; then - url="https://test.pypi.com/p/$repo_name" + url="https://test.pypi.com/p/$reponame" else url="" fi @@ -131,20 +132,20 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Build package ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} + - name: Build package ${{ steps.version.outputs.reponame }} @ ${{ steps.version.outputs.version }} run: | pip install build pip install twine python -m build - name: Publish package distributions to PyPI - if: ${{ startsWith(github.ref, 'refs/tags') && (github.event.inputs.environment == 'pypi' || github.event.inputs.environment == 'publish' ) && github.event.inputs.dryRun == 'false'}} + if: ${{ startsWith(github.ref, 'refs/tags') && (github.event.inputs.environment == 'pypi' || github.event.inputs.environment == 'publish' ) && github.event.inputs.dryRun != 'true'}} uses: pypa/gh-action-pypi-publish@release/v1 - with: +# with: # skip-existing: true # verbose: true # print-hash: true - name: Test Publish package distributions to PyPI - if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.environment == 'testpypi' && github.event.inputs.dryRun == 'false'}} + if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.environment == 'testpypi' && github.event.inputs.dryRun == 'true' }} uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ @@ -152,10 +153,11 @@ jobs: # verbose: true # print-hash: true - name: Summary output - if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.dryRun == 'false'}} + if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.dryRun != 'true' }} run: echo "Published ${{ steps.version.outputs.repo_name }} @ ${{ steps.version.outputs.version }} to ${{ steps.version.outputs.url }}" >> $GITHUB_STEP_SUMMARY + - name: (TEST RUN) Test Publish package distributions to PyPI - if: ${{ startsWith(github.ref, 'refs/tags') && github.event.inputs.dryRun == 'true'}} + if: ${{ github.event.inputs.dryRun == 'true' }} run: echo "Dry run deployment, did not publish" >> $GITHUB_STEP_SUMMARY From 21fa4d4f4444082c47b0f78673840c273251bee7 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Wed, 16 Oct 2024 13:18:18 +1000 Subject: [PATCH 07/12] chore: update changelog/bump version 1.1.1 --- CHANGELOG | 10 ++++++++++ setup.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ec8d2382..9159bc03 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,13 @@ +1.1.0 2024-10-16 +================ + +Fixes: +* feat: Add pypi cicd publish via github action via environment controls by @duttonw in https://github.com/ckan/ckanext-xloader/pull/228 + + +**Full Changelog**: https://github.com/ckan/ckanext-xloader/compare/1.1.0...1.1.1 + + 1.1.0 2024-10-15 ================ diff --git a/setup.py b/setup.py index 1c0dd931..b3c7ec68 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # http://packaging.python.org/en/latest/tutorial.html#version - version='1.1.0', + version='1.1.1', description='Express Loader - quickly load data into CKAN DataStore''', long_description=long_description, From bf40ecde34a4dc316850dd128b097a267bb2eb83 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Tue, 15 Oct 2024 14:17:12 +1000 Subject: [PATCH 08/12] Pin setuptools only for 2.9 to allow CICD to pass --- .github/workflows/test.yml | 2 ++ README.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 92a95972..a65aed65 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,6 +53,8 @@ jobs: steps: - uses: actions/checkout@v4 + - if: ${{ matrix.ckan-version == 2.9 }} + run: pip install "setuptools>=44.1.0,<71" - name: Install requirements run: | pip install -r requirements.txt diff --git a/README.rst b/README.rst index aed6f4b2..5a4ca6c0 100644 --- a/README.rst +++ b/README.rst @@ -128,7 +128,7 @@ CKAN version Compatibility =============== ============= 2.7 no longer supported (last supported version: 0.12.2) 2.8 no longer supported (last supported version: 0.12.2) -2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2)) +2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2)), Must: ``pip install "setuptools>=44.1.0,<71"`` 2.10 yes 2.11 yes =============== ============= From 593a244af3bddfad335f4dca05bcfed71d4ce32a Mon Sep 17 00:00:00 2001 From: william dutton Date: Tue, 15 Oct 2024 16:54:57 +1000 Subject: [PATCH 09/12] doc: Add additional ckan config options --- README.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.rst b/README.rst index 5a4ca6c0..4ec2e11b 100644 --- a/README.rst +++ b/README.rst @@ -203,6 +203,20 @@ expect European (day-first) dates, you could add to ``postgresql.conf``: datestyle=ISO,DMY +External Database credentials for datastore + + ``ckanext.xloader.jobs_db.uri = postgresql://ckan_default:pass@localhost/ckan_default`` + +API Key requires for xloader interaction CKAN 2.10 onwards, to generate ``TOKEN=ckan -c /etc/ckan/default/production.ini user token add $ACCOUNT xloader | tail -1 | tr -d '[:space:]')`` + + ``ckanext.xloader.api_token = `` + +Badge notification on what xloader is doing + + ``ckanext.xloader.show_badges = True|False (default True)`` + + ``ckanext.xloader.debug_badges = True|False (default False)`` + ------------------------ Developer installation ------------------------ From 0bd9c66c5caf3841818f12dc7a13b5b79ac020d7 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Thu, 24 Oct 2024 14:35:41 +1000 Subject: [PATCH 10/12] fix: Move from static image to css badge which allows i18n more easily --- ckanext/xloader/helpers.py | 26 ++++++--- ckanext/xloader/plugin.py | 2 +- .../static/badges/en/datastore-active.svg | 1 - .../static/badges/en/datastore-complete.svg | 1 - .../static/badges/en/datastore-error.svg | 1 - .../static/badges/en/datastore-inactive.svg | 1 - .../static/badges/en/datastore-pending.svg | 1 - .../static/badges/en/datastore-running.svg | 1 - .../static/badges/en/datastore-unknown.svg | 1 - .../static/badges/fr/datastore-active.svg | 1 - .../static/badges/fr/datastore-complete.svg | 1 - .../static/badges/fr/datastore-error.svg | 1 - .../static/badges/fr/datastore-inactive.svg | 1 - .../static/badges/fr/datastore-pending.svg | 1 - .../static/badges/fr/datastore-running.svg | 1 - .../static/badges/fr/datastore-unknown.svg | 1 - ckanext/xloader/webassets/css/xloader.css | 56 +++++++++++++++++++ ckanext/xloader/webassets/webassets.yml | 4 ++ 18 files changed, 78 insertions(+), 24 deletions(-) delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-active.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-complete.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-error.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-inactive.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-pending.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-running.svg delete mode 100644 ckanext/xloader/public/static/badges/en/datastore-unknown.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-active.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-complete.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-error.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-inactive.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-pending.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-running.svg delete mode 100644 ckanext/xloader/public/static/badges/fr/datastore-unknown.svg create mode 100644 ckanext/xloader/webassets/css/xloader.css create mode 100644 ckanext/xloader/webassets/webassets.yml diff --git a/ckanext/xloader/helpers.py b/ckanext/xloader/helpers.py index 864d0731..a08d5b66 100644 --- a/ckanext/xloader/helpers.py +++ b/ckanext/xloader/helpers.py @@ -101,9 +101,6 @@ def xloader_badge(resource): if status not in basic_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)): return '' - badge_url = toolkit.h.url_for_static('/static/badges/{lang}/datastore-{status}.svg'.format( - lang=toolkit.h.lang(), status=status)) - title = toolkit.h.render_datetime(xloader_job.get('last_updated'), with_hours=True) \ if xloader_job.get('last_updated') else '' @@ -113,13 +110,24 @@ def xloader_badge(resource): id=resource.get('package_id'), resource_id=resource.get('id')) - return Markup(u'{alt}'.format( + return Markup(u''' + + {prefix} + {status_title} + '''.format( pusher_url=pusher_url, - badge_url=badge_url, - alt=html_escape(messages[status], quote=True), + prefix=toolkit._('datastore'), + status=status, + status_title=html_escape(messages[status], quote=True), title=html_escape(title, quote=True))) except toolkit.NotAuthorized: - return Markup(u'{alt}'.format( - badge_url=badge_url, - alt=html_escape(messages[status], quote=True), + return Markup(u''' + + {prefix} + {status_title} + + '''.format( + prefix=toolkit._('datastore'), + status=status, + status_title=html_escape(messages[status], quote=True), title=html_escape(title, quote=True))) diff --git a/ckanext/xloader/plugin.py b/ckanext/xloader/plugin.py index aef1fd98..07af8db7 100644 --- a/ckanext/xloader/plugin.py +++ b/ckanext/xloader/plugin.py @@ -51,7 +51,7 @@ def get_blueprint(self): def update_config(self, config): toolkit.add_template_directory(config, 'templates') - toolkit.add_public_directory(config, 'public') + toolkit.add_resource(u'webassets', 'ckanext-xloader') # IConfigurable diff --git a/ckanext/xloader/public/static/badges/en/datastore-active.svg b/ckanext/xloader/public/static/badges/en/datastore-active.svg deleted file mode 100644 index 4a1d1ce9..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-active.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: activedatastoreactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-complete.svg b/ckanext/xloader/public/static/badges/en/datastore-complete.svg deleted file mode 100644 index 7cbfd824..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-complete.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: completedatastorecomplete \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-error.svg b/ckanext/xloader/public/static/badges/en/datastore-error.svg deleted file mode 100644 index fe74ebe3..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-error.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: errordatastoreerror \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-inactive.svg b/ckanext/xloader/public/static/badges/en/datastore-inactive.svg deleted file mode 100644 index 5de623d0..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-inactive.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: inactivedatastoreinactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-pending.svg b/ckanext/xloader/public/static/badges/en/datastore-pending.svg deleted file mode 100644 index 49867a51..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-pending.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: pendingdatastorepending \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-running.svg b/ckanext/xloader/public/static/badges/en/datastore-running.svg deleted file mode 100644 index ab3cce1e..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-running.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: runningdatastorerunning \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/en/datastore-unknown.svg b/ckanext/xloader/public/static/badges/en/datastore-unknown.svg deleted file mode 100644 index a190db75..00000000 --- a/ckanext/xloader/public/static/badges/en/datastore-unknown.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: unknowndatastoreunknown \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-active.svg b/ckanext/xloader/public/static/badges/fr/datastore-active.svg deleted file mode 100644 index 4a1d1ce9..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-active.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: activedatastoreactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-complete.svg b/ckanext/xloader/public/static/badges/fr/datastore-complete.svg deleted file mode 100644 index f0e226d4..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-complete.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: complètedatastorecomplète \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-error.svg b/ckanext/xloader/public/static/badges/fr/datastore-error.svg deleted file mode 100644 index 48f14fb6..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-error.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: erreurdatastoreerreur \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg b/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg deleted file mode 100644 index 5de623d0..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-inactive.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: inactivedatastoreinactive \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-pending.svg b/ckanext/xloader/public/static/badges/fr/datastore-pending.svg deleted file mode 100644 index 29acb160..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-pending.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: en attentedatastoreen attente \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-running.svg b/ckanext/xloader/public/static/badges/fr/datastore-running.svg deleted file mode 100644 index 230db15f..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-running.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: en cours d'exécutiondatastoreen cours d'exécution \ No newline at end of file diff --git a/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg b/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg deleted file mode 100644 index 91f4285f..00000000 --- a/ckanext/xloader/public/static/badges/fr/datastore-unknown.svg +++ /dev/null @@ -1 +0,0 @@ -datastore: inconnuedatastoreinconnue \ No newline at end of file diff --git a/ckanext/xloader/webassets/css/xloader.css b/ckanext/xloader/webassets/css/xloader.css new file mode 100644 index 00000000..591b098f --- /dev/null +++ b/ckanext/xloader/webassets/css/xloader.css @@ -0,0 +1,56 @@ +.loader-badge { + margin-left: 10px; + background: #555; + color: #fff; + border-radius: 3px; + display: inline-block; + font-size: 14px; + vertical-align: middle; + font-weight: 400; + line-height: 1.2; +} + +.loader-badge:hover, +.loader-badge:focus { + color: #fff; +} + +.prefix, +.status { + display: inline-block; + padding: 2px 6px; +} + +.loader-badge .status { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +.loader-badge .status.active { + background: #97C50F; +} + +.loader-badge .status.complete { + background: #1081C2; +} + +.loader-badge .status.error { + background: #D9634D; +} + +.loader-badge .status.inactive { + background: #F27E3F; +} + +.loader-badge .status.pending { + background: #9B9B9B; +} + +.loader-badge .status.running { + background: #D8B124; +} + +.loader-badge .status.unknown { + background: #9D9D9D; +} + diff --git a/ckanext/xloader/webassets/webassets.yml b/ckanext/xloader/webassets/webassets.yml new file mode 100644 index 00000000..5beaf6b6 --- /dev/null +++ b/ckanext/xloader/webassets/webassets.yml @@ -0,0 +1,4 @@ +main-css: + output: ckanext-xloader/%(version)s_xloader.css + contents: + - css/xloader.css From f0f39faa60f952832f30a1d664fd3e7207efebea Mon Sep 17 00:00:00 2001 From: William Dutton Date: Fri, 25 Oct 2024 06:40:07 +1000 Subject: [PATCH 11/12] fix: webassets not loaded on snippets, correct display vs hover title, remove display bug from badge display --- ckanext/xloader/helpers.py | 36 +++++++++++++------ .../templates/package/resource_read.html | 3 ++ .../package/snippets/resource_info.html | 2 ++ .../package/snippets/resource_item.html | 2 ++ ckanext/xloader/webassets/css/xloader.css | 1 + 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ckanext/xloader/helpers.py b/ckanext/xloader/helpers.py index a08d5b66..25e6ba83 100644 --- a/ckanext/xloader/helpers.py +++ b/ckanext/xloader/helpers.py @@ -85,7 +85,19 @@ def xloader_badge(resource): # we do not know what the status is status = 'unknown' - messages = { + status_translations = { + # Default messages + 'pending': toolkit._('Pending'), + 'running': toolkit._('Running'), + 'error': toolkit._('Error'), + # Debug messages + 'complete': toolkit._('Complete'), + 'active': toolkit._('Active'), + 'inactive': toolkit._('Inactive'), + 'unknown': toolkit._('Unknown'), + } + + status_descriptions = { # Default messages 'pending': toolkit._('Data awaiting load to DataStore'), 'running': toolkit._('Loading data into DataStore'), @@ -101,8 +113,8 @@ def xloader_badge(resource): if status not in basic_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)): return '' - title = toolkit.h.render_datetime(xloader_job.get('last_updated'), with_hours=True) \ - if xloader_job.get('last_updated') else '' + last_updated = toolkit.h.render_datetime(xloader_job.get('last_updated'), with_hours=True) \ + if xloader_job.get('last_updated') else toolkit._('Last Updated Not Available') try: toolkit.check_access('resource_update', {'user': toolkit.g.user}, {'id': resource.get('id')}) @@ -111,23 +123,25 @@ def xloader_badge(resource): resource_id=resource.get('id')) return Markup(u''' - + {prefix} - {status_title} + {status_display} '''.format( pusher_url=pusher_url, prefix=toolkit._('datastore'), status=status, - status_title=html_escape(messages[status], quote=True), - title=html_escape(title, quote=True))) + status_display=html_escape(status_translations[status], quote=True), + status_description=html_escape(status_descriptions[status], quote=True), + title=html_escape(last_updated, quote=True))) except toolkit.NotAuthorized: return Markup(u''' - + {prefix} - {status_title} + {status_display} '''.format( prefix=toolkit._('datastore'), status=status, - status_title=html_escape(messages[status], quote=True), - title=html_escape(title, quote=True))) + status_display=html_escape(status_translations[status], quote=True), + status_description=html_escape(status_descriptions[status], quote=True), + title=html_escape(last_updated, quote=True))) diff --git a/ckanext/xloader/templates/package/resource_read.html b/ckanext/xloader/templates/package/resource_read.html index 09183a3f..6deab846 100644 --- a/ckanext/xloader/templates/package/resource_read.html +++ b/ckanext/xloader/templates/package/resource_read.html @@ -1,5 +1,6 @@ {% ckan_extends %} + {% block resource_read_url %} {% set badge = h.xloader_badge(res) %} {% if badge %} @@ -21,3 +22,5 @@ {% endif %} {{ super() }} {% endblock %} + +{% asset 'ckanext-xloader/main-css' %} diff --git a/ckanext/xloader/templates/package/snippets/resource_info.html b/ckanext/xloader/templates/package/snippets/resource_info.html index 2bdea4d3..af371d96 100644 --- a/ckanext/xloader/templates/package/snippets/resource_info.html +++ b/ckanext/xloader/templates/package/snippets/resource_info.html @@ -4,3 +4,5 @@ {{ super() }} {{ h.xloader_badge(res) }} {% endblock %} + +{% asset 'ckanext-xloader/main-css' %} diff --git a/ckanext/xloader/templates/package/snippets/resource_item.html b/ckanext/xloader/templates/package/snippets/resource_item.html index 8226bd1f..49d8a14f 100644 --- a/ckanext/xloader/templates/package/snippets/resource_item.html +++ b/ckanext/xloader/templates/package/snippets/resource_item.html @@ -18,3 +18,5 @@ {{ super() }} {{ h.xloader_badge(res) }} {% endblock %} + +{% asset 'ckanext-xloader/main-css' %} diff --git a/ckanext/xloader/webassets/css/xloader.css b/ckanext/xloader/webassets/css/xloader.css index 591b098f..e6ad04ed 100644 --- a/ckanext/xloader/webassets/css/xloader.css +++ b/ckanext/xloader/webassets/css/xloader.css @@ -8,6 +8,7 @@ vertical-align: middle; font-weight: 400; line-height: 1.2; + text-decoration: none; } .loader-badge:hover, From 80999e4b2831cdb3bf722c684bf983583f565912 Mon Sep 17 00:00:00 2001 From: William Dutton Date: Fri, 25 Oct 2024 08:50:29 +1000 Subject: [PATCH 12/12] fix: asset inclusion must be in the block being rendered, not on the outer that is not rendered --- ckanext/xloader/templates/package/resource_read.html | 3 ++- .../xloader/templates/package/snippets/resource_info.html | 3 +-- .../xloader/templates/package/snippets/resource_item.html | 3 ++- ckanext/xloader/webassets/css/xloader.css | 5 ++++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ckanext/xloader/templates/package/resource_read.html b/ckanext/xloader/templates/package/resource_read.html index 6deab846..c99dcec2 100644 --- a/ckanext/xloader/templates/package/resource_read.html +++ b/ckanext/xloader/templates/package/resource_read.html @@ -5,6 +5,7 @@ {% set badge = h.xloader_badge(res) %} {% if badge %} {{ badge }}

+ {% asset 'ckanext-xloader/main-css' %} {% endif %} {{ super() }} {% endblock %} @@ -23,4 +24,4 @@ {{ super() }} {% endblock %} -{% asset 'ckanext-xloader/main-css' %} + diff --git a/ckanext/xloader/templates/package/snippets/resource_info.html b/ckanext/xloader/templates/package/snippets/resource_info.html index af371d96..cfe00c58 100644 --- a/ckanext/xloader/templates/package/snippets/resource_info.html +++ b/ckanext/xloader/templates/package/snippets/resource_info.html @@ -3,6 +3,5 @@ {% block resource_info %} {{ super() }} {{ h.xloader_badge(res) }} + {% asset 'ckanext-xloader/main-css' %} {% endblock %} - -{% asset 'ckanext-xloader/main-css' %} diff --git a/ckanext/xloader/templates/package/snippets/resource_item.html b/ckanext/xloader/templates/package/snippets/resource_item.html index 49d8a14f..6fe9efe6 100644 --- a/ckanext/xloader/templates/package/snippets/resource_item.html +++ b/ckanext/xloader/templates/package/snippets/resource_item.html @@ -17,6 +17,7 @@ {% block resource_item_title %} {{ super() }} {{ h.xloader_badge(res) }} + {% asset 'ckanext-xloader/main-css' %} {% endblock %} -{% asset 'ckanext-xloader/main-css' %} + diff --git a/ckanext/xloader/webassets/css/xloader.css b/ckanext/xloader/webassets/css/xloader.css index e6ad04ed..f0cc39d4 100644 --- a/ckanext/xloader/webassets/css/xloader.css +++ b/ckanext/xloader/webassets/css/xloader.css @@ -8,7 +8,10 @@ vertical-align: middle; font-weight: 400; line-height: 1.2; - text-decoration: none; +} + +a.loader-badge { + text-decoration: none; } .loader-badge:hover,