├── .editorconfig ├── .github ├── .stale.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── release-drafter.yml └── workflows │ ├── greetings.yml │ └── python-publish.yml ├── .gitignore ├── .pre-commit-config.yaml ├── MANIFEST.in ├── README.md ├── assets ├── logo.png └── term.gif ├── dev_requirements.txt ├── docs ├── Makefile ├── _static │ └── custom.css ├── conf.py ├── docs.rst └── index.rst ├── pytest.ini ├── pythoncms ├── .env_demo ├── .test.prod.env ├── CHANGELOG.md ├── __init__.py ├── app.py ├── autoapp.py.example ├── cli.py ├── config.py ├── config_demo.json ├── conftest.py ├── init.py ├── manage.py ├── migrations │ ├── README │ ├── alembic.ini │ ├── env.py │ ├── script.py.mako │ └── versions │ │ └── 0fbf6b2e734f_.py ├── modules │ ├── __init__.py │ ├── contact │ │ ├── forms.py │ │ ├── global.py │ │ ├── info.json │ │ ├── models.py │ │ ├── templates │ │ │ └── contact │ │ │ │ ├── blocks │ │ │ │ └── sidebar.html │ │ │ │ ├── contact_form.html │ │ │ │ └── dashboard.html │ │ ├── tests │ │ │ └── test_contact.py │ │ └── view.py │ ├── resource │ │ ├── forms.py │ │ ├── info.json │ │ ├── models.py │ │ ├── templates │ │ │ └── resource │ │ │ │ └── blocks │ │ │ │ └── sidebar.html │ │ └── view.py │ └── www │ │ ├── forms.py │ │ ├── global.py │ │ ├── info.json │ │ ├── models.py │ │ ├── templates │ │ └── www │ │ │ ├── blocks │ │ │ └── sidebar.html │ │ │ └── index.html │ │ └── view.py ├── shopyo_admin.py ├── static │ ├── bootstrap-grid.min.css │ ├── bootstrap-reboot.min.css │ ├── bootstrap.bundle.min.js │ ├── bootstrap.min.css │ ├── box.svg │ ├── css │ │ ├── b4vtabs.min.css │ │ └── simple_sidebar.css │ ├── default │ │ ├── default_product.jpg │ │ └── default_subcategory.jpg │ ├── favicon.ico │ ├── fontawesome │ │ ├── LICENSE.txt │ │ ├── css │ │ │ ├── all.css │ │ │ ├── all.min.css │ │ │ ├── brands.css │ │ │ ├── brands.min.css │ │ │ ├── fontawesome.css │ │ │ ├── fontawesome.min.css │ │ │ ├── regular.css │ │ │ ├── regular.min.css │ │ │ ├── solid.css │ │ │ ├── solid.min.css │ │ │ ├── svg-with-js.css │ │ │ ├── svg-with-js.min.css │ │ │ ├── v4-shims.css │ │ │ └── v4-shims.min.css │ │ └── webfonts │ │ │ ├── fa-brands-400.eot │ │ │ ├── fa-brands-400.svg │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-brands-400.woff │ │ │ ├── fa-brands-400.woff2 │ │ │ ├── fa-regular-400.eot │ │ │ ├── fa-regular-400.svg │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-regular-400.woff │ │ │ ├── fa-regular-400.woff2 │ │ │ ├── fa-solid-900.eot │ │ │ ├── fa-solid-900.svg │ │ │ ├── fa-solid-900.ttf │ │ │ ├── fa-solid-900.woff │ │ │ └── fa-solid-900.woff2 │ ├── jquery_3.2.1.min.js │ ├── js │ │ └── python.js │ ├── logo.png │ ├── logo.svg │ ├── shopyo.png │ ├── shopyo.svg │ └── themes │ │ ├── back │ │ ├── sbadmin │ │ │ ├── .gitignore │ │ │ ├── 404.html │ │ │ ├── LICENSE │ │ │ ├── authbase.html │ │ │ ├── base.html │ │ │ ├── css │ │ │ │ ├── sb-admin-2.css │ │ │ │ └── sb-admin-2.min.css │ │ │ ├── index.html │ │ │ ├── info.json │ │ │ ├── js │ │ │ │ ├── demo │ │ │ │ │ ├── chart-area-demo.js │ │ │ │ │ ├── chart-bar-demo.js │ │ │ │ │ ├── chart-pie-demo.js │ │ │ │ │ └── datatables-demo.js │ │ │ │ ├── sb-admin-2.js │ │ │ │ └── sb-admin-2.min.js │ │ │ ├── login.html │ │ │ ├── register.html │ │ │ ├── unconfirmed.html │ │ │ └── vendor │ │ │ │ ├── bootstrap │ │ │ │ └── js │ │ │ │ │ ├── bootstrap.bundle.js │ │ │ │ │ ├── bootstrap.bundle.js.map │ │ │ │ │ ├── bootstrap.bundle.min.js │ │ │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ │ │ ├── bootstrap.js │ │ │ │ │ ├── bootstrap.js.map │ │ │ │ │ ├── bootstrap.min.js │ │ │ │ │ └── bootstrap.min.js.map │ │ │ │ ├── chart.js │ │ │ │ ├── Chart.bundle.js │ │ │ │ ├── Chart.bundle.min.js │ │ │ │ ├── Chart.js │ │ │ │ └── Chart.min.js │ │ │ │ ├── datatables │ │ │ │ ├── dataTables.bootstrap4.css │ │ │ │ ├── dataTables.bootstrap4.js │ │ │ │ ├── dataTables.bootstrap4.min.css │ │ │ │ ├── dataTables.bootstrap4.min.js │ │ │ │ ├── jquery.dataTables.js │ │ │ │ └── jquery.dataTables.min.js │ │ │ │ ├── jquery-easing │ │ │ │ ├── jquery.easing.compatibility.js │ │ │ │ ├── jquery.easing.js │ │ │ │ └── jquery.easing.min.js │ │ │ │ └── jquery │ │ │ │ ├── jquery.js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── jquery.min.map │ │ │ │ ├── jquery.slim.js │ │ │ │ ├── jquery.slim.min.js │ │ │ │ └── jquery.slim.min.map │ │ └── sneat │ │ │ ├── assets │ │ │ ├── css │ │ │ │ └── demo.css │ │ │ ├── js │ │ │ │ ├── config.js │ │ │ │ ├── dashboards-analytics.js │ │ │ │ ├── extended-ui-perfect-scrollbar.js │ │ │ │ ├── form-basic-inputs.js │ │ │ │ ├── main.js │ │ │ │ ├── pages-account-settings-account.js │ │ │ │ ├── ui-modals.js │ │ │ │ ├── ui-popover.js │ │ │ │ └── ui-toasts.js │ │ │ └── vendor │ │ │ │ ├── css │ │ │ │ ├── core.css │ │ │ │ ├── pages │ │ │ │ │ ├── page-account-settings.css │ │ │ │ │ ├── page-auth.css │ │ │ │ │ ├── page-icons.css │ │ │ │ │ └── page-misc.css │ │ │ │ └── theme-default.css │ │ │ │ ├── fonts │ │ │ │ ├── boxicons.css │ │ │ │ └── boxicons │ │ │ │ │ ├── boxicons.eot │ │ │ │ │ ├── boxicons.svg │ │ │ │ │ ├── boxicons.ttf │ │ │ │ │ ├── boxicons.woff │ │ │ │ │ └── boxicons.woff2 │ │ │ │ ├── js │ │ │ │ ├── bootstrap.js │ │ │ │ ├── helpers.js │ │ │ │ └── menu.js │ │ │ │ └── libs │ │ │ │ ├── apex-charts │ │ │ │ ├── apex-charts.css │ │ │ │ └── apexcharts.js │ │ │ │ ├── highlight │ │ │ │ ├── highlight-github.css │ │ │ │ ├── highlight.css │ │ │ │ └── highlight.js │ │ │ │ ├── jquery │ │ │ │ └── jquery.js │ │ │ │ ├── masonry │ │ │ │ └── masonry.js │ │ │ │ ├── perfect-scrollbar │ │ │ │ ├── perfect-scrollbar.css │ │ │ │ └── perfect-scrollbar.js │ │ │ │ └── popper │ │ │ │ └── popper.js │ │ │ ├── authbase.html │ │ │ ├── base.html │ │ │ ├── index.html │ │ │ ├── info.json │ │ │ ├── login.html │ │ │ ├── register.html │ │ │ ├── sections │ │ │ ├── dashboard_elements.html │ │ │ ├── resource_end_body.html │ │ │ └── resource_head.html │ │ │ ├── styles.css │ │ │ └── unconfirmed.html │ │ └── front │ │ ├── editorial │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── assets │ │ │ ├── css │ │ │ │ ├── fontawesome-all.min.css │ │ │ │ └── main.css │ │ │ ├── js │ │ │ │ ├── breakpoints.min.js │ │ │ │ ├── browser.min.js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── main.js │ │ │ │ └── util.js │ │ │ └── sass │ │ │ │ ├── base │ │ │ │ ├── _page.scss │ │ │ │ ├── _reset.scss │ │ │ │ └── _typography.scss │ │ │ │ ├── components │ │ │ │ ├── _actions.scss │ │ │ │ ├── _box.scss │ │ │ │ ├── _button.scss │ │ │ │ ├── _contact.scss │ │ │ │ ├── _features.scss │ │ │ │ ├── _form.scss │ │ │ │ ├── _icon.scss │ │ │ │ ├── _icons.scss │ │ │ │ ├── _image.scss │ │ │ │ ├── _list.scss │ │ │ │ ├── _mini-posts.scss │ │ │ │ ├── _pagination.scss │ │ │ │ ├── _posts.scss │ │ │ │ ├── _row.scss │ │ │ │ ├── _section.scss │ │ │ │ └── _table.scss │ │ │ │ ├── layout │ │ │ │ ├── _banner.scss │ │ │ │ ├── _footer.scss │ │ │ │ ├── _header.scss │ │ │ │ ├── _main.scss │ │ │ │ ├── _menu.scss │ │ │ │ ├── _sidebar.scss │ │ │ │ └── _wrapper.scss │ │ │ │ ├── libs │ │ │ │ ├── _breakpoints.scss │ │ │ │ ├── _functions.scss │ │ │ │ ├── _html-grid.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _vars.scss │ │ │ │ └── _vendor.scss │ │ │ │ └── main.scss │ │ ├── base.html │ │ ├── contact.html │ │ ├── elements.html │ │ ├── generic.html │ │ ├── images │ │ │ ├── pic01.jpg │ │ │ ├── pic02.jpg │ │ │ ├── pic03.jpg │ │ │ ├── pic04.jpg │ │ │ ├── pic05.jpg │ │ │ ├── pic06.jpg │ │ │ ├── pic07.jpg │ │ │ ├── pic08.jpg │ │ │ ├── pic09.jpg │ │ │ ├── pic10.jpg │ │ │ └── pic11.jpg │ │ ├── index.html │ │ ├── info.json │ │ ├── page.html │ │ ├── render_demo.html │ │ ├── sections │ │ │ ├── footer.html │ │ │ ├── nav.html │ │ │ ├── resources.html │ │ │ └── sidebar.html │ │ └── styles.css │ │ └── hyperspace │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── assets │ │ ├── css │ │ │ ├── fontawesome-all.min.css │ │ │ ├── images │ │ │ │ └── intro.svg │ │ │ ├── main.css │ │ │ └── noscript.css │ │ ├── js │ │ │ ├── breakpoints.min.js │ │ │ ├── browser.min.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.scrollex.min.js │ │ │ ├── jquery.scrolly.min.js │ │ │ ├── main.js │ │ │ └── util.js │ │ └── sass │ │ │ ├── base │ │ │ ├── _page.scss │ │ │ ├── _reset.scss │ │ │ └── _typography.scss │ │ │ ├── components │ │ │ ├── _actions.scss │ │ │ ├── _box.scss │ │ │ ├── _button.scss │ │ │ ├── _contact.scss │ │ │ ├── _features.scss │ │ │ ├── _form.scss │ │ │ ├── _icon.scss │ │ │ ├── _icons.scss │ │ │ ├── _image.scss │ │ │ ├── _list.scss │ │ │ ├── _menu.scss │ │ │ ├── _row.scss │ │ │ ├── _section.scss │ │ │ ├── _split.scss │ │ │ ├── _spotlights.scss │ │ │ ├── _table.scss │ │ │ └── _wrapper.scss │ │ │ ├── layout │ │ │ ├── _footer.scss │ │ │ ├── _header.scss │ │ │ ├── _intro.scss │ │ │ ├── _sidebar.scss │ │ │ └── _wrapper.scss │ │ │ ├── libs │ │ │ ├── _breakpoints.scss │ │ │ ├── _functions.scss │ │ │ ├── _html-grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _vars.scss │ │ │ └── _vendor.scss │ │ │ ├── main.scss │ │ │ └── noscript.scss │ │ ├── base.html │ │ ├── contact.html │ │ ├── elements.html │ │ ├── generic.html │ │ ├── images │ │ ├── pic01.jpg │ │ ├── pic02.jpg │ │ ├── pic03.jpg │ │ ├── pic04.jpg │ │ ├── pic05.jpg │ │ └── pic06.jpg │ │ ├── index.html │ │ ├── info.json │ │ ├── page.html │ │ ├── render_demo.html │ │ ├── sections │ │ ├── footer.html │ │ ├── nav.html │ │ └── resources.html │ │ └── styles.css ├── tests │ ├── conftest.py │ ├── test_configs.py │ ├── test_dunder_main.py │ └── test_manage.py └── wsgi.py.example ├── requirements.txt ├── setup.py └── tox.ini /.editorconfig: -------------------------------------------------------------------------------- 1 | # Check http://editorconfig.org for more information 2 | # This is the main config file for this project: 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [*.{py, pyi}] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [Makefile] 18 | indent_style = tab 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [*.{diff,patch}] 24 | trim_trailing_whitespace = false 25 | -------------------------------------------------------------------------------- /.github/.stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: If something isn't working 🔧 4 | title: '' 5 | labels: bug 6 | assignees: 7 | --- 8 | 9 | ## 🐛 Bug Report 10 | 11 | 12 | 13 | ## 🔬 How To Reproduce 14 | 15 | Steps to reproduce the behavior: 16 | 17 | 1. ... 18 | 19 | ### Code sample 20 | 21 | 22 | 23 | ### Environment 24 | 25 | * OS: [e.g. Linux / Windows / macOS] 26 | * Python version, get it with: 27 | 28 | ```bash 29 | python --version 30 | ``` 31 | 32 | ### Screenshots 33 | 34 | 35 | 36 | ## 📈 Expected behavior 37 | 38 | 39 | 40 | ## 📎 Additional context 41 | 42 | 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository 2 | 3 | blank_issues_enabled: false 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 🏖 4 | title: '' 5 | labels: enhancement 6 | assignees: 7 | --- 8 | 9 | ## 🚀 Feature Request 10 | 11 | 12 | 13 | ## 🔈 Motivation 14 | 15 | 16 | 17 | ## 🛰 Alternatives 18 | 19 | 20 | 21 | ## 📎 Additional context 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Question 3 | about: Ask a question about this project 🎓 4 | title: '' 5 | labels: question 6 | assignees: 7 | --- 8 | 9 | ## Checklist 10 | 11 | 12 | 13 | - [ ] I've searched the project's [`issues`](https://github.com/shopyo/pythoncms/issues?q=is%3Aissue). 14 | 15 | ## ❓ Question 16 | 17 | 18 | 19 | How can I [...]? 20 | 21 | Is it possible to [...]? 22 | 23 | ## 📎 Additional context 24 | 25 | 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Related Issue 6 | 7 | 8 | 9 | ## Type of Change 10 | 11 | 12 | 13 | - [ ] 📚 Examples / docs / tutorials / dependencies update 14 | - [ ] 🔧 Bug fix (non-breaking change which fixes an issue) 15 | - [ ] 🥂 Improvement (non-breaking change which improves an existing feature) 16 | - [ ] 🚀 New feature (non-breaking change which adds functionality) 17 | - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change) 18 | - [ ] 🔐 Security fix 19 | 20 | ## Checklist 21 | 22 | 23 | 24 | - [ ] I've read the [`CODE_OF_CONDUCT.md`](https://github.com/shopyo/pythoncms/blob/master/CODE_OF_CONDUCT.md) document. 25 | - [ ] I've read the [`CONTRIBUTING.md`](https://github.com/shopyo/pythoncms/blob/master/CONTRIBUTING.md) guide. 26 | - [ ] I've updated the code style using `make codestyle`. 27 | - [ ] I've written tests for all new methods and classes that I created. 28 | - [ ] I've written the docstring in Google format for all the methods and classes that I used. 29 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | # Release drafter configuration https://github.com/release-drafter/release-drafter#configuration 2 | # Emojis were chosen to match the https://gitmoji.carloscuesta.me/ 3 | 4 | name-template: "v$NEXT_PATCH_VERSION" 5 | tag-template: "v$NEXT_PATCH_VERSION" 6 | 7 | categories: 8 | - title: ":rocket: Features" 9 | labels: [enhancement, feature] 10 | - title: ":wrench: Fixes & Refactoring" 11 | labels: [bug, refactoring, bugfix, fix] 12 | - title: ":package: Build System & CI/CD" 13 | labels: [build, ci, testing] 14 | - title: ":boom: Breaking Changes" 15 | labels: [breaking] 16 | - title: ":pencil: Documentation" 17 | labels: [documentation] 18 | - title: ":arrow_up: Dependencies updates" 19 | labels: [dependencies] 20 | 21 | template: | 22 | ## What’s Changed 23 | 24 | $CHANGES 25 | 26 | ## :busts_in_silhouette: List of contributors 27 | 28 | $CONTRIBUTORS 29 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/first-interaction@v1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | pr-message: 'Hello @${{ github.actor }}, thank you for submitting a PR! We will respond as soon as possible.' 13 | issue-message: | 14 | Hello @${{ github.actor }}, thank you for your interest in our work! 15 | 16 | If this is a bug report, please provide screenshots and **minimum viable code to reproduce your issue**, otherwise we can not help you. 17 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | _build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # shopyo 107 | test.db 108 | testing.db 109 | shopyo.db 110 | 111 | # pycharm 112 | .idea/ 113 | 114 | # win 115 | *.exe 116 | *.cs 117 | *.bat 118 | *.vbs 119 | 120 | # vscode 121 | .vscode 122 | workspace.code-workspace 123 | 124 | # modules in static since present in modules 125 | shopyo/static/modules/ 126 | 127 | # ignore secrets 128 | config.json 129 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/asottile/pyupgrade 3 | rev: v3.3.1 4 | hooks: 5 | - id: pyupgrade 6 | args: ["--py36-plus"] 7 | - repo: https://github.com/asottile/reorder_python_imports 8 | rev: v3.9.0 9 | hooks: 10 | - id: reorder-python-imports 11 | name: Reorder Python imports 12 | - repo: https://github.com/psf/black 13 | rev: 22.12.0 14 | hooks: 15 | - id: black 16 | args: [--experimental-string-processing] 17 | - repo: https://github.com/pre-commit/pre-commit-hooks 18 | rev: v4.4.0 19 | hooks: 20 | - id: fix-byte-order-marker 21 | - id: trailing-whitespace 22 | - id: end-of-file-fixer 23 | - id: check-yaml 24 | - id: debug-statements 25 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | include dev_requirements.txt 3 | exclude config.json 4 | recursive-include pythoncms * 5 | recursive-exclude pythoncms/instance * 6 | recursive-exclude pythoncms/migrations * 7 | recursive-exclude pythoncms/static/modules * 8 | recursive-exclude pythoncms/.tox * 9 | recursive-exclude __pycache__ * 10 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/assets/logo.png -------------------------------------------------------------------------------- /assets/term.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/assets/term.gif -------------------------------------------------------------------------------- /dev_requirements.txt: -------------------------------------------------------------------------------- 1 | flake8==3.8.4 2 | black==20.8b1 3 | isort==5.6.4 4 | Sphinx==3.2.1 5 | pytest==6.1.1 6 | pytest-order==0.9.5 7 | tox==3.21.0 8 | pytest-cov==2.11.1 9 | codecov==2.1.11 10 | factory-boy==3.2.0 11 | freezegun==1.1.0 12 | pytest-dotenv 13 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/docs/_static/custom.css -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | # -- Path setup -------------------------------------------------------------- 7 | # 8 | # If extensions (or modules to document with autodoc) are in another directory, 9 | # add these directories to sys.path here. If the directory is relative to the 10 | # documentation root, use os.path.abspath to make it absolute, like shown here. 11 | # 12 | # import os 13 | # import sys 14 | # sys.path.insert(0, os.path.abspath('.')) 15 | # 16 | # -- Project information ----------------------------------------------------- 17 | 18 | project = "pythoncms" 19 | author = "" 20 | 21 | # -- General configuration --------------------------------------------------- 22 | 23 | # Add any Sphinx extension module names here, as strings. They can be 24 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 25 | # ones. 26 | extensions = [ 27 | "sphinx.ext.autodoc", 28 | "sphinx.ext.viewcode", 29 | "sphinx.ext.autosectionlabel", 30 | "sphinx.ext.napoleon", 31 | ] 32 | 33 | # Add any paths that contain templates here, relative to this directory. 34 | templates_path = ["_templates"] 35 | 36 | # List of patterns, relative to source directory, that match files and 37 | # directories to ignore when looking for source files. 38 | # This pattern also affects html_static_path and html_extra_path. 39 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 40 | 41 | 42 | # -- Options for HTML output ------------------------------------------------- 43 | html_context = { 44 | "project_links": [ 45 | "Source Code", 46 | "https://github.com//", 47 | "Issue Tracker", 48 | "https://github.com///issues", 49 | ] 50 | } 51 | html_logo = "shopyo.ico" 52 | 53 | html_sidebars = { 54 | "**": ["about.html", "relations.html", "navigation.html", "searchbox.html"] 55 | } 56 | 57 | # The theme to use for HTML and HTML Help pages. See the documentation for 58 | # a list of builtin themes. 59 | # 60 | html_theme = "alabaster" 61 | html_theme_options = { 62 | "github_repo": "/", 63 | "fixed_sidebar": "true", 64 | } 65 | 66 | # Add any paths that contain custom static files (such as style sheets) here, 67 | # relative to this directory. They are copied after the builtin static files, 68 | # so a file named "default.css" will overwrite the builtin "default.css". 69 | html_static_path = ["_static"] 70 | -------------------------------------------------------------------------------- /docs/docs.rst: -------------------------------------------------------------------------------- 1 | .. :tocdepth:: 5 2 | 3 | Documentation 4 | ============= 5 | 6 | Sphinx is included in dev_requirements.txt 7 | 8 | .. code:: bash 9 | 10 | cd docs 11 | sphinx-build . _build 12 | 13 | to generate html pages in docs 14 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to pythoncms docs! 2 | ============================ 3 | 4 | Write project description here 5 | 6 | .. toctree:: 7 | :maxdepth: 9 8 | 9 | Docs 10 | 11 | Indices and tables 12 | ================== 13 | 14 | * :ref:`genindex` 15 | * :ref:`modindex` 16 | * :ref:`search` 17 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | env_files = 3 | .test.prod.env 4 | -------------------------------------------------------------------------------- /pythoncms/.env_demo: -------------------------------------------------------------------------------- 1 | ACTIVE_FRONT_THEME = 'editorial' 2 | ACTIVE_BACK_THEME = 'sneat' 3 | APP_NAME = 'Demo' 4 | ACTIVE_ICONSET = 'boxicons' 5 | SITE_TITLE = 'Site title' 6 | SITE_DESCRIPTION = 'Site title' -------------------------------------------------------------------------------- /pythoncms/.test.prod.env: -------------------------------------------------------------------------------- 1 | SECRET_KEY = "secret" 2 | MAIL_USERNAME = "foo@gmail.com" 3 | MAIL_PASSWORD = "pass" 4 | MAIL_DEFAULT_SENDER = "foo@gmail.com" 5 | SQLALCHEMY_DATABASE_URI = "mysql+pymysql://db_username:db_password@db_host/db_name" 6 | -------------------------------------------------------------------------------- /pythoncms/CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/CHANGELOG.md -------------------------------------------------------------------------------- /pythoncms/__init__.py: -------------------------------------------------------------------------------- 1 | version_info = (1, 4, 2) 2 | __version__ = ".".join([str(v) for v in version_info]) 3 | -------------------------------------------------------------------------------- /pythoncms/autoapp.py.example: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.path.append(os.getcwd()) 5 | from app import create_app 6 | 7 | 8 | # CONFIG_JSON_PATH = os.path.dirname(os.path.abspath(__file__)) 9 | 10 | 11 | # try: 12 | # if not os.path.exists("config.json"): 13 | # trycopy("config_demo.json", "config.json") 14 | # except Exception as e: 15 | # print(e) 16 | # sys.exit(1) 17 | 18 | # with open(os.path.join(CONFIG_JSON_PATH, "config.json")) as f: 19 | # config_json = json.load(f) 20 | 21 | # environment = config_json["environment"] 22 | app = create_app("production") 23 | -------------------------------------------------------------------------------- /pythoncms/cli.py: -------------------------------------------------------------------------------- 1 | """ 2 | file: cli.py 3 | description: Add your custom cli commands here 4 | documentation: https://click.palletsprojects.com/en/7.x/ 5 | 6 | You will need to run ``python -m pip install -e .`` to load the setup.py 7 | which contains the entry point to this file before being able to run your 8 | custom commands 9 | 10 | Usage ``pythoncms [OPTIONS] COMMAND [ARGS]...`` 11 | 12 | Example command 'welcome' has been added. 13 | - To get your project version, run ``pythoncms --version`` 14 | - Run the sample command as ``pythoncms welcome [OPTIONS] NAME`` 15 | """ 16 | from pathlib import Path 17 | 18 | import click 19 | from shopyo.api.file import trycopytree 20 | from shopyo.api.file import trymkfile 21 | from shopyo.api.file import tryrmfile 22 | from shopyo.api.file import tryrmtree 23 | 24 | from pythoncms import __version__ 25 | 26 | path = Path(__file__) 27 | import os 28 | 29 | 30 | @click.group() 31 | @click.version_option(__version__) 32 | @click.pass_context 33 | def cli(ctx): 34 | """CLI entry point""" 35 | pass 36 | 37 | 38 | # @cli.command("welcome") 39 | # @click.argument("name") 40 | # @click.option("--verbose", "-v", is_flag=True, default=False) 41 | # def welcome(name, verbose): 42 | # """Sample command to welcome users. 43 | 44 | # NAME will be printed along with the welcome message 45 | # """ 46 | # click.secho(f"Hi {name}. Welcome to pythoncms", fg="cyan") 47 | 48 | # if verbose: 49 | # click.echo("See you soon") 50 | 51 | reqs = f"""pythoncms=={__version__}""" 52 | 53 | 54 | @cli.command("start") 55 | @click.argument("name") 56 | def start(name): 57 | """ 58 | New project 59 | """ 60 | dest = os.getcwd() + f"/{name}" 61 | 62 | trycopytree(str(path.parent.absolute()), dest) 63 | tryrmfile(dest + "/cli.py") 64 | trymkfile(dest + "/requirements.txt", reqs) 65 | try: 66 | os.rename('.env_demo', '.env') 67 | except Exception as e: 68 | print(e) 69 | click.echo(f"🍭 Pythoncms project {name} is ready to go!") 70 | -------------------------------------------------------------------------------- /pythoncms/config_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "admin_user": { 3 | "email": "admin@domain.com", 4 | "password": "pass" 5 | }, 6 | "settings": { 7 | "APP_NAME": "Demo", 8 | "ACTIVE_FRONT_THEME": "editorial", 9 | "ACTIVE_BACK_THEME": "sneat", 10 | "ACTIVE_ICONSET": "fa", 11 | "SITE_TITLE": "My site", 12 | "SITE_DESCRIPTION": "description", 13 | "CURRENCY": "MUR", 14 | "ACTIVE_ICONSET": "boxicons" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pythoncms/init.py: -------------------------------------------------------------------------------- 1 | """ 2 | All initializations like db = SQLAlchemy in this file 3 | """ 4 | import os 5 | 6 | from flask_login import LoginManager 7 | from flask_mailman import Mail 8 | from flask_migrate import Migrate 9 | from flask_sqlalchemy import SQLAlchemy 10 | from flask_wtf.csrf import CSRFProtect 11 | 12 | # from flask_marshmallow import Marshmallow, uncommented as not updated to support flask 2.x 13 | 14 | root_path = os.path.dirname(os.path.abspath(__file__)) # don't remove 15 | static_path = os.path.join(root_path, "static") # don't remove 16 | modules_path = os.path.join(root_path, "modules") # don't remove 17 | themes_path = os.path.join(static_path, "themes") # don't remove 18 | installed_packages = [] # don't remove 19 | 20 | installed_packages = [] 21 | 22 | db = SQLAlchemy() 23 | # ma = Marshmallow() 24 | login_manager = LoginManager() 25 | migrate = Migrate() 26 | mail = Mail() 27 | csrf = CSRFProtect() 28 | 29 | 30 | def load_extensions(app): 31 | migrate.init_app(app, db) 32 | db.init_app(app) 33 | # ma.init_app(app) 34 | mail.init_app(app) 35 | login_manager.init_app(app) 36 | csrf.init_app(app) 37 | -------------------------------------------------------------------------------- /pythoncms/manage.py: -------------------------------------------------------------------------------- 1 | """ 2 | file: manage.py 3 | description: allows using cli commands similar to Django. 4 | Example all ``shopyo [OPTIONS] [ARGS]...`` commands can also be run as 5 | ``python manage.py [OPTIONS] [ARGS]...`` 6 | """ 7 | from shopyo.api.cli import cli 8 | 9 | if __name__ == "__main__": 10 | cli() 11 | -------------------------------------------------------------------------------- /pythoncms/migrations/README: -------------------------------------------------------------------------------- 1 | Single-database configuration for Flask. 2 | -------------------------------------------------------------------------------- /pythoncms/migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic,flask_migrate 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [logger_flask_migrate] 38 | level = INFO 39 | handlers = 40 | qualname = flask_migrate 41 | 42 | [handler_console] 43 | class = StreamHandler 44 | args = (sys.stderr,) 45 | level = NOTSET 46 | formatter = generic 47 | 48 | [formatter_generic] 49 | format = %(levelname)-5.5s [%(name)s] %(message)s 50 | datefmt = %H:%M:%S 51 | -------------------------------------------------------------------------------- /pythoncms/migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /pythoncms/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/__init__.py -------------------------------------------------------------------------------- /pythoncms/modules/contact/forms.py: -------------------------------------------------------------------------------- 1 | from flask_wtf import FlaskForm 2 | from wtforms import EmailField 3 | from wtforms import StringField 4 | from wtforms import TextAreaField 5 | from wtforms.validators import DataRequired 6 | 7 | # from wtforms.validators import Length 8 | 9 | 10 | class ContactForm(FlaskForm): 11 | name = StringField( 12 | "Name", 13 | [DataRequired()], 14 | render_kw={"class": "form-control", "autocomplete": "off"}, 15 | ) 16 | email = EmailField( 17 | "Email", 18 | [DataRequired()], 19 | render_kw={"class": "form-control", "autocomplete": "off"}, 20 | ) 21 | message = TextAreaField( 22 | "Message", 23 | [DataRequired()], 24 | render_kw={ 25 | "class": "form-control", 26 | "rows": "20", 27 | "autocomplete": "off", 28 | }, 29 | ) 30 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/global.py: -------------------------------------------------------------------------------- 1 | from flask import url_for 2 | 3 | 4 | def get_contact_url(): 5 | return url_for("contact.index") 6 | 7 | 8 | available_everywhere = {"get_contact_url": get_contact_url} 9 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "display_string": "Contact", 3 | "type": "show", 4 | "icons":{ 5 | "fa": "fa fa-envelope", 6 | "boxicons": "bx bx-envelope" 7 | }, 8 | "url_prefix": "/contact", 9 | "dashboard": "/dashboard", 10 | "author": { 11 | "name":"Abdur-Rahmaan Janhangeer", 12 | "website":"https://www.pythonkitchen.com/about-me/", 13 | "mail":"arj.python@gmail.com" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/models.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from init import db 4 | 5 | 6 | class ContactMessage(db.Model): 7 | 8 | __tablename__ = "contact" 9 | id = db.Column(db.Integer, primary_key=True) 10 | created_date = db.Column(db.DateTime, default=datetime.now()) 11 | name = db.Column(db.String(100)) 12 | email = db.Column(db.String(100)) 13 | message = db.Column(db.String(1024)) 14 | 15 | def insert(self): 16 | db.session.add(self) 17 | db.session.commit() 18 | 19 | def update(self): 20 | db.session.commit() 21 | 22 | def delete(self): 23 | db.session.delete(self) 24 | db.session.commit() 25 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/templates/contact/blocks/sidebar.html: -------------------------------------------------------------------------------- 1 | {{ 2 | sidebar_item('Home', 3 | icon='fa fa-envelope', 4 | url=url_for('contact.dashboard') 5 | ) 6 | }} 7 | 8 | {{ 9 | sidebar_item('Contact Page', 10 | icon='fa fa-globe', 11 | url=url_for('contact.index') 12 | ) 13 | }} 14 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/templates/contact/contact_form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% include get_active_front_theme()+'/sections/resources.html'%} 6 | {% include 'base/blocks/flashed_messages.html'%} 7 | 8 | 9 | {% include get_active_front_theme()+'/sections/nav.html'%} 10 | 11 |
12 |
13 | 14 |
15 | {{ form.name.label }}
16 |
17 |
18 | 19 |
20 | {{ form.name }} 21 |
22 |
23 | 24 |
25 | {{ form.email.label }}
26 |
27 |
28 | 29 |
30 | {{ form.email }} 31 |
32 |
33 | 34 |
35 | {{ form.message.label }}
36 |
37 |
38 | 39 |
40 | {{ form.message }} 41 |
42 |
43 |
44 | 45 | 46 |
47 |
48 | 49 | 50 | {% include get_active_front_theme()+'/sections/footer.html'%} 51 | 52 | 53 | -------------------------------------------------------------------------------- /pythoncms/modules/contact/view.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | from flask import flash 3 | from flask import redirect 4 | from flask import render_template 5 | from flask import request 6 | from flask import url_for 7 | from flask_login import login_required 8 | from shopyo_theme.helpers import get_active_front_theme 9 | from shopyo.api.html import notify_success 10 | 11 | from .forms import ContactForm 12 | from .models import ContactMessage 13 | 14 | contact_blueprint = Blueprint( 15 | "contact", 16 | __name__, 17 | url_prefix="/contact", 18 | template_folder="templates", 19 | ) 20 | 21 | 22 | @contact_blueprint.route("/") 23 | def index(): 24 | context = {} 25 | form = ContactForm() 26 | 27 | context.update({"form": form}) 28 | return render_template(f"{get_active_front_theme()}/contact.html", **context) 29 | 30 | 31 | @contact_blueprint.route("/validate_message", methods=["GET", "POST"]) 32 | @login_required 33 | def validate_message(): 34 | if request.method == "POST": 35 | form = ContactForm() 36 | if not form.validate_on_submit(): 37 | flash_errors(form) 38 | return redirect(url_for("contact.index")) 39 | 40 | name = form.name.data 41 | email = form.email.data 42 | message = form.message.data 43 | 44 | contact_message = ContactMessage(name=name, email=email, message=message) 45 | contact_message.insert() 46 | flash("Message submitted!", "ok") 47 | return redirect(url_for("contact.index")) 48 | 49 | 50 | @contact_blueprint.route("/dashboard", methods=["GET"], defaults={"page": 1}) 51 | @contact_blueprint.route("/dashboard/", methods=["GET"]) 52 | @login_required 53 | def dashboard(page): 54 | context = {} 55 | 56 | per_page = 10 57 | messages = ContactMessage.query.paginate( 58 | page=page, per_page=per_page, error_out=False 59 | ) 60 | context.update({"messages": messages}) 61 | return render_template("contact/dashboard.html", **context) 62 | -------------------------------------------------------------------------------- /pythoncms/modules/resource/forms.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/resource/forms.py -------------------------------------------------------------------------------- /pythoncms/modules/resource/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "display_string": "Files", 3 | "module_name": "resource", 4 | "type": "hide", 5 | "icons":{ 6 | "fa": "fa fa-envelope", 7 | "boxicons": "" 8 | }, 9 | "url_prefix": "/resource", 10 | "author": { 11 | "name": "", 12 | "website": "", 13 | "mail": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pythoncms/modules/resource/models.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from init import db 4 | 5 | 6 | class Image(db.Model): 7 | __tablename__ = "images" 8 | id = db.Column(db.Integer, primary_key=True) 9 | filename = db.Column(db.String(50), nullable=False) 10 | thumbnail = db.Column(db.String(50), nullable=False) 11 | file_size = db.Column(db.Integer, nullable=False) 12 | file_width = db.Column(db.Integer, nullable=False) 13 | file_height = db.Column(db.Integer, nullable=False) 14 | create_date = db.Column( 15 | db.DateTime, default=datetime.datetime.now(), nullable=False 16 | ) 17 | 18 | # def set_hash(self, password): 19 | # self.password = generate_password_hash(password, method="sha256") 20 | 21 | # def check_hash(self, password): 22 | # return check_password_hash(self.password, password) 23 | 24 | def insert(self): 25 | db.session.add(self) 26 | db.session.commit() 27 | 28 | def update(self): 29 | db.session.commit() 30 | 31 | def delete(self): 32 | db.session.delete(self) 33 | db.session.commit() 34 | 35 | # def getImage(self, image_id): 36 | # return Images.query.filter_by(id=image_id).first() 37 | 38 | 39 | class Resource(db.Model): 40 | __tablename__ = "resources" 41 | id = db.Column(db.Integer, primary_key=True) 42 | filename = db.Column(db.String(50), nullable=False) 43 | type = db.Column(db.String(50), nullable=False) 44 | category = db.Column(db.String(50), nullable=False) 45 | 46 | created_date = db.Column( 47 | db.DateTime, default=datetime.datetime.now(), nullable=False 48 | ) 49 | 50 | # def set_hash(self, password): 51 | # self.password = generate_password_hash(password, method="sha256") 52 | 53 | # def check_hash(self, password): 54 | # return check_password_hash(self.password, password) 55 | 56 | def insert(self): 57 | db.session.add(self) 58 | db.session.commit() 59 | 60 | def update(self): 61 | db.session.commit() 62 | 63 | def delete(self): 64 | db.session.delete(self) 65 | db.session.commit() 66 | -------------------------------------------------------------------------------- /pythoncms/modules/resource/templates/resource/blocks/sidebar.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/resource/templates/resource/blocks/sidebar.html -------------------------------------------------------------------------------- /pythoncms/modules/www/forms.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/www/forms.py -------------------------------------------------------------------------------- /pythoncms/modules/www/global.py: -------------------------------------------------------------------------------- 1 | configs = { 2 | "development": {"*********************FUN": "MIAWDEV"}, 3 | "production": {"*********************FUN": "MIAWPROD"}, 4 | "testing": {"*********************FUN": "MIAWTEST"}, 5 | } 6 | -------------------------------------------------------------------------------- /pythoncms/modules/www/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "display_string": "Www", 3 | "module_name":"www", 4 | "type": "show", 5 | "icons":{ 6 | "fa": "fa fa-globe-asia", 7 | "boxicons": "bx bx-planet" 8 | }, 9 | "url_prefix": "/", 10 | "author": { 11 | "name":"", 12 | "website":"", 13 | "mail":"" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pythoncms/modules/www/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/www/models.py -------------------------------------------------------------------------------- /pythoncms/modules/www/templates/www/blocks/sidebar.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/modules/www/templates/www/blocks/sidebar.html -------------------------------------------------------------------------------- /pythoncms/modules/www/templates/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Shopyo is now running! Please consult the docs or join the Discord community.

8 |

Otherwise, go right ahead to the dashboard to get started by logging in with email admin@domain.com and password pass.


9 |

10 | Make sure to run

shopyo initialise
to initialise the db if you are using the default modules! 11 |

12 | 13 | 14 | -------------------------------------------------------------------------------- /pythoncms/modules/www/view.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | from shopyo_theme.helpers import get_active_front_theme 3 | from shopyo.api.module import ModuleHelp 4 | from shopyo.api.templates import yo_render 5 | 6 | # from flask import url_for 7 | # from flask import redirect 8 | # from flask import flash 9 | # from flask import request 10 | # 11 | # from shopyo.api.html import notify_success 12 | # from shopyo.api.forms import flash_errors 13 | # from shopyo.api.enhance import get_active_theme_dir 14 | # from modules.box__ecommerce.shop.helpers import get_cart_data 15 | 16 | mhelp = ModuleHelp(__file__, __name__) 17 | globals()[mhelp.blueprint_str] = mhelp.blueprint 18 | module_blueprint = globals()[mhelp.blueprint_str] 19 | 20 | 21 | @module_blueprint.route("/") 22 | def index(): 23 | # cant be defined above but must be manually set each time 24 | # active_theme_dir = os.path.join( 25 | # dirpath, "..", "..", "themes", os.environ.get('ACTIVE_FRONT_THEME") 26 | # ) 27 | # module_blueprint.template_folder = active_theme_dir 28 | 29 | # return str(module_blueprint.template_folder) 30 | 31 | # return render_template(os.environ.get('ACTIVE_FRONT_THEME") + "/index.html") 32 | 33 | return render_template( 34 | f"{get_active_front_theme()}/index.html", get_static=get_static 35 | ) 36 | 37 | 38 | from shopyo.api.assets import get_static 39 | 40 | 41 | @module_blueprint.route("/render_demo") 42 | def render_demo(): 43 | context = {"fruit": "mango"} 44 | return yo_render("blogus/render_demo.html", context) 45 | -------------------------------------------------------------------------------- /pythoncms/shopyo_admin.py: -------------------------------------------------------------------------------- 1 | from flask import redirect 2 | from flask import request 3 | from flask import url_for 4 | from flask_admin import AdminIndexView 5 | from flask_admin import expose 6 | from flask_admin.contrib import sqla as flask_admin_sqla 7 | from flask_login import current_user 8 | 9 | 10 | class DefaultModelView(flask_admin_sqla.ModelView): 11 | def __init__(self, *args, **kwargs): 12 | super().__init__(*args, **kwargs) 13 | 14 | def is_accessible(self): 15 | return current_user.is_authenticated and current_user.is_admin 16 | 17 | def inaccessible_callback(self, name, **kwargs): 18 | # redirect to login page if user doesn't have access 19 | return redirect(url_for("shopyo_auth.login", next=request.url)) 20 | 21 | 22 | class MyAdminIndexView(AdminIndexView): 23 | def is_accessible(self): 24 | return current_user.is_authenticated and current_user.is_admin 25 | 26 | def inaccessible_callback(self, name, **kwargs): 27 | # redirect to login page if user doesn't have access 28 | return redirect(url_for("shopyo_auth.login", next=request.url)) 29 | 30 | @expose("/") 31 | def index(self): 32 | if not current_user.is_authenticated and current_user.is_admin: 33 | return redirect(url_for("shopyo_auth.login")) 34 | return super().index() 35 | 36 | @expose("/dashboard") 37 | def indexs(self): 38 | if not current_user.is_authenticated and current_user.is_admin: 39 | return redirect(url_for("shopyo_auth.login")) 40 | return super().index() 41 | -------------------------------------------------------------------------------- /pythoncms/static/css/simple_sidebar.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Simple Sidebar (https://startbootstrap.com/templates/simple-sidebar) 3 | * Copyright 2013-2020 Start Bootstrap 4 | * Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-simple-sidebar/blob/master/LICENSE) 5 | */ 6 | 7 | #wrapper { 8 | overflow-x: hidden; 9 | } 10 | 11 | #sidebar-wrapper { 12 | min-height: 100vh; 13 | margin-left: -15rem; 14 | -webkit-transition: margin .25s ease-out; 15 | -moz-transition: margin .25s ease-out; 16 | -o-transition: margin .25s ease-out; 17 | transition: margin .25s ease-out; 18 | } 19 | 20 | #sidebar-wrapper .sidebar-heading { 21 | padding: 0.875rem 1.25rem; 22 | font-size: 1.2rem; 23 | } 24 | 25 | #sidebar-wrapper .list-group { 26 | width: 15rem; 27 | } 28 | 29 | #page-content-wrapper { 30 | min-width: 100vw; 31 | } 32 | 33 | #wrapper.toggled #sidebar-wrapper { 34 | margin-left: 0; 35 | } 36 | 37 | @media (min-width: 768px) { 38 | #sidebar-wrapper { 39 | margin-left: 0; 40 | } 41 | 42 | #page-content-wrapper { 43 | min-width: 0; 44 | width: 100%; 45 | } 46 | 47 | #wrapper.toggled #sidebar-wrapper { 48 | margin-left: -15rem; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pythoncms/static/default/default_product.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/default/default_product.jpg -------------------------------------------------------------------------------- /pythoncms/static/default/default_subcategory.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/default/default_subcategory.jpg -------------------------------------------------------------------------------- /pythoncms/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/favicon.ico -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font Awesome Free License 2 | ------------------------- 3 | 4 | Font Awesome Free is free, open source, and GPL friendly. You can use it for 5 | commercial projects, open source projects, or really almost whatever you want. 6 | Full Font Awesome Free license: https://fontawesome.com/license/free. 7 | 8 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) 9 | In the Font Awesome Free download, the CC BY 4.0 license applies to all icons 10 | packaged as SVG and JS file types. 11 | 12 | # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL) 13 | In the Font Awesome Free download, the SIL OFL license applies to all icons 14 | packaged as web and desktop font files. 15 | 16 | # Code: MIT License (https://opensource.org/licenses/MIT) 17 | In the Font Awesome Free download, the MIT license applies to all non-font and 18 | non-icon files. 19 | 20 | # Attribution 21 | Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font 22 | Awesome Free files already contain embedded comments with sufficient 23 | attribution, so you shouldn't need to do anything additional when using these 24 | files normally. 25 | 26 | We've kept attribution comments terse, so we ask that you do not actively work 27 | to remove them from files, especially code. They're a great way for folks to 28 | learn about Font Awesome. 29 | 30 | # Brand Icons 31 | All brand icons are trademarks of their respective owners. The use of these 32 | trademarks does not indicate endorsement of the trademark holder by Font 33 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except 34 | to represent the company, product, or service to which they refer.** 35 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/brands.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Font Awesome 5 Brands'; 3 | font-style: normal; 4 | font-weight: normal; 5 | font-display: auto; 6 | src: url("../webfonts/fa-brands-400.eot"); 7 | src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); } 8 | 9 | .fab { 10 | font-family: 'Font Awesome 5 Brands'; } 11 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/brands.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"} 2 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/regular.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Font Awesome 5 Free'; 3 | font-style: normal; 4 | font-weight: 400; 5 | font-display: auto; 6 | src: url("../webfonts/fa-regular-400.eot"); 7 | src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); } 8 | 9 | .far { 10 | font-family: 'Font Awesome 5 Free'; 11 | font-weight: 400; } 12 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/regular.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Free";font-weight:400} 2 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/solid.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Font Awesome 5 Free'; 3 | font-style: normal; 4 | font-weight: 900; 5 | font-display: auto; 6 | src: url("../webfonts/fa-solid-900.eot"); 7 | src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); } 8 | 9 | .fa, 10 | .fas { 11 | font-family: 'Font Awesome 5 Free'; 12 | font-weight: 900; } 13 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/css/solid.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} 2 | -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /pythoncms/static/fontawesome/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/fontawesome/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /pythoncms/static/js/python.js: -------------------------------------------------------------------------------- 1 | function isObject(value){ 2 | return typeof value === 'object' && value !== null 3 | } 4 | function print() { 5 | var sep = ' '; 6 | var toprint = ''; 7 | for (var i = arguments.length - 1; i >= 0; i--) { 8 | var arg = arguments[arguments.length - i - 1]; 9 | 10 | if (typeof arg === 'string' || arg instanceof String) { 11 | 12 | } else if (isObject(arg)){ 13 | arg = JSON.stringify(arg); 14 | } 15 | else { 16 | arg = arg.toString(); 17 | } 18 | toprint += arg + sep; 19 | } 20 | console.log(toprint); 21 | } 22 | function max(array1){ 23 | return Math.max(...array1) 24 | } 25 | function min(array1){ 26 | return Math.min(...array1) 27 | } 28 | function sum(array1){ 29 | var sumArray = array1.reduce(function(a, b){ 30 | return a + b; 31 | }, 0); 32 | return sumArray; 33 | } 34 | 35 | function round(number){ 36 | return Math.round(number); 37 | } 38 | 39 | function int(number_string){ 40 | return parseInt(number_string); 41 | } 42 | 43 | function reverse(array1){ 44 | return array1.reverse(); 45 | } 46 | 47 | function len(object1){ 48 | return object1.length; 49 | } 50 | 51 | function checkTrue(element){ 52 | return element === true; 53 | } 54 | function all(array1){ 55 | return array1.every(checkTrue); 56 | } 57 | function any(array1){ 58 | return array1.some(function(e) { 59 | return e === true; 60 | }); 61 | } 62 | 63 | function abs(number1){ 64 | return Math.abs(number1); 65 | } 66 | -------------------------------------------------------------------------------- /pythoncms/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/logo.png -------------------------------------------------------------------------------- /pythoncms/static/shopyo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/shopyo.png -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2021 Start Bootstrap LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/authbase.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | SB Admin 2 - Login 14 | 15 | 16 | 21 | 25 | 26 | 27 | 31 | 32 | 33 | 34 |
35 | 36 |
37 |
38 |
39 |
40 | 41 | 42 |
43 |
44 | {%block content%} 45 | 46 | {%endblock%} 47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ARJ", 3 | "version": "1.0.20000000000003" 4 | } 5 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/js/demo/chart-pie-demo.js: -------------------------------------------------------------------------------- 1 | // Set new default font family and font color to mimic Bootstrap's default styling 2 | Chart.defaults.global.defaultFontFamily = 'Nunito', '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'; 3 | Chart.defaults.global.defaultFontColor = '#858796'; 4 | 5 | // Pie Chart Example 6 | var ctx = document.getElementById("myPieChart"); 7 | var myPieChart = new Chart(ctx, { 8 | type: 'doughnut', 9 | data: { 10 | labels: ["Direct", "Referral", "Social"], 11 | datasets: [{ 12 | data: [55, 30, 15], 13 | backgroundColor: ['#4e73df', '#1cc88a', '#36b9cc'], 14 | hoverBackgroundColor: ['#2e59d9', '#17a673', '#2c9faf'], 15 | hoverBorderColor: "rgba(234, 236, 244, 1)", 16 | }], 17 | }, 18 | options: { 19 | maintainAspectRatio: false, 20 | tooltips: { 21 | backgroundColor: "rgb(255,255,255)", 22 | bodyFontColor: "#858796", 23 | borderColor: '#dddfeb', 24 | borderWidth: 1, 25 | xPadding: 15, 26 | yPadding: 15, 27 | displayColors: false, 28 | caretPadding: 10, 29 | }, 30 | legend: { 31 | display: false 32 | }, 33 | cutoutPercentage: 80, 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/js/demo/datatables-demo.js: -------------------------------------------------------------------------------- 1 | // Call the dataTables jQuery plugin 2 | $(document).ready(function() { 3 | $('#dataTable').DataTable(); 4 | }); 5 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/js/sb-admin-2.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | "use strict"; // Start of use strict 3 | 4 | // Toggle the side navigation 5 | $("#sidebarToggle, #sidebarToggleTop").on('click', function(e) { 6 | $("body").toggleClass("sidebar-toggled"); 7 | $(".sidebar").toggleClass("toggled"); 8 | if ($(".sidebar").hasClass("toggled")) { 9 | $('.sidebar .collapse').collapse('hide'); 10 | }; 11 | }); 12 | 13 | // Close any open menu accordions when window is resized below 768px 14 | $(window).resize(function() { 15 | if ($(window).width() < 768) { 16 | $('.sidebar .collapse').collapse('hide'); 17 | }; 18 | 19 | // Toggle the side navigation when window is resized below 480px 20 | if ($(window).width() < 480 && !$(".sidebar").hasClass("toggled")) { 21 | $("body").addClass("sidebar-toggled"); 22 | $(".sidebar").addClass("toggled"); 23 | $('.sidebar .collapse').collapse('hide'); 24 | }; 25 | }); 26 | 27 | // Prevent the content wrapper from scrolling when the fixed side navigation hovered over 28 | $('body.fixed-nav .sidebar').on('mousewheel DOMMouseScroll wheel', function(e) { 29 | if ($(window).width() > 768) { 30 | var e0 = e.originalEvent, 31 | delta = e0.wheelDelta || -e0.detail; 32 | this.scrollTop += (delta < 0 ? 1 : -1) * 30; 33 | e.preventDefault(); 34 | } 35 | }); 36 | 37 | // Scroll to top button appear 38 | $(document).on('scroll', function() { 39 | var scrollDistance = $(this).scrollTop(); 40 | if (scrollDistance > 100) { 41 | $('.scroll-to-top').fadeIn(); 42 | } else { 43 | $('.scroll-to-top').fadeOut(); 44 | } 45 | }); 46 | 47 | // Smooth scrolling using jQuery easing 48 | $(document).on('click', 'a.scroll-to-top', function(e) { 49 | var $anchor = $(this); 50 | $('html, body').stop().animate({ 51 | scrollTop: ($($anchor.attr('href')).offset().top) 52 | }, 1000, 'easeInOutExpo'); 53 | e.preventDefault(); 54 | }); 55 | 56 | })(jQuery); // End of use strict 57 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/js/sb-admin-2.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin 2 v4.1.3 (https://startbootstrap.com/theme/sb-admin-2) 3 | * Copyright 2013-2021 Start Bootstrap 4 | * Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-sb-admin-2/blob/master/LICENSE) 5 | */ 6 | 7 | !function(l){"use strict";l("#sidebarToggle, #sidebarToggleTop").on("click",function(e){l("body").toggleClass("sidebar-toggled"),l(".sidebar").toggleClass("toggled"),l(".sidebar").hasClass("toggled")&&l(".sidebar .collapse").collapse("hide")}),l(window).resize(function(){l(window).width()<768&&l(".sidebar .collapse").collapse("hide"),l(window).width()<480&&!l(".sidebar").hasClass("toggled")&&(l("body").addClass("sidebar-toggled"),l(".sidebar").addClass("toggled"),l(".sidebar .collapse").collapse("hide"))}),l("body.fixed-nav .sidebar").on("mousewheel DOMMouseScroll wheel",function(e){var o;768 5 | 9 |

10 |

Welcome to PythonCMS! 👋

11 |

12 | Please sign-in to your account and start the adventure 13 |

14 | 15 |
21 |
22 | {{ form.email.label }} {{ form.email() }} {% if 23 | form.email.errors %} 24 |
    25 | {% for error in form.user_id.errors %} 26 |
  • {{ error }}
  • 27 | {% endfor %} 28 |
29 | {% endif %} 30 |
31 |
32 |
33 | {{form.password.label}} 34 | 35 | Forgot Password? 36 | 37 |
38 |
39 | {{ form.password() }} {% if form.password.errors %} 40 |
    41 | {% for error in form.password.errors %} 42 |
  • {{ error }}
  • 43 | {% endfor %} 44 |
45 | {% endif %} 46 |
47 |
48 |
49 |
50 | 55 | 58 |
59 |
60 | 61 | 66 |
67 | 73 |
74 |
75 | 76 |

77 | New on our platform? 78 | 79 | Create an account 80 | 81 |

82 | {%endblock%} -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/register.html: -------------------------------------------------------------------------------- 1 | {%extends 'sbadmin/authbase.html'%} 2 | 3 | {%block content%} 4 | 5 |

Adventure starts here 🚀

6 |

Make your app management easy and fun!

7 | 8 |
9 |
10 | 11 | 12 | {{ form.email(class_="form-control", placeholder="Email", autocomplete="off", autofocus=true) }} 13 |
    14 | {% for error in form.email.errors %} 15 |
  • {{ error }}
  • 16 | {% endfor %} 17 |
18 |
19 |
20 | 21 |
22 | {{ form.password(class_="form-control", placeholder="Password") }} 23 | 24 | 25 | 26 |
27 |
    28 | {% for error in form.password.errors %} 29 |
  • {{ error }}
  • 30 | {% endfor %} 31 |
32 |
33 |
34 | 35 |
36 | {{ form.confirm(class_="form-control", placeholder="Confirm Password") }} 37 | 38 | 39 |
40 |
    41 | {% for error in form.password.errors %} 42 |
  • {{ error }}
  • 43 | {% endfor %} 44 |
45 |
46 | 47 |
48 |
49 | 50 | 54 |
55 |
56 | 57 | 58 |
59 | 60 |

61 | Already have an account? 62 | 63 | Sign in instead 64 | 65 |

66 | {%endblock%} -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/unconfirmed.html: -------------------------------------------------------------------------------- 1 | {%extends 'sbadmin/authbase.html' %} 2 | 3 | {%block content%} 4 |

Welcome to PythonCMS! 👋

5 | 6 |
7 | 8 | 9 |
10 |

11 | 12 |

You have not confirmed your account. Email confirmation link was sent to {{ current_user.email }}. Please check your inbox and your spam folder.

13 | 14 | Didn't get the email? Resend 15 |
16 | New on our platform? 17 | 18 | Create an account 19 | 20 | 21 |

22 | {%endblock%} 23 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/vendor/datatables/dataTables.bootstrap4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 4 integration 3 | ©2011-2017 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return c(d,a,a.document)}:c(jQuery,window,document)})(function(c,a,d,m){var f=c.fn.dataTable;c.extend(!0,f.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", 6 | renderer:"bootstrap"});c.extend(f.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap4",sFilterInput:"form-control form-control-sm",sLengthSelect:"custom-select custom-select-sm form-control form-control-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,b,m=function(a){a.preventDefault(); 7 | !c(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")};l=0;for(h=f.length;l", 8 | {"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof b?a.sTableId+"_"+b:null}).append(c("",{href:"#","aria-controls":a.sTableId,"aria-label":u[b],"data-dt-idx":p,tabindex:a.iTabIndex,"class":"page-link"}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:b},m),p++)}},i;try{i=c(h).find(d.activeElement).data("dt-idx")}catch(v){}q(c(h).empty().html('
    ').children("ul"),s);i!==m&&c(h).find("[data-dt-idx="+i+"]").trigger("focus")};return f}); 9 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/vendor/jquery-easing/jquery.easing.compatibility.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Easing Compatibility v1 - http://gsgd.co.uk/sandbox/jquery/easing 3 | * 4 | * Adds compatibility for applications that use the pre 1.2 easing names 5 | * 6 | * Copyright (c) 2007 George Smith 7 | * Licensed under the MIT License: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | */ 10 | 11 | (function($){ 12 | $.extend( $.easing, 13 | { 14 | easeIn: function (x, t, b, c, d) { 15 | return $.easing.easeInQuad(x, t, b, c, d); 16 | }, 17 | easeOut: function (x, t, b, c, d) { 18 | return $.easing.easeOutQuad(x, t, b, c, d); 19 | }, 20 | easeInOut: function (x, t, b, c, d) { 21 | return $.easing.easeInOutQuad(x, t, b, c, d); 22 | }, 23 | expoin: function(x, t, b, c, d) { 24 | return $.easing.easeInExpo(x, t, b, c, d); 25 | }, 26 | expoout: function(x, t, b, c, d) { 27 | return $.easing.easeOutExpo(x, t, b, c, d); 28 | }, 29 | expoinout: function(x, t, b, c, d) { 30 | return $.easing.easeInOutExpo(x, t, b, c, d); 31 | }, 32 | bouncein: function(x, t, b, c, d) { 33 | return $.easing.easeInBounce(x, t, b, c, d); 34 | }, 35 | bounceout: function(x, t, b, c, d) { 36 | return $.easing.easeOutBounce(x, t, b, c, d); 37 | }, 38 | bounceinout: function(x, t, b, c, d) { 39 | return $.easing.easeInOutBounce(x, t, b, c, d); 40 | }, 41 | elasin: function(x, t, b, c, d) { 42 | return $.easing.easeInElastic(x, t, b, c, d); 43 | }, 44 | elasout: function(x, t, b, c, d) { 45 | return $.easing.easeOutElastic(x, t, b, c, d); 46 | }, 47 | elasinout: function(x, t, b, c, d) { 48 | return $.easing.easeInOutElastic(x, t, b, c, d); 49 | }, 50 | backin: function(x, t, b, c, d) { 51 | return $.easing.easeInBack(x, t, b, c, d); 52 | }, 53 | backout: function(x, t, b, c, d) { 54 | return $.easing.easeOutBack(x, t, b, c, d); 55 | }, 56 | backinout: function(x, t, b, c, d) { 57 | return $.easing.easeInOutBack(x, t, b, c, d); 58 | } 59 | });})(jQuery); 60 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sbadmin/vendor/jquery-easing/jquery.easing.min.js: -------------------------------------------------------------------------------- 1 | (function(factory){if(typeof define==="function"&&define.amd){define(["jquery"],function($){return factory($)})}else if(typeof module==="object"&&typeof module.exports==="object"){exports=factory(require("jquery"))}else{factory(jQuery)}})(function($){$.easing.jswing=$.easing.swing;var pow=Math.pow,sqrt=Math.sqrt,sin=Math.sin,cos=Math.cos,PI=Math.PI,c1=1.70158,c2=c1*1.525,c3=c1+1,c4=2*PI/3,c5=2*PI/4.5;function bounceOut(x){var n1=7.5625,d1=2.75;if(x<1/d1){return n1*x*x}else if(x<2/d1){return n1*(x-=1.5/d1)*x+.75}else if(x<2.5/d1){return n1*(x-=2.25/d1)*x+.9375}else{return n1*(x-=2.625/d1)*x+.984375}}$.extend($.easing,{def:"easeOutQuad",swing:function(x){return $.easing[$.easing.def](x)},easeInQuad:function(x){return x*x},easeOutQuad:function(x){return 1-(1-x)*(1-x)},easeInOutQuad:function(x){return x<.5?2*x*x:1-pow(-2*x+2,2)/2},easeInCubic:function(x){return x*x*x},easeOutCubic:function(x){return 1-pow(1-x,3)},easeInOutCubic:function(x){return x<.5?4*x*x*x:1-pow(-2*x+2,3)/2},easeInQuart:function(x){return x*x*x*x},easeOutQuart:function(x){return 1-pow(1-x,4)},easeInOutQuart:function(x){return x<.5?8*x*x*x*x:1-pow(-2*x+2,4)/2},easeInQuint:function(x){return x*x*x*x*x},easeOutQuint:function(x){return 1-pow(1-x,5)},easeInOutQuint:function(x){return x<.5?16*x*x*x*x*x:1-pow(-2*x+2,5)/2},easeInSine:function(x){return 1-cos(x*PI/2)},easeOutSine:function(x){return sin(x*PI/2)},easeInOutSine:function(x){return-(cos(PI*x)-1)/2},easeInExpo:function(x){return x===0?0:pow(2,10*x-10)},easeOutExpo:function(x){return x===1?1:1-pow(2,-10*x)},easeInOutExpo:function(x){return x===0?0:x===1?1:x<.5?pow(2,20*x-10)/2:(2-pow(2,-20*x+10))/2},easeInCirc:function(x){return 1-sqrt(1-pow(x,2))},easeOutCirc:function(x){return sqrt(1-pow(x-1,2))},easeInOutCirc:function(x){return x<.5?(1-sqrt(1-pow(2*x,2)))/2:(sqrt(1-pow(-2*x+2,2))+1)/2},easeInElastic:function(x){return x===0?0:x===1?1:-pow(2,10*x-10)*sin((x*10-10.75)*c4)},easeOutElastic:function(x){return x===0?0:x===1?1:pow(2,-10*x)*sin((x*10-.75)*c4)+1},easeInOutElastic:function(x){return x===0?0:x===1?1:x<.5?-(pow(2,20*x-10)*sin((20*x-11.125)*c5))/2:pow(2,-20*x+10)*sin((20*x-11.125)*c5)/2+1},easeInBack:function(x){return c3*x*x*x-c1*x*x},easeOutBack:function(x){return 1+c3*pow(x-1,3)+c1*pow(x-1,2)},easeInOutBack:function(x){return x<.5?pow(2*x,2)*((c2+1)*2*x-c2)/2:(pow(2*x-2,2)*((c2+1)*(x*2-2)+c2)+2)/2},easeInBounce:function(x){return 1-bounceOut(1-x)},easeOutBounce:bounceOut,easeInOutBounce:function(x){return x<.5?(1-bounceOut(1-2*x))/2:(1+bounceOut(2*x-1))/2}})}); -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Config 3 | * ------------------------------------------------------------------------------------- 4 | * ! IMPORTANT: Make sure you clear the browser local storage In order to see the config changes in the template. 5 | * ! To clear local storage: (https://www.leadshook.com/help/how-to-clear-local-storage-in-google-chrome-browser/). 6 | */ 7 | 8 | 'use strict'; 9 | 10 | // JS global variables 11 | let config = { 12 | colors: { 13 | primary: '#696cff', 14 | secondary: '#8592a3', 15 | success: '#71dd37', 16 | info: '#03c3ec', 17 | warning: '#ffab00', 18 | danger: '#ff3e1d', 19 | dark: '#233446', 20 | black: '#000', 21 | white: '#fff', 22 | body: '#f4f5fb', 23 | headingColor: '#566a7f', 24 | axisColor: '#a1acb8', 25 | borderColor: '#eceef1' 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/extended-ui-perfect-scrollbar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Perfect Scrollbar 3 | */ 4 | 'use strict'; 5 | 6 | document.addEventListener('DOMContentLoaded', function () { 7 | (function () { 8 | const verticalExample = document.getElementById('vertical-example'), 9 | horizontalExample = document.getElementById('horizontal-example'), 10 | horizVertExample = document.getElementById('both-scrollbars-example'); 11 | 12 | // Vertical Example 13 | // -------------------------------------------------------------------- 14 | if (verticalExample) { 15 | new PerfectScrollbar(verticalExample, { 16 | wheelPropagation: false 17 | }); 18 | } 19 | 20 | // Horizontal Example 21 | // -------------------------------------------------------------------- 22 | if (horizontalExample) { 23 | new PerfectScrollbar(horizontalExample, { 24 | wheelPropagation: false, 25 | suppressScrollY: true 26 | }); 27 | } 28 | 29 | // Both vertical and Horizontal Example 30 | // -------------------------------------------------------------------- 31 | if (horizVertExample) { 32 | new PerfectScrollbar(horizVertExample, { 33 | wheelPropagation: false 34 | }); 35 | } 36 | })(); 37 | }); 38 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/form-basic-inputs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Form Basic Inputs 3 | */ 4 | 5 | 'use strict'; 6 | 7 | (function () { 8 | // Indeterminate checkbox 9 | const checkbox = document.getElementById('defaultCheck2'); 10 | checkbox.indeterminate = true; 11 | })(); 12 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/pages-account-settings-account.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Account Settings - Account 3 | */ 4 | 5 | 'use strict'; 6 | 7 | document.addEventListener('DOMContentLoaded', function (e) { 8 | (function () { 9 | const deactivateAcc = document.querySelector('#formAccountDeactivation'); 10 | 11 | // Update/reset user image of account page 12 | let accountUserImage = document.getElementById('uploadedAvatar'); 13 | const fileInput = document.querySelector('.account-file-input'), 14 | resetFileInput = document.querySelector('.account-image-reset'); 15 | 16 | if (accountUserImage) { 17 | const resetImage = accountUserImage.src; 18 | fileInput.onchange = () => { 19 | if (fileInput.files[0]) { 20 | accountUserImage.src = window.URL.createObjectURL(fileInput.files[0]); 21 | } 22 | }; 23 | resetFileInput.onclick = () => { 24 | fileInput.value = ''; 25 | accountUserImage.src = resetImage; 26 | }; 27 | } 28 | })(); 29 | }); 30 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/ui-modals.js: -------------------------------------------------------------------------------- 1 | /** 2 | * UI Modals 3 | */ 4 | 5 | 'use strict'; 6 | 7 | (function () { 8 | // On hiding modal, remove iframe video/audio to stop playing 9 | const youTubeModal = document.querySelector('#youTubeModal'), 10 | youTubeModalVideo = youTubeModal.querySelector('iframe'); 11 | youTubeModal.addEventListener('hidden.bs.modal', function () { 12 | youTubeModalVideo.setAttribute('src', ''); 13 | }); 14 | 15 | // Function to get and auto play youTube video 16 | const autoPlayYouTubeModal = function () { 17 | const modalTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="modal"]')); 18 | modalTriggerList.map(function (modalTriggerEl) { 19 | modalTriggerEl.onclick = function () { 20 | const theModal = this.getAttribute('data-bs-target'), 21 | videoSRC = this.getAttribute('data-theVideo'), 22 | videoSRCauto = `${videoSRC}?autoplay=1`, 23 | modalVideo = document.querySelector(`${theModal} iframe`); 24 | if (modalVideo) { 25 | modalVideo.setAttribute('src', videoSRCauto); 26 | } 27 | }; 28 | }); 29 | }; 30 | 31 | // Calling function on load 32 | autoPlayYouTubeModal(); 33 | })(); 34 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/ui-popover.js: -------------------------------------------------------------------------------- 1 | // /** 2 | // * UI Tooltips & Popovers 3 | // */ 4 | 5 | 'use strict'; 6 | 7 | (function () { 8 | const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); 9 | const popoverList = popoverTriggerList.map(function (popoverTriggerEl) { 10 | // added { html: true, sanitize: false } option to render button in content area of popover 11 | return new bootstrap.Popover(popoverTriggerEl, { html: true, sanitize: false }); 12 | }); 13 | })(); 14 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/js/ui-toasts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * UI Toasts 3 | */ 4 | 5 | 'use strict'; 6 | 7 | (function () { 8 | // Bootstrap toasts example 9 | // -------------------------------------------------------------------- 10 | const toastPlacementExample = document.querySelector('.toast-placement-ex'), 11 | toastPlacementBtn = document.querySelector('#showToastPlacement'); 12 | let selectedType, selectedPlacement, toastPlacement; 13 | 14 | // Dispose toast when open another 15 | function toastDispose(toast) { 16 | if (toast && toast._element !== null) { 17 | if (toastPlacementExample) { 18 | toastPlacementExample.classList.remove(selectedType); 19 | DOMTokenList.prototype.remove.apply(toastPlacementExample.classList, selectedPlacement); 20 | } 21 | toast.dispose(); 22 | } 23 | } 24 | // Placement Button click 25 | if (toastPlacementBtn) { 26 | toastPlacementBtn.onclick = function () { 27 | if (toastPlacement) { 28 | toastDispose(toastPlacement); 29 | } 30 | selectedType = document.querySelector('#selectTypeOpt').value; 31 | selectedPlacement = document.querySelector('#selectPlacement').value.split(' '); 32 | 33 | toastPlacementExample.classList.add(selectedType); 34 | DOMTokenList.prototype.add.apply(toastPlacementExample.classList, selectedPlacement); 35 | toastPlacement = new bootstrap.Toast(toastPlacementExample); 36 | toastPlacement.show(); 37 | }; 38 | } 39 | })(); 40 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/css/pages/page-account-settings.css: -------------------------------------------------------------------------------- 1 | .api-key-actions { 2 | position: absolute !important; 3 | top: 0.75rem; 4 | right: 0.5rem; 5 | } 6 | 7 | /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBhZ2VzL3BhZ2UtYWNjb3VudC1zZXR0aW5ncy5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFDRSw2QkFBNkI7RUFDN0IsWUFBWTtFQUNaLGFBQWE7QUFDZiIsImZpbGUiOiJwYWdlcy9wYWdlLWFjY291bnQtc2V0dGluZ3MuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLmFwaS1rZXktYWN0aW9ucyB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZSAhaW1wb3J0YW50O1xuICB0b3A6IDAuNzVyZW07XG4gIHJpZ2h0OiAwLjVyZW07XG59XG4iXX0= */ 8 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/css/pages/page-icons.css: -------------------------------------------------------------------------------- 1 | #icons-container .icon-card { 2 | width: 128px; 3 | } 4 | #icons-container .icon-card i { 5 | font-size: 2rem; 6 | } 7 | 8 | @media (max-width: 1024px) { 9 | #icons-container .icon-card { 10 | width: 126px; 11 | } 12 | } 13 | @media (max-width: 767.98px) { 14 | #icons-container .icon-card { 15 | width: 131px; 16 | } 17 | } 18 | @media (max-width: 414px) { 19 | #icons-container .icon-card { 20 | width: 110px; 21 | } 22 | } 23 | @media (max-width: 375px) { 24 | #icons-container .icon-card { 25 | width: 150px; 26 | } 27 | } 28 | 29 | /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBhZ2VzL3BhZ2UtaWNvbnMuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsWUFBWTtBQUNkO0FBQ0E7RUFDRSxlQUFlO0FBQ2pCOztBQUVBO0VBQ0U7SUFDRSxZQUFZO0VBQ2Q7QUFDRjtBQUNBO0VBQ0U7SUFDRSxZQUFZO0VBQ2Q7QUFDRjtBQUNBO0VBQ0U7SUFDRSxZQUFZO0VBQ2Q7QUFDRjtBQUNBO0VBQ0U7SUFDRSxZQUFZO0VBQ2Q7QUFDRiIsImZpbGUiOiJwYWdlcy9wYWdlLWljb25zLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIiNpY29ucy1jb250YWluZXIgLmljb24tY2FyZCB7XG4gIHdpZHRoOiAxMjhweDtcbn1cbiNpY29ucy1jb250YWluZXIgLmljb24tY2FyZCBpIHtcbiAgZm9udC1zaXplOiAycmVtO1xufVxuXG5AbWVkaWEgKG1heC13aWR0aDogMTAyNHB4KSB7XG4gICNpY29ucy1jb250YWluZXIgLmljb24tY2FyZCB7XG4gICAgd2lkdGg6IDEyNnB4O1xuICB9XG59XG5AbWVkaWEgKG1heC13aWR0aDogNzY3Ljk4cHgpIHtcbiAgI2ljb25zLWNvbnRhaW5lciAuaWNvbi1jYXJkIHtcbiAgICB3aWR0aDogMTMxcHg7XG4gIH1cbn1cbkBtZWRpYSAobWF4LXdpZHRoOiA0MTRweCkge1xuICAjaWNvbnMtY29udGFpbmVyIC5pY29uLWNhcmQge1xuICAgIHdpZHRoOiAxMTBweDtcbiAgfVxufVxuQG1lZGlhIChtYXgtd2lkdGg6IDM3NXB4KSB7XG4gICNpY29ucy1jb250YWluZXIgLmljb24tY2FyZCB7XG4gICAgd2lkdGg6IDE1MHB4O1xuICB9XG59XG4iXX0= */ 30 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/css/pages/page-misc.css: -------------------------------------------------------------------------------- 1 | .misc-wrapper { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | min-height: calc(100vh - (1.625rem * 2)); 7 | text-align: center; 8 | } 9 | 10 | /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBhZ2VzL3BhZ2UtbWlzYy5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFDRSxhQUFhO0VBQ2Isc0JBQXNCO0VBQ3RCLHVCQUF1QjtFQUN2QixtQkFBbUI7RUFDbkIsd0NBQXdDO0VBQ3hDLGtCQUFrQjtBQUNwQiIsImZpbGUiOiJwYWdlcy9wYWdlLW1pc2MuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLm1pc2Mtd3JhcHBlciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBtaW4taGVpZ2h0OiBjYWxjKDEwMHZoIC0gKDEuNjI1cmVtICogMikpO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG59XG4iXX0= */ 11 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.eot -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.ttf -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.woff -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/back/sneat/assets/vendor/fonts/boxicons/boxicons.woff2 -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/libs/highlight/highlight-github.css: -------------------------------------------------------------------------------- 1 | @import '../../node_modules/highlight.js/styles/github.css'; 2 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/assets/vendor/libs/highlight/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Atom One Light by Daniel Gamage 4 | Original One Light Syntax theme from https://github.com/atom/one-light-syntax 5 | 6 | base: #fafafa 7 | mono-1: #383a42 8 | mono-2: #686b77 9 | mono-3: #a0a1a7 10 | hue-1: #0184bb 11 | hue-2: #4078f2 12 | hue-3: #a626a4 13 | hue-4: #50a14f 14 | hue-5: #e45649 15 | hue-5-2: #c91243 16 | hue-6: #986801 17 | hue-6-2: #c18401 18 | 19 | */ 20 | .hljs { 21 | display: block; 22 | overflow-x: auto; 23 | padding: 0.5em; 24 | color: #383a42; 25 | background: #fafafa; 26 | } 27 | 28 | .hljs-comment, 29 | .hljs-quote { 30 | color: #a0a1a7; 31 | font-style: italic; 32 | } 33 | 34 | .hljs-doctag, 35 | .hljs-keyword, 36 | .hljs-formula { 37 | color: #a626a4; 38 | } 39 | 40 | .hljs-section, 41 | .hljs-name, 42 | .hljs-selector-tag, 43 | .hljs-deletion, 44 | .hljs-subst { 45 | color: #e45649; 46 | } 47 | 48 | .hljs-literal { 49 | color: #0184bb; 50 | } 51 | 52 | .hljs-string, 53 | .hljs-regexp, 54 | .hljs-addition, 55 | .hljs-attribute, 56 | .hljs-meta-string { 57 | color: #50a14f; 58 | } 59 | 60 | .hljs-built_in, 61 | .hljs-class .hljs-title { 62 | color: #c18401; 63 | } 64 | 65 | .hljs-attr, 66 | .hljs-variable, 67 | .hljs-template-variable, 68 | .hljs-type, 69 | .hljs-selector-class, 70 | .hljs-selector-attr, 71 | .hljs-selector-pseudo, 72 | .hljs-number { 73 | color: #986801; 74 | } 75 | 76 | .hljs-symbol, 77 | .hljs-bullet, 78 | .hljs-link, 79 | .hljs-meta, 80 | .hljs-selector-id, 81 | .hljs-title { 82 | color: #4078f2; 83 | } 84 | 85 | .hljs-emphasis { 86 | font-style: italic; 87 | } 88 | 89 | .hljs-strong { 90 | font-weight: bold; 91 | } 92 | 93 | .hljs-link { 94 | text-decoration: underline; 95 | } 96 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/index.html: -------------------------------------------------------------------------------- 1 | {%extends 'sneat/base.html'%} 2 | 3 | 4 | 5 | {%block content%} 6 |
    7 |
    19 | {%endblock%} 20 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ARJ", 3 | "version": "1.0.20000000000003" 4 | } 5 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/login.html: -------------------------------------------------------------------------------- 1 | {%extends 'sneat/authbase.html' %} 2 | 3 | {%block content%} 4 |

    Welcome to PythonCMS! 👋

    5 |

    Please sign-in to your account and start the adventure

    6 | 7 |
    8 |
    9 | {{ form.email.label }} 10 | {{ form.email() }} 11 | {% if form.email.errors %} 12 |
      13 | {% for error in form.user_id.errors %} 14 |
    • {{ error }}
    • 15 | {% endfor %} 16 |
    17 | {% endif %} 18 |
    19 |
    20 |
    21 | {{form.password.label}} 22 | 23 | Forgot Password? 24 | 25 |
    26 |
    27 | {{ form.password() }} 28 | {% if form.password.errors %} 29 |
      30 | {% for error in form.password.errors %} 31 |
    • {{ error }}
    • 32 | {% endfor %} 33 |
    34 | {% endif %} 35 | 36 |
    37 |
    38 |
    39 |
    40 | 41 | 42 |
    43 |
    44 | 45 | 46 |
    47 | 48 |
    49 |
    50 | 51 |

    52 | New on our platform? 53 | 54 | Create an account 55 | 56 |

    57 | {%endblock%} 58 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/register.html: -------------------------------------------------------------------------------- 1 | {%extends 'sneat/authbase.html' %} 2 | 3 | {%block content%} 4 | 5 |

    Adventure starts here 🚀

    6 |

    Make your app management easy and fun!

    7 | 8 |
    9 |
    10 | 11 | 12 | {{ form.email(class_="form-control", placeholder="Email", autocomplete="off", autofocus=true) }} 13 |
      14 | {% for error in form.email.errors %} 15 |
    • {{ error }}
    • 16 | {% endfor %} 17 |
    18 |
    19 |
    20 | 21 |
    22 | {{ form.password(class_="form-control", placeholder="Password") }} 23 | 24 | 25 | 26 |
    27 |
      28 | {% for error in form.password.errors %} 29 |
    • {{ error }}
    • 30 | {% endfor %} 31 |
    32 |
    33 |
    34 | 35 |
    36 | {{ form.confirm(class_="form-control", placeholder="Confirm Password") }} 37 | 38 | 39 | 40 |
    41 |
      42 | {% for error in form.password.errors %} 43 |
    • {{ error }}
    • 44 | {% endfor %} 45 |
    46 |
    47 | 48 |
    49 |
    50 | 51 | 55 |
    56 |
    57 | 58 | 59 |
    60 | 61 |

    62 | Already have an account? 63 | 64 | Sign in instead 65 | 66 |

    67 | {%endblock%} 68 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/sections/resource_end_body.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/sections/resource_head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/styles.css: -------------------------------------------------------------------------------- 1 | 2 | html { 3 | scroll-behavior: smooth; 4 | } 5 | 6 | .suggest { 7 | 8 | } 9 | 10 | .suggest span { 11 | padding-left: 5px; 12 | padding-right: 5px; 13 | margin: 5px; 14 | min-width: 50px; 15 | } 16 | 17 | .shopyo-link{ 18 | text-decoration: inherit; 19 | color: inherit; 20 | } 21 | 22 | .shopyo-link:hover{ 23 | text-decoration: inherit; 24 | color: inherit; 25 | } 26 | 27 | .card-menu{ 28 | display: inline-block; 29 | min-width: 200px; 30 | margin-top: 10px; 31 | } 32 | .card-menu-icon{ 33 | font-size: 40px; 34 | color: #3f497d; 35 | } 36 | 37 | .shopyo-alert{ 38 | 39 | } 40 | 41 | #flashed-messages{ 42 | padding: 5px; 43 | position: fixed; 44 | right: 5px; 45 | top: 5px; 46 | z-index: 10; 47 | height: 300px; 48 | overflow-y: scroll; 49 | 50 | } 51 | 52 | #flashed-messages::-webkit-scrollbar { 53 | display: none; 54 | } 55 | 56 | /* Hide scrollbar for IE and Edge */ 57 | #flashed-messages{ 58 | -ms-overflow-style: none; 59 | } 60 | 61 | .yo-admin-nav-icon{ 62 | font-size: 30px 63 | } 64 | .form-inline a{ 65 | font-size: 15px; 66 | } 67 | 68 | #page-content-wrapper{ 69 | background-color: #f1f1f1; 70 | } 71 | 72 | .yo-sidebar-item{ 73 | background-color: #fff; 74 | border: none; 75 | } 76 | .yo-sidebar-item:hover{ 77 | background-color: #ece0fd; 78 | color:#6200ee; 79 | border: none; 80 | } 81 | 82 | .shopyo-main-area{ 83 | background: rgb(131,58,180); 84 | background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 30%, rgba(252,176,69,1) 100%); 85 | } 86 | 87 | #page-content-wrapper{ 88 | background: rgb(131,58,180); 89 | background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,75,29,1) 0%, rgba(252,176,69,1) 100%); 90 | color: black; 91 | } 92 | -------------------------------------------------------------------------------- /pythoncms/static/themes/back/sneat/unconfirmed.html: -------------------------------------------------------------------------------- 1 | {%extends 'sneat/authbase.html' %} 2 | 3 | {%block content%} 4 |

    Welcome to PythonCMS! 👋

    5 | 6 |
    7 | 8 | 9 |
    10 |

    11 | 12 |

    You have not confirmed your account. Email confirmation link was sent to {{ current_user.email }}. Please check your inbox and your spam folder.

    13 | 14 | Didn't get the email? Resend 15 |
    16 | New on our platform? 17 | 18 | Create an account 19 | 20 | 21 |

    22 | {%endblock%} 23 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/README.txt: -------------------------------------------------------------------------------- 1 | Editorial by HTML5 UP 2 | html5up.net | @ajlkn 3 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 4 | 5 | 6 | Say hello to Editorial, a blog/magazine-ish template built around a toggleable "locking" 7 | sidebar (scroll down to see what I mean) and an accordion-style menu. Not the usual landing 8 | page/portfolio affair you'd expect to see at HTML5 UP, but I figured for my 41st (!!!) 9 | template I'd change it up a little. Enjoy :) 10 | 11 | Demo images* courtesy of Unsplash, a radtastic collection of CC0 (public domain) images 12 | you can use for pretty much whatever. 13 | 14 | (* = not included) 15 | 16 | AJ 17 | aj@lkn.io | @ajlkn 18 | 19 | 20 | Credits: 21 | 22 | Demo Images: 23 | Unsplash (unsplash.com) 24 | 25 | Icons: 26 | Font Awesome (fontawesome.io) 27 | 28 | Other: 29 | jQuery (jquery.com) 30 | Responsive Tools (github.com/ajlkn/responsive-tools) 31 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/js/breakpoints.min.js: -------------------------------------------------------------------------------- 1 | /* breakpoints.js v1.0 | @ajlkn | MIT licensed */ 2 | var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads or stops resizing. 40 | &.is-preload, 41 | &.is-resizing { 42 | *, *:before, *:after { 43 | @include vendor('animation', 'none !important'); 44 | @include vendor('transition', 'none !important'); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | 34 | body { 35 | line-height: 1; 36 | } 37 | 38 | ol, ul { 39 | list-style:none; 40 | } 41 | 42 | blockquote, q { 43 | quotes: none; 44 | 45 | &:before, 46 | &:after { 47 | content: ''; 48 | content: none; 49 | } 50 | } 51 | 52 | table { 53 | border-collapse: collapse; 54 | border-spacing: 0; 55 | } 56 | 57 | body { 58 | -webkit-text-size-adjust: none; 59 | } 60 | 61 | mark { 62 | background-color: transparent; 63 | color: inherit; 64 | } 65 | 66 | input::-moz-focus-inner { 67 | border: 0; 68 | padding: 0; 69 | } 70 | 71 | input, select, textarea { 72 | -moz-appearance: none; 73 | -webkit-appearance: none; 74 | -ms-appearance: none; 75 | appearance: none; 76 | } 77 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid 1px _palette(border); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5em; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_button.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Button */ 8 | 9 | input[type="submit"], 10 | input[type="reset"], 11 | input[type="button"], 12 | button, 13 | .button { 14 | @include vendor('appearance', 'none'); 15 | @include vendor('transition', ( 16 | 'background-color #{_duration(transition)} ease-in-out', 17 | 'color #{_duration(transition)} ease-in-out' 18 | )); 19 | background-color: transparent; 20 | border-radius: _size(border-radius); 21 | border: 0; 22 | box-shadow: inset 0 0 0 2px _palette(accent); 23 | color: _palette(accent) !important; 24 | cursor: pointer; 25 | display: inline-block; 26 | font-family: _font(family-heading); 27 | font-size: 0.8em; 28 | font-weight: _font(weight-heading); 29 | height: 3.5em; 30 | letter-spacing: _font(kerning-heading); 31 | line-height: 3.5em; 32 | padding: 0 2.25em; 33 | text-align: center; 34 | text-decoration: none; 35 | text-transform: uppercase; 36 | white-space: nowrap; 37 | 38 | &:hover { 39 | background-color: transparentize(_palette(accent), 0.95); 40 | } 41 | 42 | &:active { 43 | background-color: transparentize(_palette(accent), 0.85); 44 | } 45 | 46 | &.icon { 47 | &:before { 48 | margin-right: 0.5em; 49 | } 50 | } 51 | 52 | &.fit { 53 | width: 100%; 54 | } 55 | 56 | &.small { 57 | font-size: 0.6em; 58 | } 59 | 60 | &.large { 61 | font-size: 1em; 62 | height: 3.65em; 63 | line-height: 3.65em; 64 | } 65 | 66 | &.primary { 67 | background-color: _palette(accent); 68 | box-shadow: none; 69 | color: _palette(bg) !important; 70 | 71 | &:hover { 72 | background-color: lighten(_palette(accent), 3); 73 | } 74 | 75 | &:active { 76 | background-color: darken(_palette(accent), 3); 77 | } 78 | } 79 | 80 | &.disabled, 81 | &:disabled { 82 | @include vendor('pointer-events', 'none'); 83 | opacity: 0.25; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_contact.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Contact */ 8 | 9 | ul.contact { 10 | list-style: none; 11 | padding: 0; 12 | 13 | li { 14 | @include icon; 15 | border-top: solid 1px _palette(border); 16 | margin: 1.5em 0 0 0; 17 | padding: 1.5em 0 0 3em; 18 | position: relative; 19 | 20 | &:before { 21 | color: _palette(accent); 22 | display: inline-block; 23 | font-size: 1.5em; 24 | height: 1.125em; 25 | left: 0; 26 | line-height: 1.125em; 27 | position: absolute; 28 | text-align: center; 29 | top: (1.5em / 1.5); 30 | width: 1.5em; 31 | } 32 | 33 | &:first-child { 34 | border-top: 0; 35 | margin-top: 0; 36 | padding-top: 0; 37 | 38 | &:before { 39 | top: 0; 40 | } 41 | } 42 | 43 | a { 44 | color: inherit; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | 14 | > .label { 15 | display: none; 16 | } 17 | 18 | &:before { 19 | line-height: inherit; 20 | } 21 | 22 | &.solid { 23 | &:before { 24 | font-weight: 900; 25 | } 26 | } 27 | 28 | &.brands { 29 | &:before { 30 | font-family: 'Font Awesome 5 Brands'; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 1em 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | 22 | .icon { 23 | color: inherit; 24 | 25 | &:before { 26 | font-size: 1.25em; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border-radius: _size(border-radius); 11 | border: 0; 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | border-radius: _size(border-radius); 17 | display: block; 18 | } 19 | 20 | &.left, 21 | &.right { 22 | max-width: 40%; 23 | 24 | img { 25 | width: 100%; 26 | } 27 | } 28 | 29 | &.left { 30 | float: left; 31 | padding: 0 1.5em 1em 0; 32 | top: 0.25em; 33 | } 34 | 35 | &.right { 36 | float: right; 37 | padding: 0 0 1em 1.5em; 38 | top: 0.25em; 39 | } 40 | 41 | &.fit { 42 | display: block; 43 | margin: 0 0 _size(element-margin) 0; 44 | width: 100%; 45 | 46 | img { 47 | width: 100%; 48 | } 49 | } 50 | 51 | &.main { 52 | display: block; 53 | margin: 0 0 (_size(element-margin) * 1.5) 0; 54 | width: 100%; 55 | 56 | img { 57 | width: 100%; 58 | } 59 | } 60 | } 61 | 62 | a.image { 63 | overflow: hidden; 64 | 65 | img { 66 | @include vendor('transition', 'transform #{_duration(transition)} ease'); 67 | } 68 | 69 | &:hover { 70 | img { 71 | @include vendor('transform', 'scale(1.075)'); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25em; 13 | 14 | li { 15 | padding-left: 0.25em; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1em; 23 | 24 | li { 25 | padding-left: 0.5em; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid 1px _palette(border); 34 | padding: 0.5em 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_mini-posts.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Mini Posts */ 8 | 9 | .mini-posts { 10 | article { 11 | border-top: solid 1px _palette(border); 12 | margin-top: _size(element-margin); 13 | padding-top: _size(element-margin); 14 | 15 | .image { 16 | display: block; 17 | margin: 0 0 (_size(element-margin) * 0.75) 0; 18 | 19 | img { 20 | display: block; 21 | width: 100%; 22 | } 23 | } 24 | 25 | &:first-child { 26 | border-top: 0; 27 | margin-top: 0; 28 | padding-top: 0; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_pagination.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Pagination */ 8 | 9 | ul.pagination { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding-left: 0; 17 | vertical-align: middle; 18 | 19 | > .page { 20 | @include vendor('transition', ( 21 | 'background-color #{_duration(transition)} ease-in-out', 22 | 'color #{_duration(transition)} ease-in-out' 23 | )); 24 | border-bottom: 0; 25 | border-radius: _size(border-radius); 26 | display: inline-block; 27 | font-size: 0.8em; 28 | font-weight: _font(weight-bold); 29 | height: 2em; 30 | line-height: 2em; 31 | margin: 0 0.125em; 32 | min-width: 2em; 33 | padding: 0 0.5em; 34 | text-align: center; 35 | 36 | &.active { 37 | background-color: _palette(accent); 38 | color: _palette(bg) !important; 39 | 40 | &:hover { 41 | background-color: lighten(_palette(accent), 3); 42 | } 43 | 44 | &:active { 45 | background-color: darken(_palette(accent), 3); 46 | } 47 | } 48 | } 49 | 50 | &:first-child { 51 | padding-right: 0.75em; 52 | } 53 | 54 | &:last-child { 55 | padding-left: 0.75em; 56 | } 57 | } 58 | 59 | @include breakpoint('<=xsmall') { 60 | li { 61 | &:nth-child(n+2):nth-last-child(n+2) { 62 | display: none; 63 | } 64 | 65 | &:first-child { 66 | padding-right: 0; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(1.5em); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(1.5em, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(1.5em, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(1.5em, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(1.5em, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(1.5em, 'xsmall'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | font-family: _font(family-heading); 18 | font-size: 1em; 19 | font-weight: _font(weight-heading-alt); 20 | letter-spacing: _font(kerning-heading); 21 | margin-top: -0.5em; 22 | text-transform: uppercase; 23 | } 24 | 25 | &.major { 26 | > :last-child { 27 | border-bottom: solid 3px _palette(accent); 28 | display: inline-block; 29 | margin: 0 0 _size(element-margin) 0; 30 | padding: 0 0.75em 0.5em 0; 31 | } 32 | } 33 | 34 | &.main { 35 | > :last-child { 36 | margin: 0 0 (_size(element-margin) * 0.5) 0; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/components/_table.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Table */ 8 | 9 | .table-wrapper { 10 | -webkit-overflow-scrolling: touch; 11 | overflow-x: auto; 12 | } 13 | 14 | table { 15 | margin: 0 0 _size(element-margin) 0; 16 | width: 100%; 17 | 18 | tbody { 19 | tr { 20 | border: solid 1px _palette(border); 21 | border-left: 0; 22 | border-right: 0; 23 | 24 | &:nth-child(2n + 1) { 25 | background-color: _palette(border-bg); 26 | } 27 | } 28 | } 29 | 30 | td { 31 | padding: 0.75em 0.75em; 32 | } 33 | 34 | th { 35 | color: _palette(fg-bold); 36 | font-size: 0.9em; 37 | font-weight: _font(weight-bold); 38 | padding: 0 0.75em 0.75em 0.75em; 39 | text-align: left; 40 | } 41 | 42 | thead { 43 | border-bottom: solid 2px _palette(border); 44 | } 45 | 46 | tfoot { 47 | border-top: solid 2px _palette(border); 48 | } 49 | 50 | &.alt { 51 | border-collapse: separate; 52 | 53 | tbody { 54 | tr { 55 | td { 56 | border: solid 1px _palette(border); 57 | border-left-width: 0; 58 | border-top-width: 0; 59 | 60 | &:first-child { 61 | border-left-width: 1px; 62 | } 63 | } 64 | 65 | &:first-child { 66 | td { 67 | border-top-width: 1px; 68 | } 69 | } 70 | } 71 | } 72 | 73 | thead { 74 | border-bottom: 0; 75 | } 76 | 77 | tfoot { 78 | border-top: 0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_banner.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Banner */ 8 | 9 | #banner { 10 | @include padding(6em, 0); 11 | @include vendor('display', 'flex'); 12 | 13 | h1 { 14 | margin-top: -0.125em; 15 | } 16 | 17 | .content { 18 | @include vendor('flex-grow', '1'); 19 | @include vendor('flex-shrink', '1'); 20 | width: 50%; 21 | } 22 | 23 | .image { 24 | @include vendor('flex-grow', '0'); 25 | @include vendor('flex-shrink', '0'); 26 | display: block; 27 | margin: 0 0 _size(element-margin) (_size(element-margin) * 2); 28 | width: 50%; 29 | 30 | img { 31 | height: 100%; 32 | -moz-object-fit: cover; 33 | -webkit-object-fit: cover; 34 | -ms-object-fit: cover; 35 | object-fit: cover; 36 | -moz-object-position: center; 37 | -webkit-object-position: center; 38 | -ms-object-position: center; 39 | object-position: center; 40 | width: 100%; 41 | } 42 | } 43 | 44 | @include orientation(portrait) { 45 | @include vendor('flex-direction', 'column-reverse'); 46 | 47 | h1 { 48 | br { 49 | display: none; 50 | } 51 | } 52 | 53 | .content { 54 | @include vendor('flex-grow', '0'); 55 | @include vendor('flex-shrink', '0'); 56 | width: 100%; 57 | } 58 | 59 | .image { 60 | @include vendor('flex-grow', '0'); 61 | @include vendor('flex-shrink', '0'); 62 | margin: 0 0 (_size(element-margin) * 2) 0; 63 | height: 25em; 64 | max-height: 50vh; 65 | min-height: 18em; 66 | width: 100%; 67 | } 68 | 69 | @include breakpoint('<=xsmall') { 70 | .image { 71 | max-height: 35vh; 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Footer */ 8 | 9 | #footer { 10 | .copyright { 11 | color: _palette(fg-light); 12 | font-size: 0.9em; 13 | 14 | a { 15 | color: inherit; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_header.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Header */ 8 | 9 | #header { 10 | @include vendor('display', 'flex'); 11 | border-bottom: solid 5px _palette(accent); 12 | padding: 6em 0 1em 0; 13 | position: relative; 14 | 15 | > * { 16 | @include vendor('flex', '1'); 17 | margin-bottom: 0; 18 | } 19 | 20 | .logo { 21 | border-bottom: 0; 22 | color: inherit; 23 | font-family: _font(family-heading); 24 | font-size: 1.125em; 25 | } 26 | 27 | .icons { 28 | text-align: right; 29 | } 30 | 31 | @include breakpoint('<=xlarge') { 32 | padding-top: 5em; 33 | } 34 | 35 | @include breakpoint('<=small') { 36 | padding-top: 6.5em; 37 | 38 | .logo { 39 | font-size: 1.25em; 40 | margin: 0; 41 | } 42 | 43 | .icons { 44 | height: (6.25em / 1.25); 45 | line-height: (6.25em / 1.25); 46 | position: absolute; 47 | right: (-0.625em / 1.25); 48 | top: 0; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_main.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Main */ 8 | 9 | #main { 10 | @include vendor('flex-grow', '1'); 11 | @include vendor('flex-shrink', '1'); 12 | width: 100%; 13 | 14 | > .inner { 15 | @include padding(0, 6em); 16 | margin: 0 auto; 17 | max-width: 110em; 18 | 19 | > section { 20 | @include padding(6em, 0); 21 | border-top: solid 2px _palette(border); 22 | 23 | &:first-of-type { 24 | border-top: 0 !important; 25 | } 26 | } 27 | } 28 | 29 | @include breakpoint('<=xlarge') { 30 | > .inner { 31 | @include padding(0, 5em); 32 | 33 | > section { 34 | @include padding(5em, 0); 35 | } 36 | } 37 | } 38 | 39 | @include breakpoint('<=large') { 40 | > .inner { 41 | @include padding(0, 4em); 42 | 43 | > section { 44 | @include padding(4em, 0); 45 | } 46 | } 47 | } 48 | 49 | @include breakpoint('<=small') { 50 | > .inner { 51 | @include padding(0, 2em); 52 | 53 | > section { 54 | @include padding(3em, 0); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_menu.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Menu */ 8 | 9 | #menu { 10 | ul { 11 | @include vendor('user-select', 'none'); 12 | color: _palette(fg-bold); 13 | font-family: _font(family-heading); 14 | font-weight: _font(weight-heading-alt); 15 | letter-spacing: _font(kerning-heading); 16 | list-style: none; 17 | margin-bottom: 0; 18 | padding: 0; 19 | text-transform: uppercase; 20 | 21 | a, span { 22 | border-bottom: 0; 23 | color: inherit; 24 | cursor: pointer; 25 | display: block; 26 | font-size: 0.9em; 27 | padding: 0.625em 0; 28 | 29 | &:hover { 30 | color: _palette(accent); 31 | } 32 | 33 | &.opener { 34 | @include vendor('transition', 'color #{_duration(transition)} ease-in-out'); 35 | @include icon(false, solid); 36 | -webkit-tap-highlight-color: rgba(255,255,255,0); 37 | position: relative; 38 | 39 | &:before { 40 | @include vendor('transition', ( 41 | 'color #{_duration(transition)} ease-in-out', 42 | 'transform #{_duration(transition)} ease-in-out' 43 | )); 44 | color: _palette(fg-light); 45 | content: '\f078'; 46 | position: absolute; 47 | right: 0; 48 | } 49 | 50 | &:hover { 51 | &:before { 52 | color: _palette(accent); 53 | } 54 | } 55 | 56 | &.active { 57 | & + ul { 58 | display: block; 59 | } 60 | 61 | &:before { 62 | @include vendor('transform', 'rotate(-180deg)'); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | > ul { 70 | > li { 71 | border-top: solid 1px _palette(border); 72 | margin: 0.5em 0 0 0; 73 | padding: 0.5em 0 0 0; 74 | 75 | > ul { 76 | color: _palette(fg-light); 77 | display: none; 78 | margin: 0.5em 0 1.5em 0; 79 | padding-left: 1em; 80 | 81 | a, span { 82 | font-size: 0.8em; 83 | } 84 | 85 | > li { 86 | margin: 0.125em 0 0 0; 87 | padding: 0.125em 0 0 0; 88 | } 89 | } 90 | 91 | &:first-child { 92 | border-top: 0; 93 | margin-top: 0; 94 | padding-top: 0; 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Editorial by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper */ 8 | 9 | #wrapper { 10 | @include vendor('display', 'flex'); 11 | @include vendor('flex-direction', 'row-reverse'); 12 | min-height: 100vh; 13 | } 14 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } 91 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/libs/_mixins.scss: -------------------------------------------------------------------------------- 1 | /// Makes an element's :before pseudoelement a FontAwesome icon. 2 | /// @param {string} $content Optional content value to use. 3 | /// @param {string} $category Optional category to use. 4 | /// @param {string} $where Optional pseudoelement to target (before or after). 5 | @mixin icon($content: false, $category: regular, $where: before) { 6 | 7 | text-decoration: none; 8 | 9 | &:#{$where} { 10 | 11 | @if $content { 12 | content: $content; 13 | } 14 | 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-font-smoothing: antialiased; 17 | display: inline-block; 18 | font-style: normal; 19 | font-variant: normal; 20 | text-rendering: auto; 21 | line-height: 1; 22 | text-transform: none !important; 23 | 24 | @if ($category == brands) { 25 | font-family: 'Font Awesome 5 Brands'; 26 | } 27 | @elseif ($category == solid) { 28 | font-family: 'Font Awesome 5 Free'; 29 | font-weight: 900; 30 | } 31 | @else { 32 | font-family: 'Font Awesome 5 Free'; 33 | font-weight: 400; 34 | } 35 | 36 | } 37 | 38 | } 39 | 40 | /// Applies padding to an element, taking the current element-margin value into account. 41 | /// @param {mixed} $tb Top/bottom padding. 42 | /// @param {mixed} $lr Left/right padding. 43 | /// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left) 44 | /// @param {bool} $important If true, adds !important. 45 | @mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) { 46 | 47 | @if $important { 48 | $important: '!important'; 49 | } 50 | 51 | $x: 0.1em; 52 | 53 | @if unit(_size(element-margin)) == 'rem' { 54 | $x: 0.1rem; 55 | } 56 | 57 | padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important}; 58 | 59 | } 60 | 61 | /// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp). 62 | /// @param {string} $svg SVG data URL. 63 | /// @return {string} Encoded SVG data URL. 64 | @function svg-url($svg) { 65 | 66 | $svg: str-replace($svg, '"', '\''); 67 | $svg: str-replace($svg, '%', '%25'); 68 | $svg: str-replace($svg, '<', '%3C'); 69 | $svg: str-replace($svg, '>', '%3E'); 70 | $svg: str-replace($svg, '&', '%26'); 71 | $svg: str-replace($svg, '#', '%23'); 72 | $svg: str-replace($svg, '{', '%7B'); 73 | $svg: str-replace($svg, '}', '%7D'); 74 | $svg: str-replace($svg, ';', '%3B'); 75 | 76 | @return url("data:image/svg+xml;charset=utf8,#{$svg}"); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000 4 | ); 5 | 6 | // Duration. 7 | $duration: ( 8 | nav: 0.5s, 9 | transition: 0.2s 10 | ); 11 | 12 | // Size. 13 | $size: ( 14 | border-radius: 0.375em, 15 | element-height: 2.75em, 16 | element-margin: 2em, 17 | sidebar-width: 26em, 18 | sidebar-width-alt: 24em, 19 | gutter: 3em 20 | ); 21 | 22 | // Font. 23 | $font: ( 24 | family: ('Open Sans', sans-serif), 25 | family-heading: ('Roboto Slab', serif), 26 | family-fixed: ('Courier New', monospace), 27 | weight: 400, 28 | weight-bold: 600, 29 | weight-heading: 700, 30 | weight-heading-alt: 400, 31 | kerning-heading: 0.075em 32 | ); 33 | 34 | // Palette. 35 | $palette: ( 36 | bg: #ffffff, 37 | bg-alt: #f5f6f7, 38 | fg: #7f888f, 39 | fg-bold: #3d4449, 40 | fg-light: #9fa3a6, 41 | border: rgba(210,215,217,0.75), 42 | border-bg: transparentize(#e6ebed, 0.75), 43 | accent: #f56a6a 44 | ); 45 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/assets/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import 'libs/vars'; 2 | @import 'libs/functions'; 3 | @import 'libs/mixins'; 4 | @import 'libs/vendor'; 5 | @import 'libs/breakpoints'; 6 | @import 'libs/html-grid'; 7 | @import 'fontawesome-all.min.css'; 8 | @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,400italic,600italic|Roboto+Slab:400,700'); 9 | 10 | /* 11 | Editorial by HTML5 UP 12 | html5up.net | @ajlkn 13 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 14 | */ 15 | 16 | // Breakpoints. 17 | 18 | @include breakpoints(( 19 | xlarge: ( 1281px, 1680px ), 20 | large: ( 981px, 1280px ), 21 | medium: ( 737px, 980px ), 22 | small: ( 481px, 736px ), 23 | xsmall: ( 361px, 480px ), 24 | xxsmall: ( null, 360px ), 25 | xlarge-to-max: '(min-width: 1681px)', 26 | small-to-xlarge: '(min-width: 481px) and (max-width: 1680px)' 27 | )); 28 | 29 | // Base. 30 | 31 | @import 'base/reset'; 32 | @import 'base/page'; 33 | @import 'base/typography'; 34 | 35 | // Component. 36 | 37 | @import 'components/row'; 38 | @import 'components/section'; 39 | @import 'components/form'; 40 | @import 'components/box'; 41 | @import 'components/icon'; 42 | @import 'components/image'; 43 | @import 'components/list'; 44 | @import 'components/actions'; 45 | @import 'components/icons'; 46 | @import 'components/contact'; 47 | @import 'components/pagination'; 48 | @import 'components/table'; 49 | @import 'components/button'; 50 | @import 'components/mini-posts'; 51 | @import 'components/features'; 52 | @import 'components/posts'; 53 | 54 | // Layout. 55 | 56 | @import 'layout/wrapper'; 57 | @import 'layout/main'; 58 | @import 'layout/sidebar'; 59 | @import 'layout/header'; 60 | @import 'layout/banner'; 61 | @import 'layout/footer'; 62 | @import 'layout/menu'; 63 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/base.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | {{get_setting('SITE_TITLE')}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | {%block body%} 17 | 18 | 19 | {%endblock%} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/contact.html: -------------------------------------------------------------------------------- 1 | {%extends 'editorial/base.html'%} 2 | 3 | 4 | {%block body%} 5 | 6 | 7 |
    8 | 9 | 10 |
    11 |
    12 | 13 |
    14 |

    Form

    15 |
    16 |
    17 |
    18 | {{form.name.label}} 19 | {{ form.name }} 20 |
    21 |
    22 | {{form.email.label}} 23 | {{ form.email }} 24 |
    25 | 26 |
    27 | {{form.message.label}} 28 | {{ form.message }} 29 |
    30 |
    31 |
      32 |
    • 33 | 34 |
    35 |
    36 |
    37 |
    38 |
    39 |
    40 |
    41 | 42 | {%include 'editorial/sections/sidebar.html'%} 43 |
    44 | 45 | 46 | {%endblock%} 47 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic01.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic02.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic03.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic04.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic05.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic06.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic07.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic07.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic08.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic08.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic09.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic09.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic10.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/images/pic11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/images/pic11.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ARJ", 3 | "version": "1.0.20000000000003" 4 | } 5 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/page.html: -------------------------------------------------------------------------------- 1 | {%extends 'editorial/base.html'%} 2 | 3 | 4 | {%block body%} 5 | 6 | 7 |
    8 | 9 | 10 |
    11 |
    12 | 13 | 14 | 24 | 25 | 26 |
    27 |
    28 |

    {{page.title}}

    29 |
    30 | 31 |

    {{page.get_content() | safe}}

    32 | 33 |
    34 | 35 |
    36 |
    37 | 38 | {%include 'editorial/sections/sidebar.html'%} 39 | 40 |
    41 | 42 | 43 | {%endblock%} 44 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/render_demo.html: -------------------------------------------------------------------------------- 1 | 2 |

    WWW Index

    3 |

    Fruit {{ fruit }}

    4 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/sections/footer.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/sections/footer.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/sections/nav.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/sections/nav.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/sections/resources.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/editorial/sections/resources.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/editorial/styles.css: -------------------------------------------------------------------------------- 1 | 2 | html { 3 | scroll-behavior: smooth; 4 | } 5 | .suggest { 6 | 7 | } 8 | 9 | .suggest span { 10 | padding-left: 5px; 11 | padding-right: 5px; 12 | margin: 5px; 13 | min-width: 50px; 14 | } 15 | 16 | a{ 17 | text-decoration: inherit; 18 | color: inherit; 19 | } 20 | a:hover{ 21 | text-decoration: inherit; 22 | color: inherit; 23 | } 24 | 25 | #flashed-messages{ 26 | padding: 5px; 27 | position: fixed; 28 | right: 5px; 29 | top: 5px; 30 | z-index: 10; 31 | height: 300px; 32 | overflow-y: scroll; 33 | 34 | } 35 | #flashed-messages::-webkit-scrollbar { 36 | display: none; 37 | } 38 | /* Hide scrollbar for IE and Edge */ 39 | #flashed-messages{ 40 | -ms-overflow-style: none; 41 | } 42 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/README.txt: -------------------------------------------------------------------------------- 1 | Hyperspace by HTML5 UP 2 | html5up.net | @ajlkn 3 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 4 | 5 | 6 | So I've had the wireframe for this particular design kicking around for some time, but with all 7 | the other interesting (and in some cases, semi-secret) projects I've been working on it took me 8 | a little while to get to actually designing and coding it. Fortunately, things have eased up 9 | enough for me to finaly get around to it, so I'm happy to introduce Hyperspace: a fun, blocky, 10 | one-page design with a lot of color, a bit of animation, and an additional "generic" page template 11 | (because hey, even one-page sites usually need an interior page or two). Hope you dig it :) 12 | 13 | Demo images* courtesy of Unsplash, a radtastic collection of CC0 (public domain) images 14 | you can use for pretty much whatever. 15 | 16 | (* = not included) 17 | 18 | AJ 19 | aj@lkn.io | @ajlkn 20 | 21 | 22 | Credits: 23 | 24 | Demo Images: 25 | Unsplash (unsplash.com) 26 | 27 | Icons: 28 | Font Awesome (fontawesome.io) 29 | 30 | Other: 31 | jQuery (jquery.com) 32 | Scrollex (github.com/ajlkn/jquery.scrollex) 33 | Responsive Tools (github.com/ajlkn/responsive-tools) 34 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/css/images/intro.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/css/noscript.css: -------------------------------------------------------------------------------- 1 | /* 2 | Hyperspace by HTML5 UP 3 | html5up.net | @ajlkn 4 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | */ 6 | 7 | /* Spotlights */ 8 | 9 | .spotlights > section > .image:before { 10 | opacity: 0 !important; 11 | } 12 | 13 | .spotlights > section > .content > .inner { 14 | -moz-transform: none !important; 15 | -webkit-transform: none !important; 16 | -ms-transform: none !important; 17 | transform: none !important; 18 | opacity: 1 !important; 19 | } 20 | 21 | /* Wrapper */ 22 | 23 | .wrapper > .inner { 24 | opacity: 1 !important; 25 | -moz-transform: none !important; 26 | -webkit-transform: none !important; 27 | -ms-transform: none !important; 28 | transform: none !important; 29 | } 30 | 31 | /* Sidebar */ 32 | 33 | #sidebar > .inner { 34 | opacity: 1 !important; 35 | } 36 | 37 | #sidebar nav > ul > li { 38 | -moz-transform: none !important; 39 | -webkit-transform: none !important; 40 | -ms-transform: none !important; 41 | transform: none !important; 42 | opacity: 1 !important; 43 | } 44 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/js/breakpoints.min.js: -------------------------------------------------------------------------------- 1 | /* breakpoints.js v1.0 | @ajlkn | MIT licensed */ 2 | var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e1){for(var r=0;r=i&&o>=t};break;case"bottom":h=function(t,e,n,i,o){return n>=i&&o>=n};break;case"middle":h=function(t,e,n,i,o){return e>=i&&o>=e};break;case"top-only":h=function(t,e,n,i,o){return i>=t&&n>=i};break;case"bottom-only":h=function(t,e,n,i,o){return n>=o&&o>=t};break;default:case"default":h=function(t,e,n,i,o){return n>=i&&o>=t}}return c=function(t){var i,o,l,s,r,a,u=this.state,h=!1,c=this.$element.offset();i=n.height(),o=t+i/2,l=t+i,s=this.$element.outerHeight(),r=c.top+e(this.options.top,s,i),a=c.top+s-e(this.options.bottom,s,i),h=this.test(t,o,l,r,a),h!=u&&(this.state=h,h?this.options.enter&&this.options.enter.apply(this.element):this.options.leave&&this.options.leave.apply(this.element)),this.options.scroll&&this.options.scroll.apply(this.element,[(o-r)/(a-r)])},p={id:a,options:u,test:h,handler:c,state:null,element:this,$element:s,timeoutId:null},o[a]=p,s.data("_scrollexId",p.id),p.options.initialize&&p.options.initialize.apply(this),s},jQuery.fn.unscrollex=function(){var e=t(this);if(0==this.length)return e;if(this.length>1){for(var n=0;n1){for(o=0;o=320px. 20 | @include breakpoint('<=xsmall') { 21 | html, body { 22 | min-width: 320px; 23 | } 24 | } 25 | 26 | // Set box model to border-box. 27 | // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice 28 | html { 29 | box-sizing: border-box; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: inherit; 34 | } 35 | 36 | body { 37 | background: _palette(bg); 38 | 39 | // Stops initial animations until page loads. 40 | &.is-preload { 41 | *, *:before, *:after { 42 | @include vendor('animation', 'none !important'); 43 | @include vendor('transition', 'none !important'); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | // Reset. 8 | // Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) 9 | 10 | html, body, div, span, applet, object, 11 | iframe, h1, h2, h3, h4, h5, h6, p, blockquote, 12 | pre, a, abbr, acronym, address, big, cite, 13 | code, del, dfn, em, img, ins, kbd, q, s, samp, 14 | small, strike, strong, sub, sup, tt, var, b, 15 | u, i, center, dl, dt, dd, ol, ul, li, fieldset, 16 | form, label, legend, table, caption, tbody, 17 | tfoot, thead, tr, th, td, article, aside, 18 | canvas, details, embed, figure, figcaption, 19 | footer, header, hgroup, menu, nav, output, ruby, 20 | section, summary, time, mark, audio, video { 21 | margin: 0; 22 | padding: 0; 23 | border: 0; 24 | font-size: 100%; 25 | font: inherit; 26 | vertical-align: baseline; 27 | } 28 | 29 | article, aside, details, figcaption, figure, 30 | footer, header, hgroup, menu, nav, section { 31 | display: block; 32 | } 33 | 34 | body { 35 | line-height: 1; 36 | } 37 | 38 | ol, ul { 39 | list-style:none; 40 | } 41 | 42 | blockquote, q { 43 | quotes: none; 44 | 45 | &:before, 46 | &:after { 47 | content: ''; 48 | content: none; 49 | } 50 | } 51 | 52 | table { 53 | border-collapse: collapse; 54 | border-spacing: 0; 55 | } 56 | 57 | body { 58 | -webkit-text-size-adjust: none; 59 | } 60 | 61 | mark { 62 | background-color: transparent; 63 | color: inherit; 64 | } 65 | 66 | input::-moz-focus-inner { 67 | border: 0; 68 | padding: 0; 69 | } 70 | 71 | input, select, textarea { 72 | -moz-appearance: none; 73 | -webkit-appearance: none; 74 | -ms-appearance: none; 75 | appearance: none; 76 | } 77 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_actions.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Actions */ 8 | 9 | ul.actions { 10 | @include vendor('display', 'flex'); 11 | cursor: default; 12 | list-style: none; 13 | margin-left: (_size(element-margin) * -0.5); 14 | padding-left: 0; 15 | 16 | li { 17 | padding: 0 0 0 (_size(element-margin) * 0.5); 18 | vertical-align: middle; 19 | } 20 | 21 | &.special { 22 | @include vendor('justify-content', 'center'); 23 | width: 100%; 24 | margin-left: 0; 25 | 26 | li { 27 | &:first-child { 28 | padding-left: 0; 29 | } 30 | } 31 | } 32 | 33 | &.stacked { 34 | @include vendor('flex-direction', 'column'); 35 | margin-left: 0; 36 | 37 | li { 38 | padding: (_size(element-margin) * 0.65) 0 0 0; 39 | 40 | &:first-child { 41 | padding-top: 0; 42 | } 43 | } 44 | } 45 | 46 | &.fit { 47 | width: calc(100% + #{_size(element-margin) * 0.5}); 48 | 49 | li { 50 | @include vendor('flex-grow', '1'); 51 | @include vendor('flex-shrink', '1'); 52 | width: 100%; 53 | 54 | > * { 55 | width: 100%; 56 | } 57 | } 58 | 59 | &.stacked { 60 | width: 100%; 61 | } 62 | } 63 | 64 | @include breakpoint('<=xsmall') { 65 | &:not(.fixed) { 66 | @include vendor('flex-direction', 'column'); 67 | margin-left: 0; 68 | width: 100% !important; 69 | 70 | li { 71 | @include vendor('flex-grow', '1'); 72 | @include vendor('flex-shrink', '1'); 73 | padding: (_size(element-margin) * 0.5) 0 0 0; 74 | text-align: center; 75 | width: 100%; 76 | 77 | > * { 78 | width: 100%; 79 | } 80 | 81 | &:first-child { 82 | padding-top: 0; 83 | } 84 | 85 | input[type="submit"], 86 | input[type="reset"], 87 | input[type="button"], 88 | button, 89 | .button { 90 | width: 100%; 91 | 92 | &.icon { 93 | &:before { 94 | margin-left: -0.5rem; 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_box.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Box */ 8 | 9 | .box { 10 | border-radius: _size(border-radius); 11 | border: solid _size(border-width) _palette(border); 12 | margin-bottom: _size(element-margin); 13 | padding: 1.5em; 14 | 15 | > :last-child, 16 | > :last-child > :last-child, 17 | > :last-child > :last-child > :last-child { 18 | margin-bottom: 0; 19 | } 20 | 21 | &.alt { 22 | border: 0; 23 | border-radius: 0; 24 | padding: 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_button.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Button */ 8 | 9 | input[type="submit"], 10 | input[type="reset"], 11 | input[type="button"], 12 | button, 13 | .button { 14 | @include vendor('appearance', 'none'); 15 | @include vendor('transition', ( 16 | 'border-color #{_duration(transition)} ease' 17 | )); 18 | background-color: transparent; 19 | border: solid 1px !important; 20 | border-color: _palette(border) !important; 21 | border-radius: 3em; 22 | color: _palette(fg-bold) !important; 23 | cursor: pointer; 24 | display: inline-block; 25 | font-size: 0.6em; 26 | font-weight: _font(weight-bold); 27 | height: calc(4.75em + 2px); 28 | letter-spacing: _font(kerning-alt); 29 | line-height: 4.75em; 30 | outline: 0; 31 | padding: 0 3.75em; 32 | position: relative; 33 | text-align: center; 34 | text-decoration: none; 35 | text-transform: uppercase; 36 | white-space: nowrap; 37 | 38 | &:after { 39 | @include vendor('transform', 'scale(0.25)'); 40 | @include vendor('pointer-events', 'none'); 41 | @include vendor('transition', ( 42 | 'opacity #{_duration(transition)} ease', 43 | 'transform #{_duration(transition)} ease' 44 | )); 45 | background: _palette(fg-bold); 46 | border-radius: 3em; 47 | content: ''; 48 | height: 100%; 49 | left: 0; 50 | opacity: 0; 51 | position: absolute; 52 | top: 0; 53 | width: 100%; 54 | } 55 | 56 | &.icon { 57 | &:before { 58 | margin-right: 0.75em; 59 | } 60 | } 61 | 62 | &.fit { 63 | width: 100%; 64 | } 65 | 66 | &.small { 67 | font-size: 0.4em; 68 | } 69 | 70 | &.large { 71 | font-size: 0.8em; 72 | } 73 | 74 | &.primary { 75 | background-color: _palette(fg-bold); 76 | color: _palette(bg) !important; 77 | 78 | &:after { 79 | display: none; 80 | } 81 | } 82 | 83 | &.disabled, 84 | &:disabled { 85 | cursor: default; 86 | opacity: 0.5; 87 | @include vendor('pointer-events', 'none'); 88 | } 89 | 90 | &:hover { 91 | border-color: _palette(fg) !important; 92 | 93 | &:after { 94 | opacity: 0.05; 95 | @include vendor('transform', 'scale(1)'); 96 | } 97 | 98 | &:active { 99 | border-color: _palette(fg-bold) !important; 100 | 101 | &:after { 102 | opacity: 0.1; 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_contact.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Contact */ 8 | 9 | ul.contact { 10 | list-style: none; 11 | padding: 0; 12 | 13 | > li { 14 | padding: 0; 15 | margin: 1.5em 0 0 0; 16 | 17 | &:first-child { 18 | margin-top: 0; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_features.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Features */ 8 | 9 | .features { 10 | @include vendor('display', 'flex'); 11 | @include vendor('flex-wrap', 'wrap'); 12 | border-radius: _size(border-radius); 13 | border: solid 1px _palette(border); 14 | background: _palette(border-bg); 15 | margin: 0 0 _size(element-margin) 0; 16 | 17 | section { 18 | @include padding(3em, 3em, (0.5em, 0, 0, 4em)); 19 | width: 50%; 20 | border-top: solid 1px _palette(border); 21 | position: relative; 22 | 23 | &:nth-child(-n + 2) { 24 | border-top-width: 0; 25 | } 26 | 27 | &:nth-child(2n) { 28 | border-left: solid 1px _palette(border); 29 | } 30 | 31 | .icon { 32 | @include vendor('transition', ( 33 | 'opacity #{_duration(activation) * 0.5} ease', 34 | 'transform #{_duration(activation) * 0.5} ease' 35 | )); 36 | @include vendor('transition-delay', '1s'); 37 | @include vendor('transform', 'scale(1)'); 38 | position: absolute; 39 | left: 3em; 40 | top: 3em; 41 | opacity: 1; 42 | } 43 | 44 | @for $i from 1 through _misc(max-features) { 45 | &:nth-child(#{$i}) { 46 | .icon { 47 | @include vendor('transition-delay', '#{(_duration(transition) * 0.75 * $i)}'); 48 | } 49 | } 50 | } 51 | } 52 | 53 | &.inactive { 54 | section { 55 | .icon { 56 | @include vendor('transform', 'scale(0.5)'); 57 | opacity: 0; 58 | } 59 | } 60 | } 61 | 62 | @include breakpoint('<=medium') { 63 | display: block; 64 | 65 | section { 66 | border-top-width: 1px !important; 67 | border-left-width: 0 !important; 68 | width: 100%; 69 | 70 | &:first-child { 71 | border-top-width: 0 !important; 72 | } 73 | } 74 | } 75 | 76 | @include breakpoint('<=small') { 77 | section { 78 | @include padding(2em, 1.5em, (0.5em, 0, 0, 4em)); 79 | 80 | .icon { 81 | left: 1.5em; 82 | top: 2em; 83 | } 84 | } 85 | } 86 | 87 | @include breakpoint('<=xsmall') { 88 | section { 89 | @include padding(2em, 1.5em, (0, 0, 0, 0)); 90 | 91 | .icon { 92 | left: 0; 93 | position: relative; 94 | top: 0; 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icon */ 8 | 9 | .icon { 10 | @include icon; 11 | border-bottom: none; 12 | position: relative; 13 | 14 | > .label { 15 | display: none; 16 | } 17 | 18 | &:before { 19 | line-height: inherit; 20 | } 21 | 22 | &.solid { 23 | &:before { 24 | font-weight: 900; 25 | } 26 | } 27 | 28 | &.brands { 29 | &:before { 30 | font-family: 'Font Awesome 5 Brands'; 31 | } 32 | } 33 | 34 | &.major { 35 | width: 2.5em; 36 | height: 2.5em; 37 | display: block; 38 | background: _palette(fg-bold); 39 | border-radius: 100%; 40 | color: _palette(bg); 41 | text-align: center; 42 | line-height: 2.5em; 43 | margin: 0 0 (_size(element-margin) * 0.65) 0; 44 | 45 | &:before { 46 | font-size: 1.25em; 47 | 48 | .wrapper.style1 & { 49 | color: _palette(accent1); 50 | } 51 | 52 | .wrapper.style1-alt & { 53 | color: _palette(accent1-alt); 54 | } 55 | 56 | .wrapper.style2 & { 57 | color: _palette(accent2); 58 | } 59 | 60 | .wrapper.style2-alt & { 61 | color: _palette(accent2-alt); 62 | } 63 | 64 | .wrapper.style3 & { 65 | color: _palette(accent3); 66 | } 67 | 68 | .wrapper.style3-alt & { 69 | color: _palette(accent3-alt); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Icons */ 8 | 9 | ul.icons { 10 | cursor: default; 11 | list-style: none; 12 | padding-left: 0; 13 | 14 | li { 15 | display: inline-block; 16 | padding: 0 0.75em 0 0; 17 | 18 | &:last-child { 19 | padding-right: 0; 20 | } 21 | 22 | > a, > span { 23 | border: 0; 24 | 25 | .label { 26 | display: none; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_image.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Image */ 8 | 9 | .image { 10 | border-radius: _size(border-radius); 11 | border: 0; 12 | display: inline-block; 13 | position: relative; 14 | 15 | img { 16 | border-radius: _size(border-radius); 17 | display: block; 18 | } 19 | 20 | &.left, 21 | &.right { 22 | max-width: 40%; 23 | 24 | img { 25 | width: 100%; 26 | } 27 | } 28 | 29 | &.left { 30 | float: left; 31 | margin: 0 1.5em 1em 0; 32 | top: 0.25em; 33 | } 34 | 35 | &.right { 36 | float: right; 37 | margin: 0 0 1em 1.5em; 38 | top: 0.25em; 39 | } 40 | 41 | &.fit { 42 | display: block; 43 | margin: 0 0 _size(element-margin) 0; 44 | width: 100%; 45 | 46 | img { 47 | width: 100%; 48 | } 49 | } 50 | 51 | &.main { 52 | display: block; 53 | margin: 0 0 (_size(element-margin) * 1.5) 0; 54 | width: 100%; 55 | 56 | img { 57 | width: 100%; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* List */ 8 | 9 | ol { 10 | list-style: decimal; 11 | margin: 0 0 _size(element-margin) 0; 12 | padding-left: 1.25em; 13 | 14 | li { 15 | padding-left: 0.25em; 16 | } 17 | } 18 | 19 | ul { 20 | list-style: disc; 21 | margin: 0 0 _size(element-margin) 0; 22 | padding-left: 1em; 23 | 24 | li { 25 | padding-left: 0.5em; 26 | } 27 | 28 | &.alt { 29 | list-style: none; 30 | padding-left: 0; 31 | 32 | li { 33 | border-top: solid _size(border-width) _palette(border); 34 | padding: 0.5em 0; 35 | 36 | &:first-child { 37 | border-top: 0; 38 | padding-top: 0; 39 | } 40 | } 41 | } 42 | } 43 | 44 | dl { 45 | margin: 0 0 _size(element-margin) 0; 46 | 47 | dt { 48 | display: block; 49 | font-weight: _font(weight-bold); 50 | margin: 0 0 (_size(element-margin) * 0.5) 0; 51 | } 52 | 53 | dd { 54 | margin-left: _size(element-margin); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_menu.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Menu */ 8 | 9 | ul.menu { 10 | list-style: none; 11 | padding: 0; 12 | 13 | > li { 14 | border-left: solid 1px _palette(border); 15 | display: inline-block; 16 | line-height: 1; 17 | margin-left: 1.5em; 18 | padding: 0 0 0 1.5em; 19 | 20 | &:first-child { 21 | border-left: 0; 22 | margin: 0; 23 | padding-left: 0; 24 | } 25 | } 26 | 27 | @include breakpoint('<=xsmall') { 28 | > li { 29 | border-left: 0; 30 | display: block; 31 | line-height: inherit; 32 | margin: 0.5em 0 0 0; 33 | padding-left: 0; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_row.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Row */ 8 | 9 | .row { 10 | @include html-grid(1.5em); 11 | 12 | @include breakpoint('<=xlarge') { 13 | @include html-grid(1.5em, 'xlarge'); 14 | } 15 | 16 | @include breakpoint('<=large') { 17 | @include html-grid(1.5em, 'large'); 18 | } 19 | 20 | @include breakpoint('<=medium') { 21 | @include html-grid(1.5em, 'medium'); 22 | } 23 | 24 | @include breakpoint('<=small') { 25 | @include html-grid(1.5em, 'small'); 26 | } 27 | 28 | @include breakpoint('<=xsmall') { 29 | @include html-grid(1.5em, 'xsmall'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_section.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Section/Article */ 8 | 9 | section, article { 10 | &.special { 11 | text-align: center; 12 | } 13 | } 14 | 15 | header { 16 | p { 17 | color: _palette(fg-light); 18 | position: relative; 19 | margin: 0 0 (_size(element-margin) * 0.75) 0; 20 | } 21 | 22 | h2 + p { 23 | font-size: 1.25em; 24 | margin-top: (_size(element-margin) * -0.5); 25 | line-height: 1.5em; 26 | } 27 | 28 | h3 + p { 29 | font-size: 1.1em; 30 | margin-top: (_size(element-margin) * -0.4); 31 | line-height: 1.5em; 32 | } 33 | 34 | h4 + p, 35 | h5 + p, 36 | h6 + p { 37 | font-size: 0.9em; 38 | margin-top: (_size(element-margin) * -0.3); 39 | line-height: 1.5em; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_split.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Split */ 8 | 9 | .split { 10 | @include vendor('display', 'flex'); 11 | 12 | > * { 13 | width: calc(50% - 2.5em); 14 | } 15 | 16 | > :nth-child(2n - 1) { 17 | padding-right: 2.5em; 18 | border-right: solid 1px _palette(border); 19 | } 20 | 21 | > :nth-child(2n) { 22 | padding-left: 2.5em; 23 | } 24 | 25 | &.style1 { 26 | > :nth-child(2n - 1) { 27 | width: calc(66.66666% - 2.5em); 28 | } 29 | 30 | > :nth-child(2n) { 31 | width: calc(33.33333% - 2.5em); 32 | } 33 | } 34 | 35 | @include breakpoint('<=xlarge') { 36 | > * { 37 | width: calc(50% - 2em); 38 | } 39 | 40 | > :nth-child(2n - 1) { 41 | padding-right: 2em; 42 | } 43 | 44 | > :nth-child(2n) { 45 | padding-left: 2em; 46 | } 47 | 48 | &.style1 { 49 | > :nth-child(2n - 1) { 50 | width: calc(66.66666% - 2em); 51 | } 52 | 53 | > :nth-child(2n) { 54 | width: calc(33.33333% - 2em); 55 | } 56 | } 57 | } 58 | 59 | @include breakpoint('<=medium') { 60 | display: block; 61 | 62 | > * { 63 | border-top: solid 1px _palette(border); 64 | margin: 4em 0 0 0; 65 | padding: 4em 0 0 0; 66 | width: 100% !important; 67 | } 68 | 69 | > :nth-child(2n - 1) { 70 | border-right: 0; 71 | padding-right: 0; 72 | } 73 | 74 | > :nth-child(2n) { 75 | padding-left: 0; 76 | } 77 | 78 | > :first-child { 79 | border-top: 0; 80 | margin-top: 0; 81 | padding-top: 0; 82 | } 83 | } 84 | 85 | @include breakpoint('<=small') { 86 | > * { 87 | margin: 3em 0 0 0; 88 | padding: 3em 0 0 0; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/components/_table.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Table */ 8 | 9 | .table-wrapper { 10 | -webkit-overflow-scrolling: touch; 11 | overflow-x: auto; 12 | } 13 | 14 | table { 15 | margin: 0 0 _size(element-margin) 0; 16 | width: 100%; 17 | 18 | tbody { 19 | tr { 20 | border: solid _size(border-width) _palette(border); 21 | border-left: 0; 22 | border-right: 0; 23 | 24 | &:nth-child(2n + 1) { 25 | background-color: _palette(border-bg); 26 | } 27 | } 28 | } 29 | 30 | td { 31 | padding: 0.75em 0.75em; 32 | } 33 | 34 | th { 35 | color: _palette(fg-bold); 36 | font-size: 1em; 37 | font-weight: _font(weight-bold); 38 | padding: 0 0.75em 0.75em 0.75em; 39 | text-align: left; 40 | } 41 | 42 | thead { 43 | border-bottom: solid (_size(border-width) * 2) _palette(border); 44 | } 45 | 46 | tfoot { 47 | border-top: solid (_size(border-width) * 2) _palette(border); 48 | } 49 | 50 | &.alt { 51 | border-collapse: separate; 52 | 53 | tbody { 54 | tr { 55 | td { 56 | border: solid _size(border-width) _palette(border); 57 | border-left-width: 0; 58 | border-top-width: 0; 59 | 60 | &:first-child { 61 | border-left-width: _size(border-width); 62 | } 63 | } 64 | 65 | &:first-child { 66 | td { 67 | border-top-width: _size(border-width); 68 | } 69 | } 70 | } 71 | } 72 | 73 | thead { 74 | border-bottom: 0; 75 | } 76 | 77 | tfoot { 78 | border-top: 0; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Footer */ 8 | 9 | #footer { 10 | #sidebar + #wrapper + & { 11 | margin-left: _size(sidebar-width); 12 | 13 | @include breakpoint('<=large') { 14 | margin-left: 0; 15 | } 16 | } 17 | 18 | > .inner { 19 | a { 20 | border-bottom-color: _palette(border); 21 | 22 | &:hover { 23 | border-bottom-color: transparent; 24 | } 25 | } 26 | 27 | .menu { 28 | font-size: 0.8em; 29 | color: _palette(border); 30 | } 31 | } 32 | 33 | #header + #wrapper + & { 34 | > .inner { 35 | margin: 0 auto; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/layout/_header.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Header */ 8 | 9 | #header { 10 | @include vendor('display', 'flex'); 11 | background-color: _palette(accent1); 12 | cursor: default; 13 | padding: 1.75em 2em; 14 | 15 | > .title { 16 | border: 0; 17 | color: _palette(fg-bold); 18 | display: block; 19 | font-size: 1.25em; 20 | font-weight: _font(weight-bold); 21 | } 22 | 23 | > nav { 24 | @include vendor('flex', '1'); 25 | text-align: right; 26 | 27 | > ul { 28 | margin: 0; 29 | padding: 0; 30 | 31 | > li { 32 | display: inline-block; 33 | margin-left: 1.75em; 34 | padding: 0; 35 | vertical-align: middle; 36 | 37 | &:first-child { 38 | margin-left: 0; 39 | } 40 | 41 | a { 42 | border: 0; 43 | color: _palette(fg-light); 44 | display: inline-block; 45 | font-size: 0.6em; 46 | font-weight: _font(weight-bold); 47 | letter-spacing: _font(kerning-alt); 48 | text-transform: uppercase; 49 | 50 | &:hover { 51 | color: _palette(fg); 52 | } 53 | 54 | &.active { 55 | color: _palette(fg-bold); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | @include breakpoint('<=small') { 63 | padding: 1em 2em; 64 | } 65 | 66 | @include breakpoint('<=xsmall') { 67 | display: block; 68 | padding: 0 2em; 69 | text-align: left; 70 | 71 | .title { 72 | font-size: 1.25em; 73 | padding: 1em 0; 74 | } 75 | 76 | > nav { 77 | border-top: solid 1px _palette(border); 78 | text-align: inherit; 79 | 80 | > ul { 81 | > li { 82 | margin-left: 1.5em; 83 | 84 | a { 85 | height: 6em; 86 | line-height: 6em; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/layout/_intro.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Intro */ 8 | 9 | #intro { 10 | background-attachment: fixed; 11 | background-image: url('images/intro.svg'); 12 | background-position: top right; 13 | background-repeat: no-repeat; 14 | background-size: 100% 100%; 15 | 16 | p { 17 | font-size: 1.25em; 18 | 19 | @include breakpoint('<=medium') { 20 | br { 21 | display: none; 22 | } 23 | } 24 | 25 | @include breakpoint('<=small') { 26 | font-size: 1em; 27 | } 28 | } 29 | 30 | @include breakpoint('<=large') { 31 | background-attachment: scroll; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/layout/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /// 2 | /// Hyperspace by HTML5 UP 3 | /// html5up.net | @ajlkn 4 | /// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 5 | /// 6 | 7 | /* Wrapper (main) */ 8 | 9 | #wrapper { 10 | #sidebar + & { 11 | margin-left: _size(sidebar-width); 12 | 13 | @include breakpoint('<=large') { 14 | margin-left: 0; 15 | padding-top: _size(sidebar-height); 16 | } 17 | 18 | @include breakpoint('<=small') { 19 | padding-top: 0; 20 | } 21 | } 22 | 23 | #header + & { 24 | > .wrapper { 25 | > .inner { 26 | margin: 0 auto; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/libs/_functions.scss: -------------------------------------------------------------------------------- 1 | /// Removes a specific item from a list. 2 | /// @author Hugo Giraudel 3 | /// @param {list} $list List. 4 | /// @param {integer} $index Index. 5 | /// @return {list} Updated list. 6 | @function remove-nth($list, $index) { 7 | 8 | $result: null; 9 | 10 | @if type-of($index) != number { 11 | @warn "$index: #{quote($index)} is not a number for `remove-nth`."; 12 | } 13 | @else if $index == 0 { 14 | @warn "List index 0 must be a non-zero integer for `remove-nth`."; 15 | } 16 | @else if abs($index) > length($list) { 17 | @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; 18 | } 19 | @else { 20 | 21 | $result: (); 22 | $index: if($index < 0, length($list) + $index + 1, $index); 23 | 24 | @for $i from 1 through length($list) { 25 | 26 | @if $i != $index { 27 | $result: append($result, nth($list, $i)); 28 | } 29 | 30 | } 31 | 32 | } 33 | 34 | @return $result; 35 | 36 | } 37 | 38 | /// Gets a value from a map. 39 | /// @author Hugo Giraudel 40 | /// @param {map} $map Map. 41 | /// @param {string} $keys Key(s). 42 | /// @return {string} Value. 43 | @function val($map, $keys...) { 44 | 45 | @if nth($keys, 1) == null { 46 | $keys: remove-nth($keys, 1); 47 | } 48 | 49 | @each $key in $keys { 50 | $map: map-get($map, $key); 51 | } 52 | 53 | @return $map; 54 | 55 | } 56 | 57 | /// Gets a duration value. 58 | /// @param {string} $keys Key(s). 59 | /// @return {string} Value. 60 | @function _duration($keys...) { 61 | @return val($duration, $keys...); 62 | } 63 | 64 | /// Gets a font value. 65 | /// @param {string} $keys Key(s). 66 | /// @return {string} Value. 67 | @function _font($keys...) { 68 | @return val($font, $keys...); 69 | } 70 | 71 | /// Gets a misc value. 72 | /// @param {string} $keys Key(s). 73 | /// @return {string} Value. 74 | @function _misc($keys...) { 75 | @return val($misc, $keys...); 76 | } 77 | 78 | /// Gets a palette value. 79 | /// @param {string} $keys Key(s). 80 | /// @return {string} Value. 81 | @function _palette($keys...) { 82 | @return val($palette, $keys...); 83 | } 84 | 85 | /// Gets a size value. 86 | /// @param {string} $keys Key(s). 87 | /// @return {string} Value. 88 | @function _size($keys...) { 89 | @return val($size, $keys...); 90 | } 91 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/libs/_mixins.scss: -------------------------------------------------------------------------------- 1 | /// Makes an element's :before pseudoelement a FontAwesome icon. 2 | /// @param {string} $content Optional content value to use. 3 | /// @param {string} $category Optional category to use. 4 | /// @param {string} $where Optional pseudoelement to target (before or after). 5 | @mixin icon($content: false, $category: regular, $where: before) { 6 | 7 | text-decoration: none; 8 | 9 | &:#{$where} { 10 | 11 | @if $content { 12 | content: $content; 13 | } 14 | 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-font-smoothing: antialiased; 17 | display: inline-block; 18 | font-style: normal; 19 | font-variant: normal; 20 | text-rendering: auto; 21 | line-height: 1; 22 | text-transform: none !important; 23 | 24 | @if ($category == brands) { 25 | font-family: 'Font Awesome 5 Brands'; 26 | } 27 | @elseif ($category == solid) { 28 | font-family: 'Font Awesome 5 Free'; 29 | font-weight: 900; 30 | } 31 | @else { 32 | font-family: 'Font Awesome 5 Free'; 33 | font-weight: 400; 34 | } 35 | 36 | } 37 | 38 | } 39 | 40 | /// Applies padding to an element, taking the current element-margin value into account. 41 | /// @param {mixed} $tb Top/bottom padding. 42 | /// @param {mixed} $lr Left/right padding. 43 | /// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left) 44 | /// @param {bool} $important If true, adds !important. 45 | @mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) { 46 | 47 | @if $important { 48 | $important: '!important'; 49 | } 50 | 51 | $x: 0.1em; 52 | 53 | @if unit(_size(element-margin)) == 'rem' { 54 | $x: 0.1rem; 55 | } 56 | 57 | padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important}; 58 | 59 | } 60 | 61 | /// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp). 62 | /// @param {string} $svg SVG data URL. 63 | /// @return {string} Encoded SVG data URL. 64 | @function svg-url($svg) { 65 | 66 | $svg: str-replace($svg, '"', '\''); 67 | $svg: str-replace($svg, '%', '%25'); 68 | $svg: str-replace($svg, '<', '%3C'); 69 | $svg: str-replace($svg, '>', '%3E'); 70 | $svg: str-replace($svg, '&', '%26'); 71 | $svg: str-replace($svg, '#', '%23'); 72 | $svg: str-replace($svg, '{', '%7B'); 73 | $svg: str-replace($svg, '}', '%7D'); 74 | $svg: str-replace($svg, ';', '%3B'); 75 | 76 | @return url("data:image/svg+xml;charset=utf8,#{$svg}"); 77 | 78 | } 79 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/libs/_vars.scss: -------------------------------------------------------------------------------- 1 | // Misc. 2 | $misc: ( 3 | z-index-base: 10000, 4 | max-features: 20, 5 | max-sidebar-links: 20 6 | ); 7 | 8 | // Duration. 9 | $duration: ( 10 | transition: 0.2s, 11 | activation: 1s 12 | ); 13 | 14 | // Size. 15 | $size: ( 16 | border-radius: 0.25em, 17 | border-width: 1px, 18 | element-height: 2.75em, 19 | element-margin: 2em, 20 | sidebar-width: 18em, 21 | sidebar-height: 3.5em, // when <=large is active 22 | inner-width: 75em 23 | ); 24 | 25 | // Font. 26 | $font: ( 27 | family: (Arial, Helvetica, sans-serif), 28 | family-fixed: ('Courier New', monospace), 29 | weight: normal, 30 | weight-bold: bold, 31 | kerning-alt: 0.25em 32 | ); 33 | 34 | // Palette. 35 | $palette: ( 36 | bg: #312450, 37 | bg-alt: darken(#312450, 5), 38 | fg: rgba(255,255,255,0.55), 39 | fg-bold: #ffffff, 40 | fg-light: rgba(255,255,255,0.35), 41 | border: rgba(255,255,255,0.15), 42 | border-bg: rgba(255,255,255,0.05), 43 | accent1: #5e42a6, 44 | accent1-alt: darken(#5e42a6, 10), 45 | accent2: #5052b5, 46 | accent2-alt: darken(#5052b5, 10), 47 | accent3: #b74e91, 48 | accent3-alt: darken(#b74e91, 10) 49 | ); 50 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import 'libs/vars'; 2 | @import 'libs/functions'; 3 | @import 'libs/mixins'; 4 | @import 'libs/vendor'; 5 | @import 'libs/breakpoints'; 6 | @import 'libs/html-grid'; 7 | @import 'fontawesome-all.min.css'; 8 | 9 | /* 10 | Hyperspace by HTML5 UP 11 | html5up.net | @ajlkn 12 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 13 | */ 14 | 15 | // Breakpoints. 16 | 17 | @include breakpoints(( 18 | xlarge: ( 1281px, 1680px ), 19 | large: ( 981px, 1280px ), 20 | medium: ( 737px, 980px ), 21 | small: ( 481px, 736px ), 22 | xsmall: ( 361px, 480px ), 23 | xxsmall: ( null, 360px ) 24 | )); 25 | 26 | // Base. 27 | 28 | @import 'base/reset'; 29 | @import 'base/page'; 30 | @import 'base/typography'; 31 | 32 | // Component. 33 | 34 | @import 'components/row'; 35 | @import 'components/box'; 36 | @import 'components/button'; 37 | @import 'components/features'; 38 | @import 'components/form'; 39 | @import 'components/icon'; 40 | @import 'components/image'; 41 | @import 'components/list'; 42 | @import 'components/actions'; 43 | @import 'components/contact'; 44 | @import 'components/icons'; 45 | @import 'components/menu'; 46 | @import 'components/section'; 47 | @import 'components/split'; 48 | @import 'components/spotlights'; 49 | @import 'components/table'; 50 | @import 'components/wrapper'; 51 | 52 | // Layout. 53 | 54 | @import 'layout/header'; 55 | @import 'layout/wrapper'; 56 | @import 'layout/footer'; 57 | @import 'layout/sidebar'; 58 | @import 'layout/intro'; 59 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/assets/sass/noscript.scss: -------------------------------------------------------------------------------- 1 | @import 'libs/vars'; 2 | @import 'libs/functions'; 3 | @import 'libs/mixins'; 4 | @import 'libs/vendor'; 5 | @import 'libs/breakpoints'; 6 | @import 'libs/html-grid'; 7 | 8 | /* 9 | Hyperspace by HTML5 UP 10 | html5up.net | @ajlkn 11 | Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) 12 | */ 13 | 14 | /* Spotlights */ 15 | 16 | .spotlights { 17 | > section { 18 | > .image { 19 | &:before { 20 | opacity: 0 !important; 21 | } 22 | } 23 | 24 | > .content { 25 | > .inner { 26 | @include vendor('transform', 'none !important'); 27 | opacity: 1 !important; 28 | } 29 | } 30 | } 31 | } 32 | 33 | /* Wrapper */ 34 | 35 | .wrapper { 36 | > .inner { 37 | opacity: 1 !important; 38 | @include vendor('transform', 'none !important'); 39 | } 40 | } 41 | 42 | /* Sidebar */ 43 | 44 | #sidebar { 45 | > .inner { 46 | opacity: 1 !important; 47 | } 48 | 49 | nav { 50 | > ul { 51 | > li { 52 | @include vendor('transform', 'none !important'); 53 | opacity: 1 !important; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/base.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Hyperspace by HTML5 UP 10 | 11 | 12 | 13 | 14 | 15 | 16 | {%block body%} 17 | {%endblock%} 18 | 19 | 20 |
    21 |
    22 | 25 |
    26 |
    27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/contact.html: -------------------------------------------------------------------------------- 1 | {%extends 'hyperspace/base.html'%} 2 | 3 | 4 | {%block body%} 5 | 6 | 7 |
    8 | 9 | 10 |
    11 |
    12 | 13 |
    14 |

    Form

    15 |
    16 |
    17 |
    18 | {{form.name.label}} 19 | {{ form.name }} 20 |
    21 |
    22 | {{form.email.label}} 23 | {{ form.email }} 24 |
    25 | 26 |
    27 | {{form.message.label}} 28 | {{ form.message }} 29 |
    30 |
    31 |
      32 |
    • 33 | 34 |
    35 |
    36 |
    37 |
    38 |
    39 |
    40 |
    41 | 42 |
    43 | 44 | 45 | 46 | {%endblock%} 47 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/generic.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Generic - Hyperspace by HTML5 UP 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 28 | 29 | 30 | 31 | 32 |
    33 |
    34 | 37 |
    38 |
    39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic01.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic02.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic03.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic03.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic04.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic05.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic05.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/images/pic06.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/images/pic06.jpg -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ARJ", 3 | "version": "1.0.20000000000003" 4 | } 5 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/page.html: -------------------------------------------------------------------------------- 1 | {%extends 'hyperspace/base.html'%} 2 | {%block body%} 3 | 4 | 5 |
    6 | 7 | 8 |
    9 |
    10 |

    {{page.title}}

    11 | 12 | {{page.get_content()}} 13 |
    14 |
    15 | 16 |
    17 | {%endblock%} 18 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/render_demo.html: -------------------------------------------------------------------------------- 1 | 2 |

    WWW Index

    3 |

    Fruit {{ fruit }}

    4 | -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/sections/footer.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/sections/footer.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/sections/nav.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/sections/nav.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/sections/resources.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shopyo/pythoncms/2434a85fcc0e91176b398f654afde094233f0c7c/pythoncms/static/themes/front/hyperspace/sections/resources.html -------------------------------------------------------------------------------- /pythoncms/static/themes/front/hyperspace/styles.css: -------------------------------------------------------------------------------- 1 | 2 | html { 3 | scroll-behavior: smooth; 4 | } 5 | .suggest { 6 | 7 | } 8 | 9 | .suggest span { 10 | padding-left: 5px; 11 | padding-right: 5px; 12 | margin: 5px; 13 | min-width: 50px; 14 | } 15 | 16 | a{ 17 | text-decoration: inherit; 18 | color: inherit; 19 | } 20 | a:hover{ 21 | text-decoration: inherit; 22 | color: inherit; 23 | } 24 | 25 | #flashed-messages{ 26 | padding: 5px; 27 | position: fixed; 28 | right: 5px; 29 | top: 5px; 30 | z-index: 10; 31 | height: 300px; 32 | overflow-y: scroll; 33 | 34 | } 35 | #flashed-messages::-webkit-scrollbar { 36 | display: none; 37 | } 38 | /* Hide scrollbar for IE and Edge */ 39 | #flashed-messages{ 40 | -ms-overflow-style: none; 41 | } 42 | -------------------------------------------------------------------------------- /pythoncms/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | import pytest 5 | from app import create_app 6 | from shopyo.api.file import tryrmtree 7 | 8 | # from shopyo.app import app as _app 9 | 10 | 11 | @pytest.fixture(scope="module") 12 | def temp_app(): 13 | return create_app("testing") 14 | 15 | 16 | @pytest.fixture 17 | def app(tmpdir, app_type, temp_app): 18 | src = os.path.join(temp_app.instance_path, "config.py") 19 | dest = tmpdir.join("temp_config.py") 20 | dest.write("") 21 | shutil.copy(src, dest) 22 | tryrmtree(temp_app.instance_path) 23 | dev_app = create_app(app_type) 24 | yield dev_app 25 | shutil.copy(dest, src) 26 | -------------------------------------------------------------------------------- /pythoncms/tests/test_configs.py: -------------------------------------------------------------------------------- 1 | """ 2 | test all the different configurations types in 3 | config.py 4 | """ 5 | import pytest 6 | 7 | 8 | class TestAppConfigs: 9 | @pytest.mark.parametrize("app_type", ["development"]) 10 | def test_dev_app_config(self, app): 11 | 12 | config = app.config 13 | 14 | assert "ENV" in config 15 | assert config["ENV"] == "development" 16 | assert "DEBUG" in config 17 | assert config["DEBUG"] is True 18 | assert config["LOGIN_DISABLED"] is not None 19 | assert "SECRET_KEY" in config 20 | assert config["SECRET_KEY"] is not None 21 | assert "SQLALCHEMY_DATABASE_URI" in config 22 | assert config["SQLALCHEMY_DATABASE_URI"] is not None 23 | assert config["MAIL_SERVER"] in ["localhost", "console"] 24 | assert "MAIL_PORT" in config 25 | assert "MAIL_USERNAME" in config 26 | assert "MAIL_PASSWORD" in config 27 | assert "MAIL_DEFAULT_SENDER" in config 28 | 29 | # @pytest.mark.parametrize("app_type", ["production"]) 30 | # def test_prod_app_config(self, app): 31 | # """ 32 | # Test the productions configs. Environment variable 33 | # configs(private configs) are loaded from .test.prod.env just 34 | # to make sure these are loaded correctly 35 | # """ 36 | # config = app.config 37 | 38 | # assert "ENV" in config 39 | # assert config["ENV"] == "production" 40 | # assert "DEBUG" in config 41 | # assert config["DEBUG"] is False 42 | # assert "SECRET_KEY" in config 43 | # assert config["SECRET_KEY"] == "secret" 44 | # assert "EMAIL_CONFIRMATION_DISABLED" in config 45 | # assert config["MAIL_SERVER"] not in ["localhost", "console"] 46 | # assert "MAIL_PORT" in config 47 | # assert "MAIL_USERNAME" in config 48 | # assert config["MAIL_USERNAME"] == "foo@gmail.com" 49 | # assert "MAIL_PASSWORD" in config 50 | # assert config["MAIL_PASSWORD"] == "pass" 51 | # assert "MAIL_DEFAULT_SENDER" in config 52 | # assert config["MAIL_DEFAULT_SENDER"] == "foo@gmail.com" 53 | # assert "SQLALCHEMY_DATABASE_URI" in config 54 | # assert ( 55 | # config["SQLALCHEMY_DATABASE_URI"] 56 | # == "mysql+pymysql://db_username:db_password@db_host/db_name" 57 | # ) 58 | -------------------------------------------------------------------------------- /pythoncms/tests/test_dunder_main.py: -------------------------------------------------------------------------------- 1 | # import os 2 | # import pytest 3 | # from shopyo import __main__ 4 | # def test_no_args(monkeypatch, capfd): 5 | # monkeypatch.setattr("sys.argv", [""]) 6 | # __main__.main() 7 | # captured = capfd.readouterr() 8 | # assert "No arguments supplied" in captured.out 9 | # def test_arg_no_env(monkeypatch, capfd): 10 | # monkeypatch.setattr("sys.argv", ["testok"]) 11 | # __main__.main() 12 | # captured = capfd.readouterr() 13 | # assert "Please use Shopyo in a virtual environment for this command" in captured.out 14 | import subprocess 15 | import sys 16 | 17 | 18 | def test_no_args(capfd): 19 | subprocess.run([sys.executable, "__main__.py"], text=True) 20 | captured = capfd.readouterr() 21 | assert "No arguments supplied" in captured.out 22 | -------------------------------------------------------------------------------- /pythoncms/tests/test_manage.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | 5 | def test_managepy(capfd): 6 | subprocess.run([sys.executable, "manage.py", "testok"], text=True) 7 | captured = capfd.readouterr() 8 | assert "test ok!" in captured.out 9 | -------------------------------------------------------------------------------- /pythoncms/wsgi.py.example: -------------------------------------------------------------------------------- 1 | # +++++++++++ FLASK +++++++++++ 2 | # Flask works like any other WSGI-compatible framework, we just need 3 | # to import the application. Often Flask apps are called "app" so we 4 | # may need to rename it during the import: 5 | # 6 | # 7 | import os 8 | import sys 9 | 10 | sys.path.append(os.getcwd()) 11 | from app import create_app 12 | 13 | # 14 | # The "/home/appinv" below specifies your home 15 | # directory -- the rest should be the directory you uploaded your Flask 16 | # code to underneath the home directory. So if you just ran 17 | # "git clone git@github.com/myusername/myproject.git" 18 | # ...or uploaded files to the directory "myproject", then you should 19 | # specify "/home/appinv/myproject" 20 | # on shell do pwd to get a path like this:'/home2/folder/shopyo/shopyo' set path to this 21 | path = "" 22 | if path not in sys.path: 23 | sys.path.insert(0, path) 24 | # 25 | 26 | 27 | application = create_app("production") 28 | 29 | # 30 | # NB -- many Flask guides suggest you use a file called run.py; that's 31 | # not necessary on PythonAnywhere. And you should make sure your code 32 | # does *not* invoke the flask development server with app.run(), as it 33 | # will prevent your wsgi file from working. 34 | # whatever app you specify, modify that 35 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | shopyo==4.12.1 2 | SQLAlchemy==1.4.46 3 | python-dotenv 4 | shopyo-appadmin==1.2.0 5 | shopyo-auth==1.2.0 6 | shopyo-base==1.2.0 7 | shopyo-dashboard==1.1.1 8 | shopyo-i18n==1.1.0 9 | shopyo-page==1.2.0 10 | shopyo-settings==1.2.0 11 | shopyo-theme==1.1.0 -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = 3 | py39 4 | py38 5 | py37 6 | py36 7 | skip_missing_interpreters=true 8 | 9 | [testenv] 10 | changedir = pythoncms 11 | deps = 12 | -rrequirements.txt 13 | -rdev_requirements.txt 14 | commands = python -m pytest {posargs} 15 | --------------------------------------------------------------------------------