├── .codeclimate.yml ├── .coveragerc ├── .dockerignore ├── .gitattributes ├── .gitignore ├── .travis.yml ├── Dockerfile ├── ISSUE_TEMPLATE.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── cartoview ├── __init__.py ├── app_manager │ ├── __init__.py │ ├── admin.py │ ├── api.py │ ├── context_processors.py │ ├── decorators.py │ ├── exceptions.py │ ├── fixtures │ │ ├── app_stores.json │ │ ├── app_stores_exchange.json │ │ └── app_stores_qgis.json │ ├── forms.py │ ├── helpers.py │ ├── installer.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ ├── install_app.py │ │ │ ├── load_current_apps.py │ │ │ └── update_current_apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20171001_1057.py │ │ ├── 0003_auto_20171002_0445.py │ │ ├── 0004_auto_20171002_0446.py │ │ ├── 0005_delete_apptag.py │ │ ├── 0006_app_default_config.py │ │ ├── 0007_auto_20180128_0116.py │ │ ├── 0008_appinstance_logo.py │ │ ├── 0009_auto_20180920_1659.py │ │ ├── 0010_auto_20181118_1333.py │ │ ├── 0011_auto_20200623_1741.py │ │ └── __init__.py │ ├── models.py │ ├── resources.py │ ├── rest.py │ ├── search_indexes.py │ ├── serializers.py │ ├── settings.py │ ├── static │ │ └── app_manager │ │ │ ├── css │ │ │ ├── appinstance_list.css │ │ │ └── manager.css │ │ │ ├── img │ │ │ └── no-image.jpg │ │ │ ├── js │ │ │ ├── manager.js │ │ │ └── resources.js │ │ │ └── vendor │ │ │ ├── angular-aria │ │ │ └── angular-aria.min.js │ │ │ ├── angular-bootstrap │ │ │ └── ui-bootstrap-tpls.min.js │ │ │ ├── angular-drag-and-drop-lists │ │ │ └── angular-drag-and-drop-lists.min.js │ │ │ ├── angular-img-fallback │ │ │ └── angular.dcb-img-fallback.min.js │ │ │ ├── angular-resource │ │ │ └── angular-resource.min.js │ │ │ └── angular │ │ │ └── angular.min.js │ ├── templates │ │ ├── app_instance │ │ │ ├── _resourcebase_snippet.html │ │ │ ├── _search_content.html │ │ │ └── search_scripts.html │ │ ├── app_manager │ │ │ ├── app_install_base.html │ │ │ ├── app_instance_list.html │ │ │ ├── appinstance_base.html │ │ │ ├── appinstance_detail.html │ │ │ ├── appinstance_metadata.html │ │ │ ├── apps.html │ │ │ ├── apps_table.html │ │ │ ├── dynamic_scripts.html │ │ │ ├── edit_launcher_modal.html │ │ │ ├── install_app_panel.html │ │ │ ├── install_result.html │ │ │ ├── manage.html │ │ │ └── rest_api │ │ │ │ ├── base.html │ │ │ │ ├── edit.html │ │ │ │ ├── home.html │ │ │ │ └── list.html │ │ ├── bootstrapform │ │ │ ├── field.html │ │ │ ├── form.html │ │ │ └── formset.html │ │ └── search │ │ │ └── indexes │ │ │ └── app_manager │ │ │ └── appinstance_text.txt │ ├── tests │ │ ├── __init__.py │ │ ├── test_commands.py │ │ ├── test_decorators.py │ │ ├── test_helpers.py │ │ ├── test_installer.py │ │ ├── test_req_installer.py │ │ └── test_views.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── apps_handler │ ├── __init__.py │ ├── apps.py │ ├── apps_operations.py │ ├── config.py │ ├── db_parser.py │ ├── req_installer.py │ ├── tests │ │ ├── __init__.py │ │ └── test_db_parser.py │ └── utils.py ├── cartoview_api │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── rest.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_rest.py │ │ └── test_views.py │ └── views.py ├── celery.py ├── fixtures │ └── default_oauth_apps_docker.json ├── local_settings.py.sample ├── locale │ └── ar │ │ └── LC_MESSAGES │ │ └── django.po ├── log_handler.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── cherry.conf │ │ └── cherry_server.py ├── settings.py ├── static │ ├── app_manager │ │ ├── Sortable.js │ │ ├── app.css │ │ ├── apps_list.css │ │ ├── bootstrap-sortable │ │ │ ├── css │ │ │ │ └── bootstrap-sortable.css │ │ │ └── js │ │ │ │ ├── bootstrap-sortable.js │ │ │ │ └── moment.min.js │ │ ├── default-logo.png │ │ ├── images │ │ │ ├── Access-Denied.jpg │ │ │ ├── ajax-loader.gif │ │ │ ├── cartoview.png │ │ │ └── geonode-dashboard.png │ │ ├── install.js │ │ └── jquery-jtemplates.js │ ├── bootstrap-3-arabic │ │ ├── css │ │ │ ├── bootstrap-arabic-theme.css │ │ │ ├── bootstrap-arabic-theme.css.map │ │ │ ├── bootstrap-arabic-theme.min.css │ │ │ ├── bootstrap-arabic.css │ │ │ ├── bootstrap-arabic.css.map │ │ │ └── bootstrap-arabic.min.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ └── js │ │ │ ├── bootstrap-arabic.js │ │ │ └── bootstrap-arabic.min.js │ ├── cartoview │ │ ├── img │ │ │ ├── app.png │ │ │ ├── background.png │ │ │ ├── cartoview-logo-sm.png │ │ │ ├── cartoview-logo-text-white.png │ │ │ ├── cartoview-logo-text.png │ │ │ ├── cartoview-logo.png │ │ │ ├── edit.png │ │ │ ├── icon.png │ │ │ ├── layers.png │ │ │ ├── logo.png │ │ │ └── map.png │ │ └── js │ │ │ ├── appinstance-service.js │ │ │ ├── appinstance │ │ │ └── search.js │ │ │ ├── index.js │ │ │ └── top-toolbar.js │ ├── compare-versions │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bower.json │ │ ├── index.js │ │ └── package.json │ └── geonode │ │ └── img │ │ ├── favicon.ico │ │ └── logo.png ├── store_api │ ├── __init__.py │ ├── api.py │ └── apps.py ├── templates │ ├── cartoview │ │ ├── base.html │ │ ├── check_version.js │ │ ├── footer.html │ │ ├── search_box.html │ │ └── theme_css.html │ └── geonode_base.html ├── templatetags │ ├── __init__.py │ └── cartoview_tags.py ├── tests │ ├── __init__.py │ ├── test_log_handler.py │ ├── test_template_tags.py │ ├── test_version_module.py │ └── test_views.py ├── urls.py ├── version.py ├── views.py └── wsgi.py ├── dev_config.yml ├── docker-compose.yml ├── docs ├── FAQ.md ├── contribute.md ├── css │ └── custom.css ├── demo.md ├── for-developers.md ├── img │ ├── cartoview-logo.png │ ├── demo │ │ ├── cartoview-apps.png │ │ └── cartoview-demo.png │ ├── for-developers │ │ ├── app_home.PNG │ │ ├── apps_panel.PNG │ │ ├── developers_app.png │ │ └── single_instance.PNG │ ├── installation │ │ ├── Docker │ │ │ ├── cartoview_admin.png │ │ │ ├── cartoview_browser.PNG │ │ │ ├── cartoview_cli.PNG │ │ │ ├── cartoview_docker.PNG │ │ │ ├── cartoview_logs.png │ │ │ ├── compose_v2.png │ │ │ ├── geoserver.png │ │ │ ├── geoserver_admin.png │ │ │ ├── geoserver_pass1.png │ │ │ ├── geoserver_pass2.png │ │ │ ├── geoserver_pass3.png │ │ │ └── whale_icon.png │ │ ├── Installer │ │ │ ├── admin-configuration-1.png │ │ │ ├── admin-configuration-2.png │ │ │ ├── admin.png │ │ │ ├── apps.png │ │ │ ├── cartoview-directory.png │ │ │ ├── cartoview-home.png │ │ │ ├── cartoview-services.png │ │ │ ├── db-mode.png │ │ │ ├── domain-ip.png │ │ │ ├── gis-db.png │ │ │ ├── installation-location.png │ │ │ ├── installing.png │ │ │ ├── launch.png │ │ │ ├── postgres-credentials.png │ │ │ ├── postgres-dir.png │ │ │ ├── restart-service.png │ │ │ ├── server-details.png │ │ │ ├── services.png │ │ │ └── web-db.png │ │ ├── Ubuntu │ │ │ ├── cartoview.png │ │ │ ├── geoserver-login.png │ │ │ ├── geoserver-password.png │ │ │ ├── geoserver.png │ │ │ ├── pycharm_1.png │ │ │ ├── pycharm_2.png │ │ │ ├── pycharm_3.png │ │ │ └── tomcat_manager.png │ │ └── Windows │ │ │ ├── install_gdal.png │ │ │ ├── install_python.png │ │ │ ├── pgAdmin │ │ │ ├── add-extension.png │ │ │ ├── create-database.png │ │ │ ├── database-name.png │ │ │ ├── new-server-1.png │ │ │ ├── new-server-2.png │ │ │ ├── pgAdmin-dashboard.png │ │ │ └── set-password.png │ │ │ ├── postgres │ │ │ ├── access-terminal.png │ │ │ ├── add-path.png │ │ │ ├── postgres1.png │ │ │ ├── postgres2.png │ │ │ ├── postgres3.png │ │ │ ├── postgres4.png │ │ │ ├── postgres5.png │ │ │ └── restart-postgres.png │ │ │ ├── pycharm │ │ │ ├── env-settings.png │ │ │ ├── env-variables.png │ │ │ ├── terminal-check.png │ │ │ └── terminal-settings.png │ │ │ └── start-geoserver.png │ ├── manage-apps.png │ └── upload-app │ │ ├── add_package.png │ │ ├── app_manager.png │ │ ├── app_market.png │ │ ├── app_on_appstore.png │ │ ├── create_app.png │ │ ├── login.png │ │ ├── my_apps.png │ │ ├── now_App_on_market.png │ │ ├── repo.png │ │ ├── user_info_1.png │ │ └── user_info_2.png ├── index.md ├── install-app.md ├── installation │ ├── cartoview-project.md │ ├── docker.md │ ├── ubuntu.md │ ├── vagrant.md │ ├── windows-installer.md │ └── windows.md ├── issues.md ├── key-features.md └── upload-app.md ├── env ├── celery.env ├── django.env ├── postgis.env └── tomcat.env ├── manage.py ├── mkdocs.yml ├── pavement.py ├── scripts ├── database │ └── setup.sh ├── docker │ └── setup.sh ├── misc │ └── jetty-runner.xml └── nginx │ └── nginx.conf ├── setup.cfg └── setup.py /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | pep8: 3 | enabled: true 4 | 5 | ratings: 6 | paths: 7 | - "**.py" 8 | exclude_patterns: 9 | - "static/" 10 | - "**/*.js" 11 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit = cartoview/app_manager/settings.py, 3 | cartoview/wsgi.py, 4 | cartoview/settings.py, 5 | cartoview/celery.py, 6 | */migrations/* -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | .DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | cartoview/static/* linguist-vendored=true 2 | cartoview/static/admin/* linguist-vendored=true 3 | cartoview/static/app_manager linguist-vendored=true 4 | cartoview/templates/**/*.html linguist-vendored=true 5 | cartoview/templates/admin/**/*.html linguist-vendored=true 6 | cartoview/static/admin/**/*.js linguist-vendored=true 7 | cartoview/static/bootstrap-3-arabic/**/*.js linguist-vendored=true 8 | cartoview/static/bootstrap-3-arabic/**/*.css linguist-vendored=true 9 | cartoview/static/admin/**/*.css linguist-vendored=true 10 | cartoview/static/**/*.js linguist-vendored=true 11 | cartoview/static/**/*.css linguist-vendored=true 12 | cartoview/static/*.js linguist-vendored=true 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: focal 3 | language: python 4 | cache: 5 | directories: 6 | - "$HOME/.cache/pip" 7 | before_cache: 8 | - rm -f $HOME/.cache/pip/log/debug.log 9 | addons: 10 | postgresql: '12' 11 | apt: 12 | packages: 13 | - postgresql-12 14 | - postgresql-client-12 15 | - postgresql-12-postgis-3 16 | - libevent-dev 17 | services: 18 | - postgresql 19 | python: 20 | - '3.10' 21 | env: 22 | global: 23 | - CARTOVIEW_TEST=True 24 | - DATABASE_URL=postgis://cartoview:cartoview@localhost:5432/cartoview 25 | - DATASTORE_DATABASE_URL=postgis://cartoview:cartoview@localhost:5432/cartoview_data 26 | virtualenv: 27 | system_site_packages: false 28 | branches: 29 | except: 30 | - 2.6.x_compatible 31 | - 1.4.4-(mapground) 32 | - mapground(1.8) 33 | - exchange-1.4.x 34 | before_install: 35 | - sudo apt-get autoremove sqlite3; 36 | - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/12/main/postgresql.conf; 37 | - sudo sed -i 's/peer/trust/' /etc/postgresql/12/main/pg_hba.conf; 38 | - sudo pg_ctlcluster 12 main restart; 39 | install: 40 | - sudo apt-get -qq -y update 41 | - sudo apt-get install -y gcc gettext python3-pip libpq-dev sqlite3 spatialite-bin libsqlite3-mod-spatialite libsqlite3-dev git gdal-bin lsof 42 | psmisc 43 | - sudo apt-get install -y python3-gdal python-lxml 44 | - sudo apt-get install -y python3-virtualenv python-pil python3-pil python3-lxml python3-pyproj python3-shapely python3-httplib2 python3-httplib2 45 | - sudo apt-get install -y python3-dev libgdal-dev libgeoip-dev libxml2 46 | libxml2-dev libxslt-dev git default-jdk 47 | - sudo apt-get install -y python-dev libxml2 libxml2-dev libxslt1-dev zlib1g-dev libjpeg-dev 48 | libpq-dev libgdal-dev git default-jdk 49 | - sudo apt-get install -y libmemcached-dev libsasl2-dev zlib1g-dev python-pylibmc 50 | python-setuptools 51 | - sudo apt-get install -y curl build-essential build-essential python-dev libffi-dev 52 | libssl-dev 53 | - sudo apt-get update 54 | - sudo apt install -y openjdk-8-jre openjdk-8-jdk ant maven; 55 | - sudo update-java-alternatives --set java-1.8.0-openjdk-amd64; 56 | - export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::"); 57 | - export PATH=$JAVA_HOME'bin/java':$PATH; 58 | - pip install celery 59 | - pip install pygdal==`gdal-config --version`.* 60 | - pip install tqdm 61 | - pip install -e . --upgrade 62 | - pip install timeout-decorator 63 | - paver setup_geoserver 64 | - paver start_geoserver 65 | - pip install coveralls 66 | before_script: 67 | - psql -U postgres -c "create extension postgis" 68 | - chmod +x scripts/database/setup.sh 69 | - scripts/database/setup.sh 70 | - python manage.py collectstatic --no-input 71 | script: 72 | - flake8 73 | - paver run_cartoview_test 74 | after_success: 75 | - coveralls 76 | deploy: 77 | provider: pypi 78 | user: cartologic 79 | password: 80 | secure: I55fbMkUDNnPVRejHETev9viO7nY9bD+wXzPk0MoLKhx5KceyAPYXnznVYMid7FVzBZzP6pLT9k8lZTC+Xv6ZET8GK/cgwPd+i3n8upk2PKAzjUCxutXrxTPHCKyd9HHz051Wt/0vJvhKsw37E/WPFach007gGjF2J/diGdEFtvrKYE+ixYd6wu6VevKGtCce4Wt2HY7fZ7rfhHbEdX/k2hOzrBiD5fwHp+GJdcczGpzKdtdKvdhkUEDsBs6y1hUgGbCF9i3TiagEA3/Md/bG4mU4P+B1oAkdXue9TVLOEMXD1rpdR/EMm0FwMsnZWtaYTTkvEmPrYBhLcN7NlM0/VaSJ6ejbD9nk+37uE2h7S/xKsmCezzYEDeDAXmMa3WDQQrSYLuypN8DgxFhYiac+qYIBSMUOyI+EJXSpJ9iHaseofvF+32DAm6U6P2kEpda619HuEEF++JxthVJ01hAaQDoezEisirXT0pWKEQcSbTeI5hTP0kCxxlpqgg1CNmSvSXQbTMs9FyOTIJBHkhj4rLnTI+UPv99ig0CFzQO2HbBa+4kiWl4LpGZrNd9ei1wlxpSScJsQbu3bYUfpRqY7AiPkYkaIb1jCCWwxS/AgBX7YbT4os/E+zBQGvldQncCXhtVYA6+cpGzZM29lKUHy4KMNsiB744a48AGGUv04cg= 81 | on: 82 | tags: true 83 | all_branches: true 84 | condition: $TRAVIS_TAG =~ ^v([0-9]+\.?){2,3}(b[0-9]+|rc[0-9]+){0,1} 85 | notifications: 86 | email: 87 | - ahmednosman@cartologic.com 88 | - ahmedNourElDeen@cartologic.com 89 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10.2-buster 2 | LABEL "MAINTAINER"="Cartologic Development Team" 3 | 4 | ENV PYTHONUNBUFFERED 1 5 | ARG GEONODE_DEV=true 6 | ARG APP_DIR=/usr/src/carto_app 7 | 8 | COPY . ${APP_DIR}/cartoview 9 | RUN chmod +x ${APP_DIR}/cartoview/scripts/docker/setup.sh 10 | RUN ${APP_DIR}/cartoview/scripts/docker/setup.sh 11 | 12 | VOLUME ${APP_DIR} 13 | WORKDIR ${APP_DIR}/cartoview 14 | 15 | CMD ["/bin/bash"] 16 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Please fill the following information to avoid closing issue 2 | 3 | _Describe your issue in detail_ 4 | 5 | - Cartoview Version : (x.xx.x) 6 | - Geonode Version : (x.xx.x) 7 | - log (optional): 8 | ``` 9 | please 10 | put 11 | your 12 | log 13 | here 14 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2017, Cartologic 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.py 3 | cartoview/__init__.py 4 | cartoview/celeryapp.py 5 | cartoview/pre_settings.py 6 | cartoview/settings.py 7 | cartoview/urls.py 8 | cartoview/views.py 9 | cartoview/wsgi.py 10 | include cartoview/bower.json 11 | include README.md 12 | include cartoview/.bowerrc 13 | recursive-include cartoview/static * 14 | recursive-include cartoview/templates * 15 | recursive-include cartoview/app_manager/static * 16 | recursive-include cartoview/app_manager/templates * 17 | recursive-include cartoview/workspace/templates * 18 | recursive-include cartoview/app_manager/fixtures * 19 | recursive-include cartoview/user_engage/static * 20 | recursive-include cartoview/user_engage/templates * 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | up: 2 | # bring up the services 3 | docker-compose up -d 4 | 5 | sync: up 6 | # set up the database tablea 7 | docker-compose exec cartoview python manage.py migrate 8 | docker-compose exec cartoview python manage.py loaddata sample_admin.json 9 | docker-compose exec cartoview python manage.py loaddata default_oauth_apps_docker.json 10 | docker-compose exec cartoview python manage.py loaddata app_stores.json 11 | docker-compose exec cartoview python manage.py loaddata initial_data.json 12 | 13 | backfill_api_keys: 14 | docker-compose exec cartoview python manage.py backfill_api_keys 15 | 16 | prepare_manager: up 17 | #make migration for app_manager 18 | docker-compose exec cartoview python manage.py makemigrations app_manager 19 | migrate_account: up 20 | docker-compose exec cartoview python manage.py migrate account 21 | migrate: 22 | docker-compose exec cartoview python manage.py migrate --noinput 23 | wait: 24 | sleep 5 25 | logs: 26 | docker-compose logs --follow 27 | logs_tail: 28 | docker-compose logs --follow --tail 100 29 | logs_tail_cartoview: 30 | docker-compose logs --follow --tail 100 cartoview 31 | logs_tail_geoserver: 32 | docker-compose logs --follow --tail 100 geoserver 33 | down: 34 | docker-compose down 35 | reset: down up wait sync 36 | 37 | collect_static: up 38 | docker-compose exec cartoview python manage.py collectstatic --noinput 39 | 40 | prepare_oauth: 41 | docker-compose exec cartoview paver prepare_docker_oauth_fixture 42 | docker-compose exec cartoview paver install_docker_data_dir 43 | 44 | run: up wait prepare_oauth prepare_manager sync collect_static backfill_api_keys 45 | 46 | static_db: up sync wait collect_static 47 | 48 | update: 49 | docker-compose exec cartoview pip install cartoview --no-cache-dir -U 50 | docker-compose restart cartoview 51 | new_app: collect_static 52 | docker-compose restart cartoview 53 | -------------------------------------------------------------------------------- /cartoview/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = (1, 40, 0, 'unstable', 0) 2 | __compatible_with__ = [] 3 | 4 | 5 | def get_current_version(): 6 | from .version import get_version 7 | return get_version(__version__) 8 | -------------------------------------------------------------------------------- /cartoview/app_manager/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/__init__.py -------------------------------------------------------------------------------- /cartoview/app_manager/admin.py: -------------------------------------------------------------------------------- 1 | from __future__ import (absolute_import, division, print_function, 2 | unicode_literals) 3 | 4 | from django.contrib import admin 5 | from django.http import HttpResponseServerError 6 | from future import standard_library 7 | 8 | from .installer import AppInstaller 9 | from .models import App, AppInstance, AppStore, AppType 10 | 11 | standard_library.install_aliases() 12 | 13 | 14 | def uninstall_selected(modeladmin, request, queryset): 15 | for app in queryset: 16 | try: 17 | app_store = app.store.id if app.store else None 18 | installer = AppInstaller( 19 | app.name, 20 | store_id=app_store, 21 | user=request.user, 22 | version=app.version) 23 | installer.uninstall() 24 | except Exception as e: 25 | return HttpResponseServerError(e) 26 | 27 | 28 | uninstall_selected.short_description = "Uninstall Selected Apps" 29 | 30 | 31 | @admin.register(App) 32 | class AppAdmin(admin.ModelAdmin): 33 | ordering = ('order',) 34 | actions = [uninstall_selected] 35 | 36 | 37 | admin.site.register(AppType) 38 | admin.site.register(AppInstance) 39 | admin.site.register(AppStore) 40 | -------------------------------------------------------------------------------- /cartoview/app_manager/api.py: -------------------------------------------------------------------------------- 1 | from __future__ import (absolute_import, division, print_function, 2 | unicode_literals) 3 | 4 | import warnings 5 | 6 | from django.conf.urls import include, url 7 | from django.shortcuts import render 8 | from future import standard_library 9 | from tastypie.api import Api as TastypieApi 10 | from tastypie.utils import trailing_slash 11 | 12 | from cartoview.log_handler import get_logger 13 | from .serializers import HTMLSerializer 14 | 15 | logger = get_logger(__name__) 16 | standard_library.install_aliases() 17 | 18 | 19 | def home(request): 20 | return render(request, 'app_manager/rest_api/home.html', 21 | {'apis': sorted(rest_api.apis.keys())}) 22 | 23 | 24 | class BaseApi(TastypieApi): 25 | """ 26 | A version of the Api that doesn't require a name. 27 | It also uses the whippedcream serializer by default. 28 | """ 29 | 30 | def __init__(self, app_name): 31 | self.app_name = app_name 32 | super(BaseApi, self).__init__('', HTMLSerializer) 33 | 34 | @property 35 | def urls(self): 36 | """ 37 | Provides URLconf details for the ``Api`` and all registered 38 | ``Resources`` beneath it. 39 | """ 40 | if self.api_name: 41 | api_pattern = '(?P%s)' 42 | top_level = r"^%s%s$" % (api_pattern, trailing_slash()) 43 | else: 44 | api_pattern = '(?P)' 45 | top_level = r"^$" 46 | 47 | pattern_list = [ 48 | url(top_level, 49 | self.wrap_view('top_level'), 50 | name="%s_rest_url" % self.app_name), 51 | ] 52 | 53 | for name in sorted(self._registry.keys()): 54 | resource = self._registry[name] 55 | resource.api_name = self.api_name 56 | pattern_list.append( 57 | url(r"^%s" % api_pattern, include(resource.urls))) 58 | 59 | urlpatterns = self.prepend_urls() 60 | overridden_urls = self.override_urls() 61 | if overridden_urls: 62 | warnings.warn( 63 | "'override_urls' is a deprecated method & \ 64 | will be removed by v1.0.0.\ 65 | Please rename your method to ``prepend_urls``." 66 | ) 67 | 68 | urlpatterns += overridden_urls 69 | 70 | urlpatterns += pattern_list 71 | return urlpatterns 72 | 73 | 74 | class Api(object): 75 | 76 | def __init__(self): 77 | self.apis = {} 78 | 79 | def register(self, resource, app_name=None, canonical=True): 80 | module_name = resource.__module__ 81 | 82 | if app_name is None: 83 | try: 84 | app_name = module_name.split('.')[1] 85 | except BaseException as e: 86 | logger.error(e) 87 | if app_name not in self.apis: 88 | self.apis[app_name] = BaseApi(app_name) 89 | self.apis[app_name].register(resource, canonical) 90 | 91 | @property 92 | def urls(self): 93 | pattern_list = [ 94 | url(r'^$', 95 | home, 96 | name='cartoview_rest_url'), 97 | ] 98 | for name in sorted(self.apis.keys()): 99 | pattern_list.append( 100 | url(r"^%s/" % name, include(self.apis[name].urls))) 101 | self.urlpatterns = pattern_list 102 | return self.urlpatterns 103 | 104 | def register_app_urls(self, app_name): 105 | self.urlpatterns.append( 106 | url(r"^%s/" % app_name, include(self.apis[app_name].urls))) 107 | 108 | 109 | rest_api = Api() 110 | -------------------------------------------------------------------------------- /cartoview/app_manager/context_processors.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | from django.conf import settings 6 | from future import standard_library 7 | from geonode.groups.models import Group 8 | from geonode.maps.models import Dataset, Map 9 | from geonode.people.models import Profile 10 | from geonode.version import get_version 11 | from guardian.shortcuts import get_objects_for_user 12 | 13 | from cartoview import __version__ 14 | from cartoview.app_manager.models import App, AppInstance 15 | 16 | standard_library.install_aliases() 17 | 18 | 19 | def apps(request): 20 | return {'apps': App.objects.all().order_by('order')} 21 | 22 | 23 | def cartoview_processor(request): 24 | permitted = get_objects_for_user(request.user, 25 | 'base.view_resourcebase') 26 | cartoview_counters = { 27 | "apps": App.objects.count(), 28 | "app_instances": AppInstance.objects.filter(id__in=permitted).count(), 29 | "maps": Map.objects.filter(id__in=permitted).count(), 30 | "layers": Dataset.objects.filter(id__in=permitted).count(), 31 | "users": Profile.objects.exclude(username="AnonymousUser").count(), 32 | "groups": Group.objects.exclude(name="anonymous").count() 33 | } 34 | 35 | defaults = { 36 | 'apps': App.objects.all().order_by('order'), 37 | 'CARTOVIEW_VERSION': get_version(list(__version__)), 38 | 'APPS_MENU': settings.APPS_MENU, 39 | 'apps_instance_count': AppInstance.objects.all().count(), 40 | "cartoview_counters": cartoview_counters, 41 | 'instances': AppInstance.objects.all().order_by('app__order')[:5] 42 | } 43 | return defaults 44 | -------------------------------------------------------------------------------- /cartoview/app_manager/decorators.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.utils.translation import ugettext as _ 3 | 4 | from .exceptions import AppAlreadyInstalledException 5 | from .utils import resolve_appinstance 6 | 7 | PERMISSION_MSG_DELETE = _("You are not permitted to delete this Instance") 8 | PERMISSION_MSG_GENERIC = _("You do not have permissions for this Instance.") 9 | PERMISSION_MSG_MODIFY = _("You are not permitted to modify this Instance") 10 | PERMISSION_MSG_METADATA = _( 11 | "You are not permitted to modify this Instance's metadata") 12 | PERMISSION_MSG_VIEW = _("You are not permitted to view this Instance") 13 | 14 | 15 | def can_change_app_instance(function): 16 | def wrap(request, *args, **kwargs): 17 | instance_id = kwargs.get('instance_id', None) 18 | assert instance_id 19 | resolve_appinstance(request, instance_id, 'base.change_resourcebase', 20 | PERMISSION_MSG_MODIFY) 21 | return function(request, *args, **kwargs) 22 | 23 | # wrap.__doc__ = function.__doc__ 24 | # wrap.__name__ = function.__name__ 25 | return wrap 26 | 27 | 28 | def can_view_app_instance(function): 29 | def wrap(request, *args, **kwargs): 30 | instance_id = kwargs.get('instance_id', None) 31 | assert instance_id 32 | resolve_appinstance(request, instance_id, 'base.view_resourcebase', 33 | PERMISSION_MSG_VIEW) 34 | return function(request, *args, **kwargs) 35 | 36 | # wrap.__doc__ = function.__doc__ 37 | # wrap.__name__ = function.__name__ 38 | return wrap 39 | 40 | 41 | def restart_enabled(func): 42 | def wrap(*args, **kwargs): 43 | if not getattr(settings, "CARTOVIEW_TEST", False): 44 | return func(*args, **kwargs) 45 | 46 | return wrap 47 | 48 | 49 | def rollback_on_failure(func): 50 | def wrap(*args, **kwargs): 51 | this = args[0] 52 | try: 53 | return func(*args, **kwargs) 54 | except BaseException as e: 55 | if not isinstance(e, AppAlreadyInstalledException): 56 | if hasattr(this, '_rollback'): 57 | this._rollback() 58 | raise e 59 | 60 | return wrap 61 | -------------------------------------------------------------------------------- /cartoview/app_manager/exceptions.py: -------------------------------------------------------------------------------- 1 | class AppAlreadyInstalledException(BaseException): 2 | message = "Application is already installed." 3 | -------------------------------------------------------------------------------- /cartoview/app_manager/fixtures/app_stores.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "url": "https://appstore.cartoview.net/api/v1/", 5 | "is_default": true, 6 | "name": "Cartoview App Store", 7 | "server_type": "Geoserver" 8 | }, 9 | "model": "app_manager.appstore", 10 | "pk": 1 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /cartoview/app_manager/fixtures/app_stores_exchange.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "url": "https://appstore.cartoview.net/api/v1/", 5 | "is_default": true, 6 | "name": "Cartoview App Store", 7 | "server_type": "Exchange" 8 | }, 9 | "model": "app_manager.appstore", 10 | "pk": 1 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /cartoview/app_manager/fixtures/app_stores_qgis.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fields": { 4 | "url": "https://appstore.cartoview.net/api/v1/", 5 | "is_default": true, 6 | "name": "Cartoview App Store", 7 | "server_type": "Exchange" 8 | }, 9 | "model": "app_manager.appstore", 10 | "pk": 1 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /cartoview/app_manager/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | from django.forms import FileField, ModelForm 6 | from django.utils.translation import ugettext_lazy as _ 7 | # TODO: Review this file. Legacy??! 8 | from future import standard_library 9 | from geonode.base.forms import ResourceBaseForm 10 | from modeltranslation.forms import TranslationModelForm 11 | 12 | from .models import App, AppInstance 13 | 14 | standard_library.install_aliases() 15 | 16 | 17 | class AppInstallerForm(ModelForm): 18 | error_messages = { 19 | 'duplicate_app_name': 20 | _("An application with the same user has already installed."), 21 | 'invalid_package_file': 22 | _("The uploaded file is not an application package."), 23 | } 24 | package_file = FileField() 25 | 26 | class Meta(object): 27 | model = App 28 | fields = ("package_file",) 29 | 30 | 31 | class AppForm(ModelForm): 32 | class Meta(object): 33 | model = App 34 | fields = ("title",) 35 | 36 | 37 | class AppInstanceForm(TranslationModelForm): 38 | class Meta(object): 39 | model = AppInstance 40 | fields = [ 41 | 'title', 42 | 'abstract', 43 | ] 44 | 45 | 46 | class AppInstanceEditForm(ResourceBaseForm): 47 | class Meta(ResourceBaseForm.Meta): 48 | model = AppInstance 49 | exclude = ResourceBaseForm.Meta.exclude 50 | -------------------------------------------------------------------------------- /cartoview/app_manager/helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import stat 3 | 4 | from cartoview.log_handler import get_logger 5 | 6 | world_permission = 0o777 7 | logger = get_logger(__name__) 8 | 9 | 10 | def create_direcotry(path, mode=0o777): 11 | # please read the following section 12 | # https://docs.python.org/2/library/os.html#mkdir-modebits 13 | if not os.path.exists(path): 14 | try: 15 | previous_mask = os.umask(0) 16 | os.makedirs(path, mode=mode) 17 | except OSError as e: 18 | logger.error(e) 19 | finally: 20 | # set the previous mask back 21 | os.umask(previous_mask) 22 | 23 | 24 | def change_path_permission(path, mode=world_permission): 25 | os.chmod(path, mode) 26 | 27 | 28 | def octal_permissions(protection_bits): 29 | # this return octal permission 30 | return oct(stat.S_IMODE(protection_bits)) 31 | 32 | 33 | def get_path_permission(path): 34 | ''' on platforms that do not support symbolic links, 35 | lstat is an alias for stat() 36 | so we return a tuple of both 37 | ''' 38 | lst = os.lstat(path) 39 | st = os.stat(path) 40 | permission = octal_permissions(lst.st_mode), octal_permissions(st.st_mode) 41 | return permission 42 | 43 | 44 | def get_perm(fname): 45 | return stat.S_IMODE(os.lstat(fname)[stat.ST_MODE]) 46 | 47 | 48 | def make_writeable_recursive(path): 49 | for root, dirs, files in os.walk(path, topdown=False): 50 | for dir in [os.path.join(root, d) for d in dirs]: 51 | os.chmod(dir, get_perm(dir) | stat.S_IRUSR | # noqa 52 | stat.S_IRGRP | stat.S_IROTH) 53 | for file in [os.path.join(root, f) for f in files]: 54 | os.chmod(file, get_perm(file) | stat.S_IRUSR | # noqa 55 | stat.S_IRGRP | stat.S_IROTH) 56 | -------------------------------------------------------------------------------- /cartoview/app_manager/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/management/__init__.py -------------------------------------------------------------------------------- /cartoview/app_manager/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/management/commands/__init__.py -------------------------------------------------------------------------------- /cartoview/app_manager/management/commands/install_app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import print_function 3 | 4 | from django.core.management.base import BaseCommand 5 | from pkg_resources import parse_version 6 | 7 | from cartoview.app_manager.installer import AppInstaller 8 | from cartoview.app_manager.models import App, AppStore 9 | from cartoview.log_handler import get_logger 10 | 11 | logger = get_logger(__name__) 12 | 13 | 14 | def compare_version(v1, v2): 15 | return parse_version(v1) < parse_version(v2) 16 | 17 | 18 | class Command(BaseCommand): 19 | help = 'Install App' 20 | 21 | def add_arguments(self, parser): 22 | parser.add_argument( 23 | '-n', '--name', dest='name', help='Name Of The App To Install') 24 | parser.add_argument( 25 | '-av', 26 | '--app_version', 27 | type=str, 28 | dest='app_version', 29 | help='App Version') 30 | 31 | def handle(self, *args, **options): 32 | app_name = options.get('name') 33 | app_version = options.get('app_version') 34 | store = AppStore.objects.get(is_default=True) 35 | q = App.objects.filter(name=app_name) 36 | try: 37 | if q.count() == 0 or (q.first() and 38 | compare_version(q.first().version, 39 | app_version)): 40 | installer = AppInstaller(app_name, store.id, app_version) 41 | installer.install() 42 | except Exception as ex: 43 | logger.error(ex) 44 | -------------------------------------------------------------------------------- /cartoview/app_manager/management/commands/load_current_apps.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | 3 | from django.core.management.base import BaseCommand 4 | from geonode.people.models import Profile 5 | 6 | from cartoview.app_manager.models import App, AppType 7 | from cartoview.apps_handler.config import CartoviewApp 8 | from cartoview.log_handler import get_logger 9 | 10 | logger = get_logger(with_formatter=True) 11 | 12 | 13 | class Command(BaseCommand): 14 | help = 'Update existing apps' 15 | 16 | def handle(self, *args, **options): 17 | carto_apps = CartoviewApp.objects.get_active_apps().values() 18 | user = Profile.objects.filter(is_superuser=True).first() 19 | for carto_app in carto_apps: 20 | app_name = carto_app.name 21 | query = App.objects.filter(name=app_name) 22 | if query.count() == 0: 23 | try: 24 | # ensure that the folder is python module 25 | importlib.import_module(app_name) 26 | app = App( 27 | title=app_name, 28 | name=app_name, 29 | status="Alpha", 30 | license=None, 31 | version='1.0.0', 32 | installed_by=user, 33 | store=None, 34 | order=carto_app.order, 35 | single_instance=False) 36 | single = False 37 | try: 38 | installer = importlib.import_module( 39 | '%s.installer' % app_name) 40 | single = getattr(installer.info, 'single_instance', 41 | False) 42 | except BaseException: 43 | logger.error( 44 | ('%-15s installer.py not found so this app will ' + 45 | 'be marked as Multiple Instance') % (app_name)) 46 | app.single_instance = single 47 | app.save() 48 | category, created = AppType.objects.get_or_create( 49 | name='app_manager_loader') 50 | 51 | app.category.add(category) 52 | app.tags.add(*[ 53 | 'cartoview', 54 | ]) 55 | app.save() 56 | logger.info('%-15s loaded Successfully' % (app_name)) 57 | except Exception as e: 58 | logger.error(('Failed to load %-5s may be ' + 59 | 'app folder not found error: %-10s') % 60 | (app_name, e)) 61 | -------------------------------------------------------------------------------- /cartoview/app_manager/management/commands/update_current_apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import requests 4 | from django.core.management.base import BaseCommand 5 | 6 | from cartoview.app_manager.installer import AppJson, remove_unwanted 7 | from cartoview.app_manager.models import App 8 | from cartoview.store_api.api import StoreAppResource 9 | 10 | 11 | class Command(BaseCommand): 12 | help = 'Update existing apps' 13 | 14 | def handle(self, *args, **options): 15 | # stores = AppStore.objects.filter(is_default=True) 16 | # store = stores.first() 17 | for index, app in enumerate(App.objects.all()): 18 | try: 19 | if app.store: 20 | data = self.get_data_from_store(app.name, app.store.url) 21 | api_obj = StoreAppResource() 22 | bundle = api_obj.build_bundle(data=data) 23 | app_obj = api_obj.obj_get(bundle) 24 | data = app_obj 25 | app_serializer = AppJson(remove_unwanted(data)) 26 | app = app_serializer.get_app_object(app) 27 | app.save() 28 | print('[%-2s] %-35s updated' % (index + 1, app.name)) 29 | else: 30 | print('[%-2s] %-35s Ignored because No Store Available' % 31 | (index + 1, app.name)) 32 | except Exception as ex: 33 | print('[%-2s] %-35s Failed error message %-25s' % 34 | (index + 1, app.name, ex)) 35 | 36 | def get_data_from_store(self, appname, url): 37 | payload = {'name__exact': appname} 38 | req = requests.get(url + "app", params=payload) 39 | json_api = req.json() 40 | app_data = json_api.get('objects')[0] 41 | return app_data 42 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0002_auto_20171001_1057.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('app_manager', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='AppType', 15 | fields=[ 16 | ('id', models.AutoField(verbose_name='ID', 17 | serialize=False, 18 | auto_created=True, 19 | primary_key=True)), 20 | ('name', models.CharField(unique=True, max_length=200)), 21 | ], 22 | ), 23 | migrations.AddField( 24 | model_name='app', 25 | name='status', 26 | field=models.CharField(default='Alpha', max_length=100), 27 | ), 28 | migrations.AlterField( 29 | model_name='app', 30 | name='license', 31 | field=models.CharField(max_length=100, null=True, blank=True), 32 | ), 33 | migrations.AddField( 34 | model_name='app', 35 | name='category', 36 | field=models.ManyToManyField( 37 | related_name='apps', null=True, to='app_manager.AppType'), 38 | ), 39 | ] 40 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0003_auto_20171002_0445.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('app_manager', '0002_auto_20171001_1057'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='app', 15 | name='tags', 16 | field=models.ManyToManyField( 17 | to='app_manager.AppTag', 18 | null=True, 19 | blank=True), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0004_auto_20171002_0446.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | import taggit.managers 5 | from django.db import migrations 6 | 7 | 8 | class Migration(migrations.Migration): 9 | dependencies = [ 10 | ('taggit', '0002_auto_20150616_2121'), 11 | ('app_manager', '0003_auto_20171002_0445'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='app', 17 | name='tags', 18 | ), 19 | migrations.AddField( 20 | model_name='app', 21 | name='tags', 22 | field=taggit.managers.TaggableManager( 23 | to='taggit.Tag', 24 | through='taggit.TaggedItem', 25 | help_text='A comma-separated list of tags.', 26 | verbose_name='Tags'), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0005_delete_apptag.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('app_manager', '0004_auto_20171002_0446'), 10 | ] 11 | 12 | operations = [ 13 | migrations.DeleteModel( 14 | name='AppTag', 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0006_app_default_config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | #import jsonfield.fields 5 | from django.db import migrations 6 | from django.db.models import JSONField 7 | 8 | 9 | class Migration(migrations.Migration): 10 | dependencies = [ 11 | ('app_manager', '0005_delete_apptag'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='app', 17 | name='default_config', 18 | field=JSONField(default={}), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0007_auto_20180128_0116.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('app_manager', '0006_app_default_config'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='logo', 15 | name='site', 16 | ), 17 | migrations.AlterField( 18 | model_name='app', 19 | name='category', 20 | field=models.ManyToManyField(related_name='apps', 21 | to='app_manager.AppType'), 22 | ), 23 | migrations.DeleteModel( 24 | name='Logo', 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0008_appinstance_logo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations, models 5 | 6 | import cartoview.app_manager.models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | dependencies = [ 11 | ('app_manager', '0007_auto_20180128_0116'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='appinstance', 17 | name='logo', 18 | field=models.ImageField( 19 | null=True, 20 | upload_to=cartoview.app_manager.models.get_app_logo_path, 21 | blank=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0009_auto_20180920_1659.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('app_manager', '0008_appinstance_logo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appstore', 15 | name='server_type', 16 | field=models.CharField(default='Geoserver', max_length=256, 17 | choices=[('Exchange', 'Exchange'), ('Geoserver', 'Geoserver'), 18 | ('QGISServer', 'QGISServer')]), 19 | ), 20 | migrations.AlterField( 21 | model_name='app', 22 | name='license', 23 | field=models.CharField(max_length=200, null=True, blank=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0010_auto_20181118_1333.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.16 on 2018-11-18 13:33 3 | from __future__ import unicode_literals 4 | 5 | import django.db.models.manager 6 | from django.db import migrations 7 | 8 | 9 | class Migration(migrations.Migration): 10 | dependencies = [ 11 | ('app_manager', '0009_auto_20180920_1659'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterModelManagers( 16 | name='appinstance', 17 | managers=[ 18 | ('objects', django.db.models.manager.Manager()), 19 | ('base_objects', django.db.models.manager.Manager()), 20 | ], 21 | ), 22 | migrations.RenameField( 23 | model_name='appinstance', 24 | old_name='map', 25 | new_name='related_map', 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/0011_auto_20200623_1741.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.12 on 2020-06-23 15:41 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('app_manager', '0010_auto_20181118_1333'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelOptions( 15 | name='appinstance', 16 | options={'base_manager_name': 'objects'}, 17 | ), 18 | migrations.AlterModelManagers( 19 | name='appinstance', 20 | managers=[ 21 | ], 22 | ), 23 | migrations.AlterField( 24 | model_name='app', 25 | name='date_installed', 26 | field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date Installed'), 27 | ), 28 | migrations.AlterField( 29 | model_name='app', 30 | name='store', 31 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='app_manager.AppStore'), 32 | ), 33 | migrations.AlterField( 34 | model_name='appstore', 35 | name='url', 36 | field=models.URLField(verbose_name='App Store URL'), 37 | ), 38 | ] 39 | -------------------------------------------------------------------------------- /cartoview/app_manager/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/migrations/__init__.py -------------------------------------------------------------------------------- /cartoview/app_manager/resources.py: -------------------------------------------------------------------------------- 1 | from __future__ import (absolute_import, division, print_function, 2 | unicode_literals) 3 | 4 | from django.conf.urls import url 5 | from django.db import models 6 | from django.forms.models import modelform_factory 7 | from django.shortcuts import render 8 | from future import standard_library 9 | from tastypie.authorization import Authorization 10 | from tastypie.resources import ModelResource 11 | 12 | from .serializers import HTMLSerializer, MultipartFormSerializer 13 | 14 | standard_library.install_aliases() 15 | 16 | 17 | class BaseMeta(object): 18 | object_class = None 19 | always_return_data = True 20 | serializer = HTMLSerializer() 21 | authorization = Authorization() 22 | 23 | 24 | class BaseModelResource(ModelResource): 25 | class Meta(BaseMeta): 26 | pass 27 | 28 | def build_schema(self): 29 | base_schema = super(BaseModelResource, self).build_schema() 30 | for f in self._meta.object_class._meta.fields: 31 | if f.name in base_schema['fields'] and f.choices: 32 | base_schema['fields'][f.name].update({ 33 | 'choices': f.choices, 34 | }) 35 | return base_schema 36 | 37 | def get_form(self, obj=None): 38 | form = modelform_factory(self._meta.object_class) 39 | return form(instance=obj) 40 | 41 | def prepend_urls(self): 42 | return [ 43 | url(r"^(?P%s)/edit/(?P.*?)/$" % 44 | self._meta.resource_name, self.wrap_view('edit')), 45 | url(r"^(?P%s)/new/$" % self._meta.resource_name, 46 | self.wrap_view('new_item')) 47 | ] 48 | 49 | def new_item(self, request, **kwargs): 50 | self.method_check(request, allowed=['get']) 51 | form = self.get_form() 52 | return render(request, 'app_manager/rest_api/edit.html', { 53 | 'form': form, 54 | 'operation': 'add', 55 | 'resource_uri': self.get_resource_uri() 56 | }) 57 | 58 | def edit(self, request, pk, **kwargs): 59 | self.method_check(request, allowed=['get']) 60 | obj = self._meta.object_class.objects.get(id=pk) 61 | form = self.get_form(obj) 62 | return render(request, 'app_manager/rest_api/edit.html', { 63 | 'form': form, 64 | 'operation': 'edit', 65 | 'resource_uri': self.get_resource_uri() 66 | }) 67 | 68 | 69 | class FileUploadResource(BaseModelResource): 70 | class Meta(BaseModelResource.Meta): 71 | object_class = None 72 | serializer = MultipartFormSerializer() 73 | 74 | def obj_create(self, bundle, **kwargs): 75 | bundle = super(FileUploadResource, self).obj_create(bundle, **kwargs) 76 | for f in bundle.obj._meta.fields: 77 | if isinstance(f, models.FileField): 78 | file = bundle.request.FILES.get(f.name, None) 79 | if file: 80 | f.save_form_data(bundle.obj, file) 81 | return bundle 82 | 83 | def deserialize(self, request, data, format='application/json'): 84 | deserialized = self._meta.serializer.deserialize( 85 | data, 86 | request=request, 87 | format=request.META.get('CONTENT_TYPE', 'application/json')) 88 | return deserialized 89 | -------------------------------------------------------------------------------- /cartoview/app_manager/serializers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import json 6 | 7 | from django.template.loader import render_to_string 8 | from django.utils.encoding import force_text 9 | from future import standard_library 10 | from six import binary_type 11 | from tastypie.exceptions import UnsupportedFormat 12 | from tastypie.serializers import Serializer 13 | 14 | standard_library.install_aliases() 15 | 16 | 17 | class HTMLSerializer(Serializer): 18 | 19 | def to_html(self, data, options=None): 20 | options = options or {} 21 | data = self.to_simple(data, options) 22 | json_data = json.dumps( 23 | data, cls=json.JSONEncoder, indent=4, sort_keys=True) 24 | return render_to_string('app_manager/rest_api/base.html', 25 | {'json_data': json_data}) 26 | 27 | 28 | class MultipartFormSerializer(HTMLSerializer): 29 | 30 | def __init__(self, *args, **kwargs): 31 | self.content_types['file_upload'] = 'multipart/form-data' 32 | self.formats.append('file_upload') 33 | super(type(self), self).__init__(*args, **kwargs) 34 | 35 | def from_file_upload(self, data, options=None): 36 | request = options['request'] 37 | deserialized = {} 38 | for k in request.POST: 39 | deserialized[str(k)] = str(request.POST[k]) 40 | # for k in request.FILES: 41 | # deserialized[str(k)] = request.FILES[k] 42 | return deserialized 43 | 44 | # add request param to extract files 45 | def deserialize(self, content, request=None, format='application/json'): 46 | """ 47 | Given some data and a format, calls the correct method to deserialize 48 | the data and returns the result. 49 | """ 50 | desired_format = None 51 | 52 | format = format.split(';')[0] 53 | 54 | for short_format, long_format in list(self.content_types.items()): 55 | if format == long_format: 56 | if hasattr(self, "from_%s" % short_format): 57 | desired_format = short_format 58 | break 59 | 60 | if desired_format is None: 61 | raise UnsupportedFormat( 62 | "The format indicated '%s' had no available deserialization\ 63 | method. Please check your ``formats`` and ``content_types``\ 64 | on your Serializer." % 65 | format) 66 | 67 | if isinstance(content, 68 | binary_type) and desired_format != 'file_upload': 69 | content = force_text(content) 70 | 71 | deserialized = getattr(self, "from_%s" % desired_format)(content, { 72 | 'request': request 73 | }) 74 | return deserialized 75 | -------------------------------------------------------------------------------- /cartoview/app_manager/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import importlib 6 | import os 7 | import sys 8 | import threading 9 | 10 | from future import standard_library 11 | 12 | from cartoview.log_handler import get_logger 13 | 14 | logger = get_logger(__name__, with_formatter=True) 15 | lock = threading.Lock() 16 | standard_library.install_aliases() 17 | 18 | # BASE_DIR must be defined in project.settings 19 | 20 | CARTOVIEW_APPS = () 21 | APPS_SETTINGS = [] 22 | 23 | 24 | def load_apps(APPS_DIR): 25 | with lock: 26 | from cartoview.apps_handler.utils import create_apps_dir 27 | from cartoview.apps_handler.config import CartoviewApp 28 | global CARTOVIEW_APPS 29 | global APPS_SETTINGS 30 | create_apps_dir(APPS_DIR) 31 | if APPS_DIR not in sys.path: 32 | sys.path.append(APPS_DIR) 33 | logger.info("Loading Cartoview Apps.....") 34 | CartoviewApp.apps_dir = APPS_DIR 35 | CartoviewApp.load() 36 | for app in CartoviewApp.objects.values(): 37 | try: 38 | logger.info("Check if {} Healthy.\n".format(app.name)) 39 | # ensure that the folder is python module 40 | app_module = importlib.import_module(app.name) 41 | app_dir = os.path.dirname(app_module.__file__) 42 | app_settings_file = os.path.join(app_dir, 'settings.py') 43 | libs_dir = os.path.join(app_dir, 'libs') 44 | if os.path.exists(app_settings_file): 45 | # By doing this instead of import, app/settings.py can 46 | # refer to local variables from settings.py without 47 | # circular imports. 48 | app_settings_file = os.path.realpath(app_settings_file) 49 | APPS_SETTINGS += (app_settings_file,) 50 | if os.path.exists(libs_dir) and libs_dir not in sys.path: 51 | logger.info( 52 | "Append {} libs folder to the system path.\n".format( 53 | app.name)) 54 | sys.path.append(libs_dir) 55 | logger.info("add {} to django INSTALLED_APPS.\n".format(app.name)) 56 | if app.name not in CARTOVIEW_APPS: 57 | # app_config.name.__str__() because Django don't like 58 | # unicode_literals 59 | CARTOVIEW_APPS += (app.name.__str__(),) 60 | except Exception as e: 61 | print(e) 62 | logger.error(e) 63 | -------------------------------------------------------------------------------- /cartoview/app_manager/static/app_manager/css/appinstance_list.css: -------------------------------------------------------------------------------- 1 | .apps_filter { 2 | display: flex !important; 3 | flex: 1; 4 | align-items: center; 5 | } 6 | 7 | .text-nowrap { 8 | display: block; 9 | overflow: hidden; 10 | text-overflow: ellipsis; 11 | white-space: nowrap; 12 | } 13 | 14 | .app_filter_item { 15 | flex-grow: 1 16 | } -------------------------------------------------------------------------------- /cartoview/app_manager/static/app_manager/img/no-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/static/app_manager/img/no-image.jpg -------------------------------------------------------------------------------- /cartoview/app_manager/static/app_manager/js/resources.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var app = angular.module('cartoview.appManager.resources', ['cartoview.urlsHelper', 'cartoview.userInfo', "ngResource"]); 3 | app.config(function ($httpProvider, $resourceProvider) { 4 | // Don't strip trailing slashes from calculated URLs 5 | $resourceProvider.defaults.stripTrailingSlashes = false; 6 | $httpProvider.defaults.xsrfCookieName = 'csrftoken'; 7 | $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 8 | }); 9 | app.service("InstalledAppResource", function (urls, $resource) { 10 | var resourceUrl = urls.REST_URL + 'app/:appId/:action/'; 11 | return $resource(resourceUrl, {}, { 12 | 'query': { 13 | isArray: false 14 | }, 15 | suspend: { 16 | isArray: false, 17 | method: 'POST', 18 | params: { 19 | action: "suspend", 20 | appId: "@appId" 21 | } 22 | }, 23 | activate: { 24 | isArray: false, 25 | method: 'POST', 26 | params: { 27 | action: "activate", 28 | appId: "@appId" 29 | } 30 | }, 31 | reorder: { 32 | isArray: false, 33 | method: 'POST', 34 | params: { 35 | action: "reorder" 36 | } 37 | }, 38 | install: { 39 | isArray: false, 40 | method: 'POST', 41 | params: { 42 | action: "install" 43 | } 44 | }, 45 | uninstall: { 46 | isArray: false, 47 | method: 'POST', 48 | params: { 49 | action: "uninstall", 50 | appId: "@appId" 51 | } 52 | } 53 | }); 54 | }); 55 | 56 | app.service("AppStoreResource", function (urls, $resource) { 57 | return $resource(urls.REST_URL + 'appstore/:storeId', { 58 | storeId: '@id' 59 | }, { 60 | 'query': { 61 | isArray: false 62 | } 63 | }); 64 | }); 65 | 66 | app.service("AppStore", function (urls, $resource) { 67 | function objQueryStr(obj, prefix) { 68 | var str = [], 69 | p; 70 | for (p in obj) { 71 | if (obj.hasOwnProperty(p)) { 72 | var k = prefix ? prefix + "[" + p + "]" : p, 73 | v = obj[p]; 74 | str.push((v !== null && typeof v === "object") ? 75 | serialize(v, k) : 76 | encodeURIComponent(k) + "=:" + encodeURIComponent(k)); 77 | } 78 | } 79 | return str.join("&"); 80 | } 81 | 82 | function AppResource(store) { 83 | return $resource(store.url + 'app/:storeId?server_type__name=:server_type&cartoview_version=:version', { 84 | storeId: '@id', 85 | server_type: store.server_type, 86 | version: versionInfo.current_version 87 | }, { 88 | 'query': { 89 | isArray: false, 90 | method: 'JSONP', 91 | params: { 92 | callback: 'JSON_CALLBACK' 93 | } 94 | } 95 | }); 96 | } 97 | return { 98 | AppResource: AppResource 99 | } 100 | }); 101 | 102 | 103 | })(); -------------------------------------------------------------------------------- /cartoview/app_manager/static/app_manager/vendor/angular-img-fallback/angular.dcb-img-fallback.min.js: -------------------------------------------------------------------------------- 1 | "use strict";!function(){angular.module("dcbImgFallback",[]).directive("fallbackSrc",["imageService",function(A){return{restrict:"A",link:function(M,g,I){var i=I.fallbackSrc?A.setMissing(I.fallbackSrc):A.getMissing(),D=function(){var M=I.fallbackSrc?A.setMissing(I.fallbackSrc):A.getMissing();g[0].src!==M&&(g[0].src=M)};g[0].src===A.getLoading()&&(g[0].src=i),g.on("error",D),M.$on("$destroy",function(){g.off("error",D)})}}}]).directive("loadingSrc",["$interpolate","imageService",function(A,M){var g=function(g,I,i){I[0].src=i.loadingSrc?M.setLoading(i.loadingSrc):M.getLoading();var D=new Image;D.src=A(i.imgSrc)(g),D.onload=function(){D.onload=null,I[0].src!==D.src&&(I[0].src=D.src)}};return{restrict:"A",compile:function(A,M){return M.imgSrc=M.ngSrc,delete M.ngSrc,g}}}]).factory("imageService",function(){var A="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxkZWZzPjxyYWRpYWxHcmFkaWVudCBpZD0icmFkaWFsLWdyYWRpZW50IiBjeD0iNTAwIiBjeT0iNTAwIiByPSI1MDAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNkZmRmZGYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM5OTkiLz48L3JhZGlhbEdyYWRpZW50PjwvZGVmcz48cmVjdCBmaWxsPSJ1cmwoI3JhZGlhbC1ncmFkaWVudCkiIHdpZHRoPSIxMDAwIiBoZWlnaHQ9IjEwMDAiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNjAxIDQxNGwwIDBWNTg2bDAgMEgzOTlsMCAwVjQxNGwwIDBINjAxWm0wLTE0SDM5OUExNCAxNCAwIDAgMCAzODUgNDE0djE3M2ExNCAxNCAwIDAgMCAxNCAxNEg2MDFBMTQgMTQgMCAwIDAgNjE1IDU4NlY0MTRhMTQgMTQgMCAwIDAtMTQtMTRoMFpNNTc",M=A+"1IDUwMmE3NyA3NyAwIDAgMC0yNC01NCA3NiA3NiAwIDAgMC0yNS0xNiA3NSA3NSAwIDAgMC01NyAxQTc0IDc0IDAgMCAwIDQzMCA0NzQgNzMgNzMgMCAwIDAgNDMxIDUzMGE3MiA3MiAwIDAgMCAzOSAzOCA3MCA3MCAwIDAgMCA1NC0xIDY5IDY5IDAgMCAwIDM3LTM4IDY4IDY4IDAgMCAwIDQtMTZsMSAwYTEwIDEwIDAgMCAwIDEwLTEwYzAgMCAwLTEgMC0xaDBabS0xNSAyNmE2NyA2NyAwIDAgMS0zNyAzNSA2NiA2NiAwIDAgMS01MC0xIDY0IDY0IDAgMCAxLTM0LTM1QTYzIDYzIDAgMCAxIDQ0MCA0NzkgNjIgNjIgMCAwIDEgNDU0IDQ1OSA2MiA2MiAwIDAgMSA0NzQgNDQ2YTYxIDYxIDAgMCAxIDIzLTQgNjAgNjAgMCAwIDEgNDIgMTlBNTkgNTkgMCAwIDEgNTUyIDQ4MGE1OCA1OCAwIDAgMSA0IDIyaDBjMCAwIDAgMSAwIDFhMTAgMTAgMCAwIDAgOSAxMCA2NyA2NyAwIDAgMS01IDE1aDBaIi8+PC9zdmc+",g=A+"yIDQ1MGEyMiAyMiAwIDEgMS0yMi0yMkEyMiAyMiAwIDAgMSA1NzIgNDUwWk01ODYgNTcySDQxNFY1NDNsNTAtODYgNTggNzJoMTRsNTAtNDN2ODZaIi8+PC9zdmc+";return{getLoading:function(){return M},getMissing:function(){return g},setLoading:function(A){return M=A},setMissing:function(A){return g=A}}})}(); -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_instance/_resourcebase_snippet.html: -------------------------------------------------------------------------------- 1 | {% verbatim %} 2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 | 12 | 13 |
14 |
15 | {% endverbatim %} 16 | 18 | {% verbatim %} 19 |

{{ item.category__gn_description }}

20 |

{{ item.title }}

21 |

{{ item.abstract | limitTo: 300 }}{{ item.abstract.length > 300 ? '...' : 22 | ''}}

23 |

{{ !item.app ? item.app__title:item.app.title }} 24 |

25 | 49 |
50 |
51 |
52 |
53 |
54 | {% endverbatim %} 55 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_instance/_search_content.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 |
3 |
4 |
5 | 6 |
7 |
8 | {% block bulk_perms_button %} 9 |
10 | {% if request.user.is_authenticated %} 11 |
12 | 13 |
14 | {% endif %} 15 |
16 | {% endblock %} 17 | 18 |
19 | {% trans "Filters" %} 20 | {% trans "Clear" %} 21 |
22 | {% if SEARCH_FILTERS.TEXT_ENABLED %} 23 | {% include "search/_text_filter.html" %} 24 | {% endif %} 25 |
26 | {% include "search/_general_filters.html" %} 27 |
28 |
29 | 43 |
44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | Total: 52 | 53 |
54 | {% include "search/_sort_filters.html" %} 55 |
56 |
57 | {% include 'app_instance/_resourcebase_snippet.html' %} 58 | {% include 'search/_pagination.html' %} 59 |
60 |
61 | {% include "_bulk_permissions_form.html" %} 62 |
-------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/app_install_base.html: -------------------------------------------------------------------------------- 1 | {% extends "geonode_base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %} {{ block.super }} {% endblock %} 5 | 6 | {% block body_outer %} 7 | 10 |
11 | {% block body %}{% endblock body %} 12 | {% block sidebar %}{% endblock sidebar %} 13 |
14 | {% endblock body_outer %} -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/app_instance_list.html: -------------------------------------------------------------------------------- 1 | {% extends "app_manager/appinstance_base.html" %} 2 | {% load i18n %} 3 | {% load staticfiles %} 4 | 5 | {% block title %} {% trans "Explore Apps" %} - {{ block.super }} {% endblock %} 6 | {% block head %} 7 | {{ block.super }} 8 | 9 | {% endblock %} 10 | {% block body_class %}appinstances appinstances-list explore{% endblock %} 11 | 12 | {% block body %} 13 | 34 | {% with include_type_filter='true' %} 35 | {% with facet_type='appinstances' %} 36 | {% with header='App Type' %} 37 | {% with filter='app__title' %} 38 | {% include "app_instance/_search_content.html" %} 39 | {% endwith %} 40 | {% endwith %} 41 | {% endwith %} 42 | {% endwith %} 43 | {% include "_bulk_permissions_form.html" %} 44 | {% endblock %} 45 | 46 | {% block extra_script %} 47 | {{block.super}} 48 | {% if GEONODE_SECURITY_ENABLED %} 49 | {% include "_permissions_form_js.html" %} 50 | {% endif %} 51 | 61 | {% with include_spatial='true' %} 62 | {% include 'app_instance/search_scripts.html' %} 63 | {% endwith %} 64 | 65 | 66 | 67 | {% endblock extra_script %} 68 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/appinstance_base.html: -------------------------------------------------------------------------------- 1 | {% extends "geonode_base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %} {{ block.super }} {% endblock %} 5 | 6 | {% block body_class %}appinstances{% endblock %} 7 | 8 | {% block body_outer %} 9 | 12 | {% block body %}{% endblock body %} 13 | {% block sidebar %}{% endblock sidebar %} 14 | {% endblock body_outer %} 15 | {% block extra_script %} 16 | 17 | {{block.super}} 18 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/edit_launcher_modal.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap_tags staticfiles%} 2 | {% load i18n %} 3 | 4 | 5 | 6 | 53 | 54 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/install_app_panel.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap_tags staticfiles%} 2 | {% load i18n %} 3 | 4 | 22 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/install_result.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap_tags staticfiles%} 2 | {% load i18n %} 3 | 4 |
-------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/rest_api/base.html: -------------------------------------------------------------------------------- 1 | 2 | {% block title %}REST API{% endblock %} 3 | {% block styles %} 4 | {% endblock styles %} 5 | {% block content %} 6 | {{ html }} 7 | {% if json_data %} 8 |
{{ json_data }}
9 | {% endif %} 10 | {% block content_inner %}{% endblock content_inner %} 11 | {% endblock content %} 12 | {% block scripts %} 13 | 14 | {% endblock scripts %} -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/rest_api/edit.html: -------------------------------------------------------------------------------- 1 | {% extends "app_manager/rest_api/base.html" %} 2 | {% load bootstrap %} 3 | {% block content_inner %} 4 | {% if form %} 5 |
6 | {{ form|bootstrap_horizontal }} 7 |
8 |
9 | 10 |
11 |
12 |
13 | {% endif %} 14 | 15 | {% endblock content_inner %} 16 | {% block scripts %} 17 | 20 | {% endblock scripts %} 21 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/rest_api/home.html: -------------------------------------------------------------------------------- 1 | {% extends "app_manager/rest_api/base.html" %} 2 | {% block content_inner %} 3 |
    4 | {% for name in apis %} 5 |
  • {{ name }}
  • 6 | {% endfor %} 7 |
8 | {% endblock content_inner %} 9 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/app_manager/rest_api/list.html: -------------------------------------------------------------------------------- 1 | {% extends "app_manager/rest_api/base.html" %} 2 | {% block content_inner %} 3 |
    4 | {% for name in apis %} 5 |
  • {{ name }}
  • 6 | {% endfor %} 7 |
8 | {% endblock content_inner %} 9 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/bootstrapform/field.html: -------------------------------------------------------------------------------- 1 | {% load bootstrap %} 2 | 3 |
4 | {% if field|is_checkbox %} 5 |
6 |
7 | {% if field.auto_id %} 8 | 11 | {% endif %} 12 | {% for error in field.errors %} 13 | {{ error }} 14 | {% endfor %} 15 | 16 | {% if field.help_text %} 17 |

18 | {{ field.help_text|safe }} 19 |

20 | {% endif %} 21 |
22 |
23 | {% elif field|is_radio %} 24 | {% if field.auto_id %} 25 | 26 | {% endif %} 27 |
28 | {% for choice in field %} 29 |
30 | 34 |
35 | {% endfor %} 36 | 37 | {% for error in field.errors %} 38 | {{ error }} 39 | {% endfor %} 40 | 41 | {% if field.help_text %} 42 |

43 | {{ field.help_text|safe }} 44 |

45 | {% endif %} 46 |
47 | {% else %} 48 | {% if field.auto_id %} 49 | 50 | {% endif %} 51 | 52 |
53 | {{ field }} 54 | 55 | {% for error in field.errors %} 56 | {{ error }} 57 | {% endfor %} 58 | 59 | {% if field.help_text %} 60 |

61 | {{ field.help_text|safe }} 62 |

63 | {% endif %} 64 |
65 | {% endif %} 66 |
67 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/bootstrapform/form.html: -------------------------------------------------------------------------------- 1 | {% if form.non_field_errors %} 2 |
3 | × 4 | {% for non_field_error in form.non_field_errors %} 5 | {{ non_field_error }} 6 | {% endfor %} 7 |
8 | {% endif %} 9 | 10 | 11 | 12 | {% if form.fieldsets %} 13 | {% for fieldset in form.fieldsets %} 14 |
15 | {% if fieldset.legend %} 16 | {{ fieldset.legend }} 17 | {% endif %} 18 | {% if fieldset.description %} 19 |

{{ fieldset.description }}

20 | {% endif %} 21 | {% for field in fieldset %} 22 | {% if field.is_hidden %} 23 | {{ field }} 24 | {% else %} 25 | {% include 'bootstrapform/field.html' %} 26 | {% endif %} 27 | {% endfor %} 28 |
29 | {% endfor %} 30 | {% else %} 31 | {% for field in form.hidden_fields %} 32 | {{ field }} 33 | {% endfor %} 34 | {% for field in form.visible_fields %} 35 | {% include 'bootstrapform/field.html' %} 36 | {% endfor %} 37 | 38 | {% endif %} 39 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/bootstrapform/formset.html: -------------------------------------------------------------------------------- 1 | {{ formset.management_form }} 2 | 3 | {% for form in formset %} 4 | 5 | {% include "bootstrapform/form.html" with form=form %} 6 | 7 | {% endfor %} 8 | -------------------------------------------------------------------------------- /cartoview/app_manager/templates/search/indexes/app_manager/appinstance_text.txt: -------------------------------------------------------------------------------- 1 | {{ object.content }} 2 | {{ object.title }} 3 | {{ object.abstract }} 4 | {{ object.purpose }} 5 | {{ object.name }} 6 | {{ object.supplemental_information }} 7 | {{ object.keyword_list }} -------------------------------------------------------------------------------- /cartoview/app_manager/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/app_manager/tests/__init__.py -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_commands.py: -------------------------------------------------------------------------------- 1 | from django.core.management import call_command 2 | from django.test import TestCase 3 | from six import StringIO 4 | 5 | from cartoview.app_manager.models import (App, AppStore) 6 | 7 | 8 | class UpdateCurrentAppsTest(TestCase): 9 | fixtures = ['app_stores.json', ] 10 | 11 | def test_command_output(self): 12 | out = StringIO() 13 | out1 = StringIO() 14 | call_command("load_current_apps", stdout=out1) 15 | call_command('update_current_apps', stdout=out) 16 | self.assertIn('', out.getvalue()) 17 | viewer = App.objects.get(name="cartoview_basic_viewer") 18 | viewer.store = AppStore.objects.get(is_default=True) 19 | viewer.save() 20 | call_command('update_current_apps', stdout=out) 21 | self.assertIn('', out.getvalue()) 22 | -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_decorators.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import AnonymousUser 2 | from django.core.exceptions import PermissionDenied 3 | from django.core.management import call_command 4 | from django.http import HttpRequest 5 | from django.test import TestCase 6 | from geonode.people.models import Profile 7 | from mock import Mock 8 | 9 | from cartoview.app_manager.decorators import can_view_app_instance 10 | from cartoview.app_manager.models import App, AppInstance 11 | 12 | 13 | class DecoratorsTest(TestCase): 14 | fixtures = ['sample_admin.json', ] 15 | 16 | def setUp(self): 17 | call_command("load_current_apps") 18 | self.app = App.objects.get(name="cartoview_basic_viewer") 19 | self.app_instance = AppInstance() 20 | self.app_instance.app = self.app 21 | self.user = Profile.objects.get(username="admin") 22 | self.app_instance.owner = self.user 23 | self.app_instance.title = "fake_viewer" 24 | self.app_instance.config = {} 25 | self.app_instance.abstract = "fake_viewer_abstract" 26 | self.app_instance.map_id = None 27 | self.app_instance.save() 28 | 29 | def test_can_view_app(self): 30 | func_allowed = Mock() 31 | func_allowed.__name__ = "fake_app_view" 32 | req = HttpRequest() 33 | req.user = self.user 34 | decorated = can_view_app_instance(func_allowed) 35 | decorated(req, instance_id=self.app_instance.id) 36 | self.assertTrue(func_allowed.called) 37 | func_anonymous_allowed = Mock() 38 | func_anonymous_allowed.__name__ = "fake_app_view" 39 | req.user = AnonymousUser() 40 | decorated = can_view_app_instance(func_anonymous_allowed) 41 | decorated(req, instance_id=self.app_instance.id) 42 | self.assertTrue(func_anonymous_allowed.called) 43 | func_not_allowed = Mock() 44 | func_not_allowed.__name__ = "fake_app_view" 45 | decorated = can_view_app_instance(func_not_allowed) 46 | owner_permissions = [ 47 | 'view_resourcebase', 48 | 'download_resourcebase', 49 | 'change_resourcebase_metadata', 50 | 'change_resourcebase', 51 | 'delete_resourcebase', 52 | 'change_resourcebase_permissions', 53 | 'publish_resourcebase', 54 | ] 55 | permessions = { 56 | 'users': { 57 | '{}'.format(self.user): owner_permissions, 58 | } 59 | } 60 | self.app_instance.set_permissions(permessions) 61 | try: 62 | decorated(req, instance_id=self.app_instance.id) 63 | except PermissionDenied: 64 | pass 65 | self.assertFalse(func_not_allowed.called) 66 | -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_helpers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | from django.conf import settings 5 | from django.test import TestCase 6 | 7 | from cartoview.app_manager.helpers import ( 8 | get_path_permission, get_perm, make_writeable_recursive, create_direcotry) 9 | 10 | 11 | class HelpersTest(TestCase): 12 | def test_helpers(self): 13 | apps_dir_perm = get_perm(settings.APPS_DIR) 14 | self.assertEqual(apps_dir_perm, 511) 15 | apps_dir_perm = get_path_permission(settings.APPS_DIR) 16 | self.assertEqual(apps_dir_perm, ('0o777', '0o777')) 17 | try: 18 | make_writeable_recursive(settings.APPS_DIR) 19 | except OSError: 20 | self.fail("Failed to change permission") 21 | test_dir = os.path.join(settings.CARTOVIEW_DIR, 'test_dir') 22 | create_direcotry(test_dir) 23 | self.assertTrue(os.path.exists(test_dir)) 24 | shutil.rmtree(test_dir) 25 | -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_installer.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME 4 | from django.urls import reverse 5 | from django.test import TestCase 6 | from geonode.people.models import Profile 7 | 8 | from cartoview.app_manager.installer import AppInstaller 9 | from cartoview.app_manager.models import App 10 | 11 | lock = threading.RLock() 12 | 13 | 14 | class AppInstallerTest(TestCase): 15 | fixtures = ['sample_admin.json', 'app_stores.json'] 16 | 17 | def setUp(self): 18 | self.client.login(username="admin", password="admin") 19 | 20 | def test_app_installer(self): 21 | with lock: 22 | user = Profile.objects.filter(is_superuser=True).first() 23 | store_id = 1 24 | app_name = "cartoview_test_app" 25 | app_version = "0.1" 26 | app_installer = AppInstaller(app_name, store_id, app_version, user) 27 | installed_apps = app_installer.install() 28 | self.assertEqual(len(installed_apps), 1) 29 | apps_admin_url = reverse( 30 | "admin:%s_%s_changelist" % (App._meta.app_label, 31 | App._meta.model_name)) 32 | data = { 33 | 'action': 'suspend_selected', 34 | ACTION_CHECKBOX_NAME: 35 | [str(app.pk) for app in installed_apps] 36 | } 37 | resp = self.client.post(apps_admin_url, data) 38 | self.assertNotEqual(resp.status_code, 500) 39 | data = { 40 | 'action': 'activate_selected', 41 | ACTION_CHECKBOX_NAME: 42 | [str(app.pk) for app in installed_apps] 43 | } 44 | resp = self.client.post(apps_admin_url, data) 45 | self.assertNotEqual(resp.status_code, 500) 46 | uninstalled = app_installer.uninstall() 47 | self.assertEqual(uninstalled, True) 48 | 49 | def tearDown(self): 50 | pass 51 | -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_req_installer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import tempfile 4 | 5 | from django.test import TestCase 6 | 7 | from cartoview.apps_handler.req_installer import ReqFileException, ReqInstaller 8 | 9 | 10 | class ReqInstallerTest(TestCase): 11 | def setUp(self): 12 | self.tmp_dir = tempfile.mkdtemp() 13 | self.req_file = os.path.join(self.tmp_dir, 'req.txt') 14 | self.target_dir = os.path.join(self.tmp_dir, 'libs') 15 | 16 | def test_req_installer(self): 17 | with open(self.req_file, "w") as f: 18 | f.write("pipenv") 19 | req_installer = ReqInstaller(self.tmp_dir, self.target_dir) 20 | req_installer.install_all() 21 | self.assertTrue(len(os.listdir(self.target_dir)) > 0) 22 | self.assertRaises(ReqFileException, ReqInstaller, "/dummy_path") 23 | 24 | def tearDown(self): 25 | shutil.rmtree(self.tmp_dir) 26 | -------------------------------------------------------------------------------- /cartoview/app_manager/tests/test_views.py: -------------------------------------------------------------------------------- 1 | from django.core.management import call_command 2 | from django.urls import reverse 3 | from django.test import RequestFactory, TestCase 4 | from geonode.people.models import Profile 5 | from geonode.tests.base import GeoNodeLiveTestSupport 6 | 7 | 8 | class CartoviewAppsViewTest(TestCase): 9 | def setUp(self): 10 | call_command("load_current_apps") 11 | 12 | def test_view_url_exists_at_desired_location(self): 13 | resp = self.client.get('/cv_apps/') 14 | self.assertEqual(resp.status_code, 200) 15 | 16 | def test_view_url_accessible_by_name(self): 17 | resp = self.client.get(reverse('app_manager_base_url')) 18 | self.assertEqual(resp.status_code, 200) 19 | 20 | def test_view_uses_correct_template(self): 21 | resp = self.client.get(reverse('app_manager_base_url')) 22 | self.assertEqual(resp.status_code, 200) 23 | self.assertTemplateUsed(resp, 'app_manager/apps.html') 24 | self.assertTrue("apps" in resp.context) 25 | 26 | 27 | class CartoviewManageAppsViewTest(GeoNodeLiveTestSupport): 28 | # fixtures = ['sample_admin.json'] 29 | 30 | def setUp(self): 31 | call_command("load_current_apps") 32 | self.factory = RequestFactory() 33 | self.username = "staff_user" 34 | self.password = "staff_user" 35 | self.email = "staff_user@staff_user.com" 36 | self.user = Profile.objects.create_superuser( 37 | self.username, self.email, self.password) 38 | self.client.login(username=self.username, password=self.password) 39 | 40 | def test_view_url_exists_at_desired_location(self): 41 | resp = self.client.get("/cv_apps/manage/") 42 | self.assertEqual(resp.status_code, 200) 43 | 44 | def test_view_url_accessible_by_name(self): 45 | resp = self.client.get(reverse("manage_apps")) 46 | self.assertEqual(resp.status_code, 200) 47 | 48 | def test_view_uses_correct_template(self): 49 | resp = self.client.get(reverse('manage_apps')) 50 | self.assertEqual(resp.status_code, 200) 51 | self.assertTemplateUsed(resp, 'app_manager/manage.html') 52 | self.assertTrue("apps" in resp.context) 53 | self.assertTrue("site_apps" in resp.context) 54 | self.assertTrue("version_info" in resp.context) 55 | -------------------------------------------------------------------------------- /cartoview/app_manager/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import importlib 6 | 7 | from django.conf.urls import include, url 8 | from django.views.generic import TemplateView 9 | from future import standard_library 10 | 11 | from cartoview.app_manager.rest import (AppInstanceResource, AppResource, 12 | AppStoreResource, 13 | GeonodeMapLayerResource, TagResource) 14 | from cartoview.apps_handler.config import CartoviewApp 15 | from . import views as app_manager_views 16 | from .api import rest_api 17 | 18 | standard_library.install_aliases() 19 | rest_api.register(AppResource()) 20 | rest_api.register(AppStoreResource()) 21 | rest_api.register(AppInstanceResource()) 22 | rest_api.register(GeonodeMapLayerResource()) 23 | rest_api.register(TagResource()) 24 | 25 | urlpatterns = [ 26 | url(r'^$', app_manager_views.index, name='app_manager_base_url'), 27 | url(r'^manage/$', app_manager_views.manage_apps, name='manage_apps'), 28 | url(r'^install/(?P\d+)/(?P.*)/(?P.*)/$', 29 | app_manager_views.install_app, 30 | name='install_app'), 31 | url(r'^uninstall/(?P\d+)/(?P.*)/$', 32 | app_manager_views.uninstall_app, 33 | name='cartoview_uninstall_app_url'), 34 | url(r'^appinstances/$', 35 | TemplateView.as_view( 36 | template_name='app_manager/app_instance_list.html'), 37 | name='appinstance_browse'), 38 | url(r'^appinstance/(?P\d+)/?$', 39 | app_manager_views.appinstance_detail, 40 | name='appinstance_detail'), 41 | url(r'^appinstance/(?P\d+)/metadata$', 42 | app_manager_views.appinstance_metadata, 43 | name='appinstance_metadata'), 44 | url(r'^moveup/(?P\d+)/$', 45 | app_manager_views.move_up, 46 | name='move_up'), 47 | url(r'^movedown/(?P\d+)/$', 48 | app_manager_views.move_down, 49 | name='move_down'), 50 | url(r'^save_app_orders/$', 51 | app_manager_views.save_app_orders, 52 | name='save_app_orders'), 53 | url(r'^(?P\d+)/remove$', 54 | app_manager_views.appinstance_remove, 55 | name="appinstance_remove"), 56 | url(r'^rest/', include(rest_api.urls)), 57 | ] 58 | 59 | 60 | def import_app_rest(app_name): 61 | try: 62 | # print 'define %s rest api ....' % app_name 63 | # module_ = importlib.import_module('%s.rest' % app_name) 64 | importlib.import_module('%s.rest' % app_name) 65 | except ImportError: 66 | pass 67 | 68 | 69 | def app_url(app_name): 70 | app = str(app_name) 71 | return url( 72 | r'^' + app + '/', include('%s.urls' % app), name=app + '_base_url') 73 | 74 | 75 | def load_apps_urls(): 76 | app_names = CartoviewApp.objects.get_active_apps().keys() 77 | for app_name in app_names: 78 | import_app_rest(app_name) 79 | urlpatterns.append(app_url(app_name)) 80 | 81 | 82 | load_apps_urls() 83 | -------------------------------------------------------------------------------- /cartoview/app_manager/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import abc 6 | 7 | from django.utils.translation import ugettext as _ 8 | from future import standard_library 9 | from future.utils import with_metaclass 10 | from geonode.utils import resolve_object 11 | 12 | from cartoview.app_manager.models import AppInstance 13 | 14 | standard_library.install_aliases() 15 | 16 | _PERMISSION_MSG_GENERIC = _("You do not have permissions for this Instance.") 17 | 18 | 19 | def resolve_appinstance(request, 20 | appinstanceid, 21 | permission='base.change_resourcebase', 22 | msg=_PERMISSION_MSG_GENERIC, 23 | **kwargs): 24 | """ 25 | Resolve the document by the provided primary key 26 | and check the optional permission. 27 | """ 28 | return resolve_object( 29 | request, 30 | AppInstance, {'pk': appinstanceid}, 31 | permission=permission, 32 | permission_msg=msg, 33 | **kwargs) 34 | 35 | 36 | class Thumbnail(with_metaclass(abc.ABCMeta, object)): 37 | @abc.abstractmethod 38 | def create_thumbnail(self): 39 | """Implement your thumbnail method""" 40 | pass 41 | 42 | 43 | class AppsThumbnail(Thumbnail): 44 | def __init__(self, instance): 45 | self.instance = instance 46 | 47 | def create_thumbnail(self): 48 | instance = self.instance 49 | if not isinstance(instance, AppInstance): 50 | return 51 | instance_map = getattr(instance, 'related_map', instance.map) 52 | if instance_map: 53 | instance.thumbnail_url = instance_map.get_thumbnail_url() 54 | instance.save() 55 | 56 | 57 | def populate_apps(): 58 | from django.apps import apps 59 | from django.conf import settings 60 | apps.populate(settings.INSTALLED_APPS) 61 | -------------------------------------------------------------------------------- /cartoview/apps_handler/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /cartoview/apps_handler/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | from django.apps import AppConfig 6 | from future import standard_library 7 | 8 | from cartoview.apps_handler.apps_operations import pending_handler 9 | from cartoview.log_handler import get_logger 10 | 11 | standard_library.install_aliases() 12 | 13 | logger = get_logger(__name__) 14 | 15 | 16 | class AppsHandlerConfig(AppConfig): 17 | name = 'cartoview.apps_handler' 18 | verbose_name = "Apps Handler" 19 | 20 | def ready(self): 21 | pending_handler() 22 | -------------------------------------------------------------------------------- /cartoview/apps_handler/apps_operations.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import json 6 | import os 7 | 8 | from django.conf import settings 9 | from django.core.management import call_command 10 | from django.core.management.base import CommandError 11 | from future import standard_library 12 | 13 | from cartoview.log_handler import get_logger 14 | 15 | standard_library.install_aliases() 16 | logger = get_logger(__name__) 17 | 18 | 19 | class AppsHandler(object): 20 | def __init__(self): 21 | pass 22 | 23 | def delete_application_on_fail(self, appname): 24 | from cartoview.app_manager.installer import AppInstaller 25 | AppInstaller(appname).uninstall(restart=True) 26 | 27 | def get_pending_apps(self, app_name): 28 | app = {"name": app_name, "makemigrations": False, "migrate": True} 29 | DEFAULT_APPS = [ 30 | app, 31 | ] 32 | apps = DEFAULT_APPS 33 | apps_dir = getattr(settings, 'APPS_DIR', None) 34 | _app_dir = os.path.join(apps_dir, app_name) 35 | app_data_file = os.path.join(_app_dir, 'installer.json') 36 | if os.path.exists(app_data_file) and os.access(app_data_file, os.R_OK): 37 | with open(app_data_file, 'r') as f: 38 | app_data = json.load(f) 39 | apps = app_data.get('apps', DEFAULT_APPS) 40 | return apps 41 | 42 | def makemigrations(self, app_name): 43 | call_command("makemigrations", app_name, interactive=False) 44 | 45 | def migrate(self, app_name): 46 | try: 47 | call_command("migrate", app_name, interactive=False) 48 | except CommandError as e: 49 | logger.error(e) 50 | if e.args[0] and "does not have migrations" not in e.args[0]: 51 | self.delete_application_on_fail(app_name) 52 | 53 | def collectstatic(self): 54 | if not settings.DEBUG: 55 | call_command( 56 | "collectstatic", 57 | interactive=False, 58 | ignore=['node_modules', '.git']) 59 | 60 | def execute_pending(self): 61 | from cartoview.apps_handler.config import CartoviewApp 62 | CartoviewApp.load() 63 | pending_apps = CartoviewApp.objects.get_pending_apps().values() 64 | for app in pending_apps: 65 | _pending_apps = self.get_pending_apps(app.name) 66 | if _pending_apps: 67 | for _app in _pending_apps: 68 | _app_name = _app.get('name', None) 69 | _make_migrations = _app.get('makemigrations', False) 70 | _migrate = _app.get('migrate', False) 71 | if _app_name: 72 | if _make_migrations: 73 | self.makemigrations(_app_name) 74 | if _migrate: 75 | self.migrate(_app_name) 76 | else: 77 | self.migrate(app) 78 | self.collectstatic() 79 | carto_app = CartoviewApp.objects.get(app.name) 80 | carto_app.pending = False 81 | carto_app.commit() 82 | CartoviewApp.save() 83 | 84 | def __call__(self): 85 | apps_dir = getattr(settings, 'APPS_DIR', None) 86 | if apps_dir and os.path.exists(apps_dir): 87 | self.execute_pending() 88 | 89 | 90 | pending_handler = AppsHandler() 91 | -------------------------------------------------------------------------------- /cartoview/apps_handler/db_parser.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | from urllib.parse import urlencode 6 | 7 | import dj_database_url 8 | from django.conf import settings 9 | from future import standard_library 10 | 11 | standard_library.install_aliases() 12 | 13 | 14 | class DBParseException(Exception): 15 | pass 16 | 17 | 18 | def get_db_url(db_key): 19 | databases = getattr(settings, 'DATABASES', {}) 20 | _schemes = {v: k for k, v in dj_database_url.SCHEMES.items()} 21 | if db_key in databases: 22 | db = databases.get(db_key) 23 | engine = db.get('ENGINE', None) 24 | db_url = '' 25 | name = db.get('NAME', None) 26 | host = db.get('HOST', None) 27 | port = db.get('PORT', None) 28 | user = db.get('USER', None) 29 | password = db.get('PASSWORD', None) 30 | options = db.get('OPTIONS', None) 31 | if db and engine: 32 | if engine != dj_database_url.SCHEMES[ 33 | 'sqlite'] and engine != dj_database_url.SCHEMES[ 34 | 'spatialite']: 35 | db_url += "{}://".format(_schemes[engine]) 36 | if user and password: 37 | db_url += "{}:{}".format(user, password) 38 | if host: 39 | db_url += "@{}".format(host) 40 | if port: 41 | db_url += ":{}".format(port) 42 | if name: 43 | db_url += "/{}".format(name) 44 | if options: 45 | db_url += "?{}".format(urlencode(options)) 46 | else: 47 | db_url += "{}://".format(_schemes[engine]) 48 | db_url += name 49 | return db_url 50 | raise DBParseException("Invalid database key") 51 | -------------------------------------------------------------------------------- /cartoview/apps_handler/req_installer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import os 6 | import re 7 | 8 | from future import standard_library 9 | 10 | standard_library.install_aliases() 11 | req_file_regex = re.compile(r'^(req|requirement)s?\.txt') 12 | 13 | 14 | class ReqFileException(Exception): 15 | message = "requirement file doesn't exists!" 16 | 17 | 18 | class ReqFilePermissionException(Exception): 19 | message = "can not read requirement file!" 20 | 21 | 22 | class ReqInstaller(object): 23 | def __init__(self, app_dir, target=None): 24 | self._app_dir = app_dir 25 | self.req_file = None 26 | self.target = target 27 | self.find_req_file() 28 | 29 | def find_req_file(self): 30 | if not os.path.exists(self._app_dir): 31 | raise ReqFileException() 32 | for root, dirs, files in os.walk(self._app_dir): 33 | for name in files: 34 | if req_file_regex.match(name): 35 | self.req_file = os.path.join(root, name) 36 | break 37 | else: 38 | continue 39 | break 40 | if not self.req_file or not os.path.exists(self.req_file): 41 | raise ReqFileException() 42 | if not os.access(self.req_file, os.R_OK): 43 | raise ReqFilePermissionException() 44 | 45 | def install_all(self, *args, **kwargs): 46 | from subprocess import call 47 | command = ["pip", "install", "-r", self.req_file] 48 | if self.target: 49 | command.extend(["-t", self.target]) 50 | call(command) 51 | -------------------------------------------------------------------------------- /cartoview/apps_handler/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/apps_handler/tests/__init__.py -------------------------------------------------------------------------------- /cartoview/apps_handler/tests/test_db_parser.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django.test import TestCase 4 | from django.test import override_settings 5 | 6 | from ..db_parser import get_db_url 7 | 8 | 9 | class DBParserTest(TestCase): 10 | def test_get_db_url(self): 11 | from django.conf import settings 12 | base_dir = getattr(settings, 'BASE_DIR', '') 13 | sqlite_path = os.path.join(base_dir, 'test.db') 14 | databases = { 15 | 'postgis': { 16 | 'ENGINE': 'django.contrib.gis.db.backends.postgis', 17 | 'NAME': 'cartoview', 18 | 'USER': 'docker', 19 | 'PASSWORD': 'docker', 20 | 'HOST': 'localhost', 21 | 'PORT': '5432', 22 | }, 23 | 'sqlite': { 24 | 'ENGINE': 'django.db.backends.sqlite3', 25 | 'NAME': sqlite_path 26 | } 27 | } 28 | with override_settings(DATABASES=databases): 29 | self.assertEqual( 30 | get_db_url('sqlite'), 'sqlite://{}'.format(sqlite_path)) 31 | self.assertEqual( 32 | get_db_url('postgis'), 33 | 'postgis://docker:docker@localhost:5432/cartoview') 34 | -------------------------------------------------------------------------------- /cartoview/apps_handler/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import (absolute_import, division, print_function, 3 | unicode_literals) 4 | 5 | import os 6 | 7 | from django.conf import settings 8 | from future import standard_library 9 | 10 | from cartoview.app_manager.helpers import (change_path_permission, 11 | create_direcotry) 12 | 13 | standard_library.install_aliases() 14 | 15 | 16 | def create_apps_dir(apps_dir): 17 | if not apps_dir: 18 | apps_dir = getattr(settings, 'APPS_DIR', None) 19 | if not apps_dir: 20 | project_dir = getattr(settings, 'BASE_DIR', settings.PROJECT_DIR) 21 | apps_dir = os.path.abspath(os.path.join( 22 | os.path.dirname(project_dir), "apps")) 23 | if not os.path.exists(apps_dir): 24 | create_direcotry(apps_dir) 25 | if not os.access(apps_dir, os.W_OK): 26 | change_path_permission(apps_dir) 27 | -------------------------------------------------------------------------------- /cartoview/cartoview_api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/cartoview_api/__init__.py -------------------------------------------------------------------------------- /cartoview/cartoview_api/admin.py: -------------------------------------------------------------------------------- 1 | # from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /cartoview/cartoview_api/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class CartoviewAPIConfig(AppConfig): 7 | name = 'cartoview.cartoview_api' 8 | verbose_name = "Cartoview API" 9 | -------------------------------------------------------------------------------- /cartoview/cartoview_api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/cartoview_api/migrations/__init__.py -------------------------------------------------------------------------------- /cartoview/cartoview_api/models.py: -------------------------------------------------------------------------------- 1 | # from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /cartoview/cartoview_api/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/cartoview_api/tests/__init__.py -------------------------------------------------------------------------------- /cartoview/cartoview_api/tests/test_rest.py: -------------------------------------------------------------------------------- 1 | from django.urls import reverse 2 | from django.test import TestCase 3 | from geonode.urls import api 4 | from tastypie.test import ResourceTestCaseMixin 5 | 6 | from cartoview.cartoview_api.rest import ExtendedResourceBaseResource 7 | 8 | 9 | class ExtendedResourceBaseResourceTest(ResourceTestCaseMixin, TestCase): 10 | fixtures = ['sample_admin.json'] 11 | 12 | def setUp(self): 13 | super(ExtendedResourceBaseResourceTest, self).setUp() 14 | self.username = 'admin' 15 | self.password = 'admin' 16 | 17 | def get_credentials(self): 18 | return self.create_basic( 19 | username=self.username, 20 | password=self.password) 21 | 22 | def test_get_list(self): 23 | target_url = reverse( 24 | "api_dispatch_list", 25 | kwargs={"resource_name": 26 | ExtendedResourceBaseResource.Meta.resource_name, 27 | "api_name": api.api_name}) 28 | self.assertHttpOK(self.api_client.get( 29 | target_url, format='json')) 30 | -------------------------------------------------------------------------------- /cartoview/cartoview_api/tests/test_views.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.test import TestCase 3 | from faker import Faker 4 | 5 | from cartoview.cartoview_api.views import ( 6 | get_geoserver_credintials, convert_infinty) 7 | 8 | 9 | class CartoviewApiViewsTest(TestCase): 10 | def setUp(self): 11 | self.faker = Faker() 12 | 13 | def test_get_geoserver_credintials(self): 14 | gs_user, gs_password, gs_url = get_geoserver_credintials() 15 | self.assertEqual(gs_user, settings.OGC_SERVER_DEFAULT_USER) 16 | self.assertEqual(gs_password, settings.OGC_SERVER_DEFAULT_PASSWORD) 17 | self.assertEqual(gs_url, settings.GEOSERVER_LOCATION) 18 | 19 | def test_convert_infinty(self): 20 | self.assertIsNone(convert_infinty(float('inf'))) 21 | self.assertIsNotNone(convert_infinty(self.faker.random.random())) 22 | self.assertIsNotNone(convert_infinty(self.faker.name())) 23 | self.assertIsNotNone(convert_infinty(self.faker.text())) 24 | -------------------------------------------------------------------------------- /cartoview/celery.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | import os 5 | 6 | from celery import Celery 7 | 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cartoview.settings') 9 | 10 | app = Celery('cartoview') 11 | 12 | # Using a string here means the worker will not have to 13 | # pickle the object when using Windows. 14 | app.config_from_object('django.conf:settings', namespace="CELERY") 15 | app.autodiscover_tasks() 16 | -------------------------------------------------------------------------------- /cartoview/fixtures/default_oauth_apps_docker.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "oauth2_provider.application", 4 | "pk": 1001, 5 | "fields": { 6 | "skip_authorization": true, 7 | "created": "2018-05-31T10:00:31.661Z", 8 | "updated": "2018-05-31T11:30:31.245Z", 9 | "algorithm": "RS256", 10 | "redirect_uris": "http://geonode/geoserver", 11 | "name": "GeoServer", 12 | "authorization_grant_type": "authorization-code", 13 | "client_type": "confidential", 14 | "client_id": "Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV", 15 | "client_secret": "rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3", 16 | "user": [ 17 | "admin" 18 | ] 19 | } 20 | } 21 | ] 22 | -------------------------------------------------------------------------------- /cartoview/log_handler.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from sys import stdout 3 | 4 | formatter = logging.Formatter( 5 | '[%(levelname)s %(asctime)s] {%(name)s:%(lineno)d} - %(message)s', 6 | '%m-%d %H:%M:%S') 7 | 8 | 9 | def get_logger(name=__name__, with_formatter=True): 10 | logger = logging.getLogger(name) 11 | logger.setLevel(logging.DEBUG) 12 | handler = logging.StreamHandler(stdout) 13 | if with_formatter: 14 | handler.setFormatter(formatter) 15 | logger.addHandler(handler) 16 | return logger 17 | -------------------------------------------------------------------------------- /cartoview/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/management/__init__.py -------------------------------------------------------------------------------- /cartoview/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/management/commands/__init__.py -------------------------------------------------------------------------------- /cartoview/management/commands/cherry.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | server.socket_host: "0.0.0.0" 3 | server.socket_port: 8000 4 | server.thread_pool: 30 5 | server.socket_file: None 6 | server.max_request_body_size: 0 7 | server.socket_timeout: 100000 8 | environment: "production" 9 | log.screen: True 10 | # For SSL Support server.ssl_module = 'pyopenssl' 11 | # server.ssl_certificate = 'ssl/certificate.crt' 12 | # server.ssl_private_key = 'ssl/private.key' 13 | # server.ssl_certificate_chain = 'ssl/bundle.crt' -------------------------------------------------------------------------------- /cartoview/management/commands/cherry_server.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import importlib 4 | import os 5 | 6 | import cherrypy 7 | from django.core.management.base import BaseCommand 8 | 9 | _current_path = os.path.abspath(os.path.dirname(__file__)) 10 | _default_config = os.path.join(_current_path, 'cherry.conf') 11 | 12 | 13 | class Command(BaseCommand): 14 | help = 'Start Django Server' 15 | 16 | def add_arguments(self, parser): 17 | parser.add_argument( 18 | '-w', 19 | '--wsgi', 20 | type=str, 21 | dest='wsgi', 22 | nargs='?', 23 | default='cartoview.wsgi', 24 | help='Wsgi Module') 25 | 26 | parser.add_argument( 27 | '-sf', 28 | '--config-file', 29 | type=str, 30 | dest='config_file', 31 | nargs='?', 32 | default=_default_config, 33 | help='Socket File') 34 | 35 | def handle(self, *args, **options): 36 | config_file = options.get('config_file') 37 | wsgi_module = options.get('wsgi') 38 | wsgi_app = importlib.import_module(wsgi_module).application 39 | if os.path.exists(config_file): 40 | self.start_server(wsgi_app, config_file) 41 | else: 42 | raise Exception("Can't find/access config file") 43 | 44 | def start_server(self, wsgi_app, config_file): 45 | cherrypy.tree.graft(wsgi_app, "/") 46 | cherrypy.config.update(config_file) 47 | cherrypy.engine.start() 48 | cherrypy.engine.block() 49 | -------------------------------------------------------------------------------- /cartoview/static/app_manager/app.css: -------------------------------------------------------------------------------- 1 | .l2{ 2 | padding-left: 30px; 3 | } 4 | .panel-heading a:after { 5 | font-family: 'Glyphicons Halflings'; 6 | content: "\e114"; 7 | float: right; 8 | color: grey; 9 | } 10 | .panel-heading a.collapsed:after { 11 | content: "\e080"; 12 | } 13 | 14 | tr:first-of-type a.up { 15 | visibility: hidden; 16 | 17 | } 18 | tr:nth-last-child(1) a.down { 19 | visibility: hidden; 20 | } 21 | 22 | a.up:hover, a.down:hover{text-decoration:none; cursor:pointer;} 23 | #ct-cards { min-width: 560px;} 24 | 25 | 26 | 27 | 28 | h1 { 29 | color: #FF3F00; 30 | font-size: 20px; 31 | font-family: 'Roboto', sans-serif; 32 | font-weight: 300; 33 | text-align: center; 34 | } 35 | 36 | 37 | ul { 38 | margin: 0; 39 | padding: 0; 40 | list-style: none; 41 | } 42 | 43 | 44 | 45 | 46 | 47 | .sortable-ghost { 48 | opacity: .2; 49 | } 50 | 51 | 52 | img { 53 | border: 0; 54 | vertical-align: middle; 55 | } 56 | 57 | 58 | .logo { 59 | top: 55px; 60 | left: 30px; 61 | position: absolute; 62 | } 63 | 64 | 65 | .title { 66 | color: #fff; 67 | padding: 3px 10px; 68 | display: inline-block; 69 | position: relative; 70 | background-color: #FF7373; 71 | z-index: 1000; 72 | } 73 | .title_xl { 74 | padding: 3px 15px; 75 | font-size: 40px; 76 | } 77 | 78 | 79 | 80 | .tile { 81 | width: 22%; 82 | min-width: 245px; 83 | color: #FF7270; 84 | padding: 10px 30px; 85 | text-align: center; 86 | margin-top: 15px; 87 | margin-left: 5px; 88 | margin-right: 30px; 89 | background-color: #fff; 90 | display: inline-block; 91 | vertical-align: top; 92 | } 93 | .tile__name { 94 | cursor: move; 95 | padding-bottom: 10px; 96 | border-bottom: 1px solid #FF7373; 97 | } 98 | 99 | .tile__list { 100 | margin-top: 10px; 101 | } 102 | .tile__list:last-child { 103 | margin-right: 0; 104 | min-height: 80px; 105 | } 106 | 107 | .tile__list img { 108 | cursor: move; 109 | margin: 10px; 110 | border-radius: 100%; 111 | } 112 | 113 | 114 | 115 | .block { 116 | opacity: 1; 117 | 118 | } 119 | .block__list { 120 | padding: 20px 0; 121 | max-width: 360px; 122 | margin-top: -8px; 123 | margin-left: 5px; 124 | background-color: #336699; 125 | } 126 | .block__list li { cursor: move; } 127 | 128 | .block__list_words li { 129 | background-color: #5F9EDF; 130 | padding: 10px 40px; 131 | border:1px solid #FFFFFF; 132 | color: #FFFFFF; 133 | 134 | } 135 | .block__list_words .sortable-ghost { 136 | opacity: 0.4; 137 | background-color: #F4E2C9; 138 | } 139 | 140 | .block__list_words li:first-letter { 141 | text-transform: uppercase; 142 | } 143 | 144 | .block__list_tags { 145 | padding-left: 30px; 146 | } 147 | 148 | .block__list_tags:after { 149 | clear: both; 150 | content: ''; 151 | display: block; 152 | } 153 | .block__list_tags li { 154 | color: #fff; 155 | float: left; 156 | margin: 8px 20px 10px 0; 157 | padding: 5px 10px; 158 | min-width: 10px; 159 | background-color: #5F9EDF; 160 | text-align: center; 161 | } 162 | .block__list_tags li:first-child:first-letter { 163 | text-transform: uppercase; 164 | } 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /cartoview/static/app_manager/apps_list.css: -------------------------------------------------------------------------------- 1 | 2 | .app-logo-ct { 3 | /*background-image: url(default-logo.png);*/ 4 | /*background-size: auto 100%;*/ 5 | /*background-position: center center;*/ 6 | /*background-repeat: no-repeat;*/ 7 | padding: 0; 8 | margin: 0; 9 | } 10 | .apps-wrapper{ 11 | display: flex; 12 | flex-wrap: wrap; 13 | justify-content: center; 14 | flex: none; 15 | } 16 | .caption{ 17 | display: flex !important; 18 | flex-direction: column !important; 19 | } 20 | .flex-row{ 21 | flex-direction: column; 22 | } 23 | .fill-empty{ 24 | display: flex; 25 | flex-grow: 1 26 | } 27 | .thumbnail{ 28 | height: 100%; 29 | padding-bottom: 10px; 30 | display: flex; 31 | flex-direction: column 32 | } 33 | .flex-item{ 34 | display: flex; 35 | flex-direction: column; 36 | width: 23%; 37 | margin: 10px; 38 | } 39 | .app-img{ 40 | height:200px !important; 41 | display: flex; 42 | } 43 | .app-logo { 44 | min-height: 100px; 45 | width: 100%; 46 | background-size: auto 100%; 47 | background-position: center center; 48 | background-repeat: no-repeat; 49 | display: inline-block; 50 | } 51 | 52 | div.list-group-item { 53 | height: auto; 54 | padding: 0; 55 | } 56 | 57 | .list-group-item { 58 | margin: 10px; 59 | } 60 | 61 | .list-group-item img { 62 | max-height: 120px; 63 | margin: auto; 64 | } 65 | 66 | .list-group-item { 67 | border-bottom: 1px solid #eee; 68 | border: 1px solid #dedede; 69 | } 70 | @media (max-width: 418px) { 71 | .flex-item{ 72 | width: 100%; 73 | } 74 | } 75 | @media (max-width: 1024px ) and (min-width:420px) { 76 | .flex-item{ 77 | width: 30%; 78 | } 79 | } -------------------------------------------------------------------------------- /cartoview/static/app_manager/bootstrap-sortable/css/bootstrap-sortable.css: -------------------------------------------------------------------------------- 1 | table.sortable span.sign { 2 | display: block; 3 | position: absolute; 4 | top: 50%; 5 | right: 5px; 6 | font-size: 12px; 7 | margin-top: -10px; 8 | color: #bfbfc1; 9 | } 10 | 11 | table.sortable span.arrow, span.reversed { 12 | border-style: solid; 13 | border-width: 5px; 14 | font-size: 0; 15 | border-color: #ccc transparent transparent transparent; 16 | line-height: 0; 17 | height: 0; 18 | width: 0; 19 | margin-top: -2px; 20 | } 21 | 22 | table.sortable span.arrow.up { 23 | border-color: transparent transparent #ccc transparent; 24 | margin-top: -7px; 25 | } 26 | 27 | table.sortable span.reversed { 28 | border-color: transparent transparent #ccc transparent; 29 | margin-top: -7px; 30 | } 31 | 32 | table.sortable span.reversed.up { 33 | border-color: #ccc transparent transparent transparent; 34 | margin-top: -2px; 35 | } 36 | 37 | 38 | 39 | table.sortable span.az:before { 40 | content: "a .. z"; 41 | } 42 | 43 | table.sortable span.az.up:before { 44 | content: "z .. a"; 45 | } 46 | 47 | table.sortable span.AZ:before { 48 | content: "A .. Z"; 49 | } 50 | 51 | table.sortable span.AZ.up:before { 52 | content: "Z .. A"; 53 | } 54 | 55 | table.sortable span._19:before { 56 | content: "1 .. 9"; 57 | } 58 | 59 | table.sortable span._19.up:before { 60 | content: "9 .. 1"; 61 | } 62 | 63 | table.sortable span.month:before { 64 | content: "jan .. dec"; 65 | } 66 | 67 | table.sortable span.month.up:before { 68 | content: "dec .. jan"; 69 | } 70 | 71 | table.sortable thead th:not([data-defaultsort=disabled]) { 72 | cursor: pointer; 73 | position: relative; 74 | top: 0; 75 | left: 0; 76 | } 77 | 78 | table.sortable thead th:hover:not([data-defaultsort=disabled]) { 79 | background: #efefef; 80 | } 81 | 82 | table.sortable thead th div.mozilla { 83 | position: relative; 84 | } 85 | -------------------------------------------------------------------------------- /cartoview/static/app_manager/default-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/app_manager/default-logo.png -------------------------------------------------------------------------------- /cartoview/static/app_manager/images/Access-Denied.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/app_manager/images/Access-Denied.jpg -------------------------------------------------------------------------------- /cartoview/static/app_manager/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/app_manager/images/ajax-loader.gif -------------------------------------------------------------------------------- /cartoview/static/app_manager/images/cartoview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/app_manager/images/cartoview.png -------------------------------------------------------------------------------- /cartoview/static/app_manager/images/geonode-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/app_manager/images/geonode-dashboard.png -------------------------------------------------------------------------------- /cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/bootstrap-3-arabic/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/app.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/background.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/cartoview-logo-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/cartoview-logo-sm.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/cartoview-logo-text-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/cartoview-logo-text-white.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/cartoview-logo-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/cartoview-logo-text.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/cartoview-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/cartoview-logo.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/edit.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/icon.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/layers.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/logo.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/img/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/cartoview/img/map.png -------------------------------------------------------------------------------- /cartoview/static/cartoview/js/appinstance-service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kamal on 8/4/16. 3 | */ 4 | angular.module('cartoview.appInstances', ['ngResource', 'cartoview.urlsHelper']); 5 | angular.module('cartoview.appInstances').config(function ($httpProvider) { 6 | $httpProvider.defaults.withCredentials = true 7 | }); 8 | angular.module('cartoview.appInstances').factory('AppInstance', function ($resource, urls) { 9 | return $resource(urls.REST_URL + 'appinstances/:instanceId/', {instanceId: '@id'}, { 10 | update: { 11 | method: 'PUT' 12 | } 13 | }); 14 | }); -------------------------------------------------------------------------------- /cartoview/static/cartoview/js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kamal on 8/16/16. 3 | */ 4 | 5 | angular.module('cartoview.index', ['cartoview.base']); 6 | angular.module('cartoview.index').config(function () { 7 | 8 | }); 9 | -------------------------------------------------------------------------------- /cartoview/static/cartoview/js/top-toolbar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kamal on 8/21/16. 3 | */ 4 | angular.module('cartoview.topToolbar', ['cartoview.urlsHelper','cartoview.userInfo', 'ngMaterial']) 5 | .directive('cartoviewTopToolbar', function(urls, cartoviewUser) { 6 | return { 7 | restrict: 'E', 8 | transclude: true, 9 | replace: true, 10 | templateUrl: urls.STATIC_URL + "cartoview/angular-templates/top-toolbar.html", 11 | controller: function ($scope, $mdSidenav) { 12 | $scope.cartoviewUser = cartoviewUser; 13 | $scope.urls = urls; 14 | $scope.showMobileMainHeader = true; 15 | $scope.openSideNavPanel = function(panelId) { 16 | $mdSidenav(panelId).open(); 17 | }; 18 | $scope.closeSideNavPanel = function(panelId) { 19 | $mdSidenav(panelId).close(); 20 | }; 21 | } 22 | } 23 | }); -------------------------------------------------------------------------------- /cartoview/static/compare-versions/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.1.0](https://github.com/omichelsen/compare-versions/releases/tag/v3.1.0) - 2017-09-25 4 | - Ignore leading zero in numbers. 5 | 6 | ## [3.0.1](https://github.com/omichelsen/compare-versions/releases/tag/v3.0.1) - 2017-04-01 7 | - Fix for leading 'v'. 8 | 9 | ## [3.0.0](https://github.com/omichelsen/compare-versions/releases/tag/v3.0.0) - 2016-08-08 10 | - Validate input data. 11 | 12 | ## [2.0.2](https://github.com/omichelsen/compare-versions/releases/tag/v2.0.2) - 2016-06-06 13 | - Handle numbers in pre-release versions. 14 | 15 | ## [2.0.1](https://github.com/omichelsen/compare-versions/releases/tag/v2.0.1) - 2015-09-13 16 | - Fix for versions with <3 digits. 17 | 18 | ## [2.0.0](https://github.com/omichelsen/compare-versions/releases/tag/v2.0.0) - 2015-09-07 19 | - Change global window accessor from returnExports to compareVersions. 20 | 21 | ## [1.1.2](https://github.com/omichelsen/compare-versions/releases/tag/v1.1.2) - 2015-05-03 22 | - Move patch check outside of the for loop. 23 | 24 | ## [1.1.1](https://github.com/omichelsen/compare-versions/releases/tag/v1.1.1) - 2015-05-03 25 | - Add a base 10 radix. 26 | 27 | ## [1.1.0](https://github.com/omichelsen/compare-versions/releases/tag/v1.1.0) - 2015-03-18 28 | - Added support for semver pre-release and metadata syntax. 29 | 30 | ## [1.0.0](https://github.com/omichelsen/compare-versions/releases/tag/v1.0.0) - 2015-03-18 31 | - Initial release. 32 | -------------------------------------------------------------------------------- /cartoview/static/compare-versions/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cartoview/static/compare-versions/README.md: -------------------------------------------------------------------------------- 1 | # compare-versions 2 | 3 | [![Build Status](https://img.shields.io/travis/omichelsen/compare-versions/master.svg)](https://travis-ci.org/omichelsen/compare-versions) 4 | [![Coverage Status](https://coveralls.io/repos/omichelsen/compare-versions/badge.svg?branch=master&service=github)](https://coveralls.io/github/omichelsen/compare-versions?branch=master) 5 | 6 | Compare [semver](http://semver.org/) version strings to find greater, equal or lesser. Runs in the browser as well as Node.js/React Native etc. Has no dependencies and is tiny (<600 bytes gzipped). 7 | 8 | This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`. Also supports wildcards for minor and patch version like `1.0.x` or `1.0.*`. Any leading `v` is ignored. Numbers with leading zero is handled as normal numbers ignoring the zero. 9 | 10 | ## Install 11 | 12 | Install with `npm` or `bower`: 13 | 14 | ```bash 15 | $ npm install compare-versions --save 16 | ``` 17 | 18 | ```bash 19 | $ bower install compare-versions --save 20 | ``` 21 | 22 | ## Usage 23 | 24 | ```javascript 25 | var compareVersions = require('compare-versions'); 26 | 27 | compareVersions('10.1.8', '10.0.4'); // 1 28 | compareVersions('10.0.1', '10.0.1'); // 0 29 | compareVersions('10.1.1', '10.2.2'); // -1 30 | ``` 31 | 32 | Can also be used for sorting: 33 | 34 | ```javascript 35 | var versions = [ 36 | '1.5.19', 37 | '1.2.3', 38 | '1.5.5' 39 | ]; 40 | console.log(versions.sort(compareVersions)); 41 | ``` 42 | 43 | Outputs: 44 | 45 | ```javascript 46 | [ 47 | '1.2.3', 48 | '1.5.5', 49 | '1.5.19' 50 | ] 51 | ``` 52 | -------------------------------------------------------------------------------- /cartoview/static/compare-versions/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "compare-versions", 3 | "version": "3.1.0", 4 | "description": "Compare semver version strings to find greater, equal or lesser.", 5 | "main": "index.js", 6 | "authors": [ 7 | "Ole Bjørn Michelsen " 8 | ], 9 | "moduleType": [ 10 | "amd", 11 | "globals", 12 | "node" 13 | ], 14 | "keywords": [ 15 | "semver", 16 | "version", 17 | "compare", 18 | "browser", 19 | "node" 20 | ], 21 | "license": "MIT", 22 | "ignore": [ 23 | "**/.*", 24 | "node_modules", 25 | "bower_components", 26 | "test", 27 | "tests" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /cartoview/static/compare-versions/index.js: -------------------------------------------------------------------------------- 1 | /* global define */ 2 | (function (root, factory) { 3 | /* istanbul ignore next */ 4 | if (typeof define === 'function' && define.amd) { 5 | define([], factory); 6 | } else if (typeof exports === 'object') { 7 | module.exports = factory(); 8 | } else { 9 | root.compareVersions = factory(); 10 | } 11 | }(this, function () { 12 | 13 | var semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i; 14 | var patch = /-([0-9A-Za-z-.]+)/; 15 | 16 | function split(v) { 17 | var temp = v.replace(/^v/, '').split('.'); 18 | var arr = temp.splice(0, 2); 19 | arr.push(temp.join('.')); 20 | return arr; 21 | } 22 | 23 | function tryParse(v) { 24 | return isNaN(Number(v)) ? v : Number(v); 25 | } 26 | 27 | function validate(version) { 28 | if (typeof version !== 'string') { 29 | throw new TypeError('Invalid argument expected string'); 30 | } 31 | if (!semver.test(version)) { 32 | throw new Error('Invalid argument not valid semver'); 33 | } 34 | } 35 | 36 | return function compareVersions(v1, v2) { 37 | [v1, v2].forEach(validate); 38 | 39 | var s1 = split(v1); 40 | var s2 = split(v2); 41 | 42 | for (var i = 0; i < 3; i++) { 43 | var n1 = parseInt(s1[i] || 0, 10); 44 | var n2 = parseInt(s2[i] || 0, 10); 45 | 46 | if (n1 > n2) return 1; 47 | if (n2 > n1) return -1; 48 | } 49 | 50 | if ([s1[2], s2[2]].every(patch.test.bind(patch))) { 51 | var p1 = patch.exec(s1[2])[1].split('.').map(tryParse); 52 | var p2 = patch.exec(s2[2])[1].split('.').map(tryParse); 53 | 54 | for (i = 0; i < Math.max(p1.length, p2.length); i++) { 55 | if (p1[i] === undefined || typeof p2[i] === 'string' && typeof p1[i] === 'number') return -1; 56 | if (p2[i] === undefined || typeof p1[i] === 'string' && typeof p2[i] === 'number') return 1; 57 | 58 | if (p1[i] > p2[i]) return 1; 59 | if (p2[i] > p1[i]) return -1; 60 | } 61 | } else if ([s1[2], s2[2]].some(patch.test.bind(patch))) { 62 | return patch.test(s1[2]) ? -1 : 1; 63 | } 64 | 65 | return 0; 66 | }; 67 | 68 | })); 69 | -------------------------------------------------------------------------------- /cartoview/static/compare-versions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "compare-versions", 3 | "version": "3.1.0", 4 | "description": "Compare semver version strings to find greater, equal or lesser.", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:omichelsen/compare-versions.git" 9 | }, 10 | "scripts": { 11 | "test": "mocha", 12 | "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", 13 | "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" 14 | }, 15 | "keywords": [ 16 | "semver", 17 | "version", 18 | "compare", 19 | "browser", 20 | "node" 21 | ], 22 | "author": "Ole Bjørn Michelsen ", 23 | "license": "MIT", 24 | "devDependencies": { 25 | "istanbul": "^0.4.3", 26 | "mocha": "^3.0.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cartoview/static/geonode/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/geonode/img/favicon.ico -------------------------------------------------------------------------------- /cartoview/static/geonode/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/static/geonode/img/logo.png -------------------------------------------------------------------------------- /cartoview/store_api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/store_api/__init__.py -------------------------------------------------------------------------------- /cartoview/store_api/api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from tastypie import fields 3 | from tastypie.resources import Resource 4 | 5 | 6 | class GenericApiResource(object): 7 | def __init__(self, initial=None): 8 | self.__dict__['_data'] = {} 9 | 10 | if hasattr(initial, 'items'): 11 | self.__dict__['_data'] = initial 12 | 13 | def __getattr__(self, name): 14 | return self._data.get(name, None) 15 | 16 | def __setattr__(self, name, value): 17 | self.__dict__['_data'][name] = value 18 | 19 | def to_dict(self): 20 | return self._data 21 | 22 | 23 | class StoreAppVersion(Resource): 24 | id = fields.IntegerField() 25 | app = fields.CharField() 26 | build_no = fields.IntegerField() 27 | cartoview_version = fields.ListField() 28 | changelog = fields.CharField() 29 | logo = fields.CharField() 30 | installation_instructions = fields.CharField() 31 | download_link = fields.CharField() 32 | created_at = fields.DateTimeField() 33 | modified_at = fields.DateTimeField() 34 | dependencies = fields.DictField() 35 | downloads = fields.IntegerField() 36 | resource_uri = fields.CharField() 37 | version = fields.CharField() 38 | 39 | class Meta: 40 | resource_name = 'store_app_version' 41 | object_class = GenericApiResource 42 | 43 | def obj_get(self, bundle, **kwargs): 44 | data = bundle.data 45 | obj = GenericApiResource(initial=data) 46 | return obj 47 | 48 | 49 | class StoreAppResource(Resource): 50 | id = fields.IntegerField() 51 | approved = fields.BooleanField() 52 | rejected = fields.BooleanField() 53 | author = fields.CharField() 54 | author_website = fields.CharField() 55 | created_at = fields.DateTimeField() 56 | demo_url = fields.CharField() 57 | description = fields.CharField() 58 | title = fields.CharField() 59 | status = fields.CharField() 60 | tags = fields.ListField() 61 | type = fields.ListField() 62 | downloads = fields.IntegerField() 63 | stars = fields.IntegerField() 64 | license = fields.DictField() 65 | latest_version = fields.ForeignKey(StoreAppVersion, 'latest_version') 66 | modified_at = fields.DateTimeField() 67 | name = fields.CharField() 68 | resource_uri = fields.CharField() 69 | server_type = fields.DictField() 70 | single_instance = fields.BooleanField() 71 | 72 | class Meta: 73 | resource_name = 'store_app' 74 | object_class = GenericApiResource 75 | 76 | def obj_get(self, bundle, **kwargs): 77 | data = bundle.data 78 | latest_version = data.pop('latest_version', None) 79 | obj = GenericApiResource(initial=data) 80 | api_obj = StoreAppVersion() 81 | if latest_version: 82 | bundle = api_obj.build_bundle(data=latest_version) 83 | v_obj = api_obj.obj_get(bundle) 84 | obj.latest_version = v_obj 85 | return obj 86 | -------------------------------------------------------------------------------- /cartoview/store_api/apps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class StoreApiConfig(AppConfig): 7 | name = 'cartoview.store_api' 8 | verbose_name = "Store Api" 9 | -------------------------------------------------------------------------------- /cartoview/templates/cartoview/base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load i18n %} 4 | {% block extra_head %} 5 | {{ block.super }} 6 | {% endblock %} 7 | 8 | {% block footer %} 9 | {% include 'cartoview/footer.html' %} 10 | {% endblock %} -------------------------------------------------------------------------------- /cartoview/templates/cartoview/check_version.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kamal on 2/13/17. 3 | */ 4 | (function () { 5 | var currentVersion = "{{current_version}}", 6 | latestVersion = "{{latest_version}}"; 7 | const el="
A new version(v "+latestVersion+") of cartoview is available for dowonload, Please upgrade. Installed Version(v "+currentVersion+")
" 8 | const check=compareVersions(currentVersion, latestVersion); 9 | if(check===-1){ 10 | document.write(el) 11 | } 12 | 13 | })(); 14 | -------------------------------------------------------------------------------- /cartoview/templates/cartoview/footer.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | -------------------------------------------------------------------------------- /cartoview/templates/cartoview/search_box.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | -------------------------------------------------------------------------------- /cartoview/templates/geonode_base.html: -------------------------------------------------------------------------------- 1 | {% extends "cartoview/base.html" %} -------------------------------------------------------------------------------- /cartoview/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/templatetags/__init__.py -------------------------------------------------------------------------------- /cartoview/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/cartoview/tests/__init__.py -------------------------------------------------------------------------------- /cartoview/tests/test_log_handler.py: -------------------------------------------------------------------------------- 1 | from logging import Logger, DEBUG 2 | 3 | from django.test import TestCase 4 | 5 | from cartoview.log_handler import get_logger 6 | 7 | 8 | class CartoviewHomeViewTest(TestCase): 9 | 10 | def test_get_logger(self): 11 | logger = get_logger(__name__) 12 | self.assertEqual(isinstance(logger, Logger), True) 13 | self.assertEqual(logger.name, __name__) 14 | self.assertEqual(logger.level, DEBUG) 15 | -------------------------------------------------------------------------------- /cartoview/tests/test_template_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.http import HttpRequest 3 | from django.template import Context, Template 4 | from django.test.testcases import TestCase 5 | 6 | from geonode.people.models import Profile 7 | 8 | 9 | class CartoviewTemplateTagsTest(TestCase): 10 | fixtures = ['sample_admin.json', ] 11 | 12 | def render_template(self, string, context=None): 13 | context = context or {} 14 | context = Context(context) 15 | return Template(string).render(context) 16 | 17 | def test_template_tags(self): 18 | rendered = self.render_template( 19 | """{% load cartoview_tags %}x={{test_dict|dump_json}}""", { 20 | "test_dict": {"foo": "bar"}} 21 | ) 22 | self.assertEqual(rendered, u'x={"foo": "bar"}') 23 | self.assertRaises( 24 | template.TemplateSyntaxError, 25 | self.render_template, 26 | """{% load cartoview_tags %%}}x={{test_dict|dump_json}}""", { 27 | "test_dict": {"foo": "bar"}} 28 | ) 29 | req = HttpRequest() 30 | req.user = Profile.objects.filter(username="admin").first() 31 | rendered = self.render_template( 32 | """{% load cartoview_tags %}{% facets as facets %}{{facets}}""", { 33 | "request": req} 34 | ) 35 | # self.assertEqual( 36 | # rendered, u'{u'raster': 0, u'vector': 0, u'' + # noqa 37 | # 'remote': 0, u'document': 0, u'map': 0}') 38 | self.assertRaises( 39 | template.TemplateSyntaxError, 40 | self.render_template, 41 | """{% load cartoview_tags %%}}x={{test_dict|dump_json}}""", { 42 | "test_dict": {"foo": "bar"}} 43 | ) 44 | -------------------------------------------------------------------------------- /cartoview/tests/test_version_module.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from cartoview import get_current_version 4 | from cartoview.version import get_version, json_version_info 5 | 6 | 7 | class CartoviewVersionModule(TestCase): 8 | def test_json_version_info(self): 9 | version_text = json_version_info() 10 | self.assertTrue(isinstance(version_text, str)) 11 | cond1 = "current_version" in version_text 12 | cond2 = "backward_versions" in version_text 13 | self.assertTrue(cond1 and cond2) 14 | 15 | def test_get_version(self): 16 | stable = (1, 8, 5, 'final', 0) 17 | unstable = (1, 8, 5, 'unstable', 0) 18 | rc = (1, 8, 5, 'rc', 0) 19 | beta = (1, 8, 5, 'beta', 0) 20 | version = get_version(stable) 21 | self.assertEqual(version, '1.8.5') 22 | version = get_version(rc) 23 | self.assertEqual(version, '1.8.5rc0') 24 | version = get_version(beta) 25 | self.assertEqual(version, '1.8.5b0') 26 | version = get_version(unstable) 27 | self.assertTrue("dev" in version) 28 | _version = get_current_version() 29 | self.assertNotEqual(_version, '') 30 | -------------------------------------------------------------------------------- /cartoview/tests/test_views.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | from django.urls import reverse 5 | from django.test import TestCase 6 | from geonode.urls import api 7 | from pkg_resources import parse_version 8 | 9 | from cartoview.version import get_current_version 10 | 11 | 12 | class CartoviewHomeViewTest(TestCase): 13 | 14 | def test_view_url_exists_at_desired_location(self): 15 | resp = self.client.get('/') 16 | self.assertEqual(resp.status_code, 200) 17 | 18 | def test_view_url_accessible_by_name(self): 19 | resp = self.client.get(reverse('home')) 20 | self.assertEqual(resp.status_code, 200) 21 | 22 | def test_view_uses_correct_template(self): 23 | resp = self.client.get(reverse('home')) 24 | self.assertEqual(resp.status_code, 200) 25 | self.assertTemplateUsed(resp, 'index.html') 26 | 27 | 28 | class CartoviewCheckVersionViewTest(TestCase): 29 | 30 | def test_view_url_exists_at_desired_location(self): 31 | resp = self.client.get('/check-version/') 32 | self.assertEqual(resp.status_code, 200) 33 | 34 | def test_view_url_accessible_by_name(self): 35 | resp = self.client.get(reverse('check_version')) 36 | self.assertEqual(resp.status_code, 200) 37 | 38 | def test_view_uses_correct_template(self): 39 | resp = self.client.get(reverse('check_version')) 40 | self.assertEqual(resp.status_code, 200) 41 | self.assertTemplateUsed(resp, 'cartoview/check_version.js') 42 | self.assertEqual("current_version" in resp.context, True) 43 | self.assertEqual("latest_version" in resp.context, True) 44 | _version = parse_version(get_current_version())._version 45 | release = _version.release 46 | version = [str(x) for x in release] 47 | current_version = ".".join(version) 48 | req = requests.get("https://pypi.org/pypi/cartoview/json") 49 | latest_version = str(req.json()["info"]["version"]) 50 | self.assertEqual(resp.context["current_version"], current_version) 51 | self.assertEqual(resp.context["latest_version"], latest_version) 52 | 53 | 54 | class CartoviewResourcesRegisteredTest(TestCase): 55 | 56 | def test_api_url_exists_at_desired_location(self): 57 | resp = self.client.get('/api/') 58 | self.assertEqual(resp.status_code, 200) 59 | 60 | def test_api_url_accessible_by_name(self): 61 | resp = self.client.get( 62 | reverse("api_%s_top_level" % api.api_name, 63 | kwargs={"api_name": api.api_name})) 64 | self.assertEqual(resp.status_code, 200) 65 | 66 | def test_cartoview_resources_exists(self): 67 | resp = self.client.get( 68 | reverse("api_%s_top_level" % api.api_name, 69 | kwargs={"api_name": api.api_name})) 70 | self.assertEqual(resp.status_code, 200) 71 | resources_dict = json.loads(resp.content) 72 | self.assertTrue("app" in resources_dict.keys()) 73 | self.assertTrue("appinstances" in resources_dict.keys()) 74 | self.assertTrue("all_resources" in resources_dict.keys()) 75 | for endpoint in resources_dict.values(): 76 | resp = self.client.get(endpoint['list_endpoint']) 77 | self.assertEqual(resp.status_code, 200) 78 | -------------------------------------------------------------------------------- /cartoview/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | from django.conf.urls import include, url 5 | from geonode.api.urls import api 6 | from geonode.urls import urlpatterns as geonode_urls 7 | 8 | from cartoview.app_manager.rest import (AppInstanceResource, AppResource, 9 | AppTypeResource, 10 | LayerFilterExtensionResource) 11 | from cartoview.cartoview_api.views import layer_config_json, update_extent 12 | from cartoview.views import check_version 13 | from .cartoview_api.rest import (AllResourcesResource, AttributeResource, 14 | ExtendedResourceBaseResource, 15 | MapLayerResource) 16 | 17 | api.register(AppInstanceResource()) 18 | api.register(AppResource()) 19 | api.register(AppTypeResource()) 20 | api.register(LayerFilterExtensionResource()) 21 | api.register(AllResourcesResource()) 22 | api.register(AttributeResource()) 23 | api.register(MapLayerResource()) 24 | api.register(ExtendedResourceBaseResource()) 25 | urlpatterns = [ 26 | url(r'^layer/(?P[^/]*)/json/?$', layer_config_json, name='layer_json'), 27 | url(r'^update/extent/(?P[^/]*)$', update_extent, name='cartoview.update_extent'), 28 | url(r'^check-version/$', check_version, name='check_version'), 29 | url(r'', include(api.urls)), 30 | url(r'^cv_apps/', include('cartoview.app_manager.urls')), 31 | ] 32 | urlpatterns += geonode_urls 33 | -------------------------------------------------------------------------------- /cartoview/version.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import json 3 | import os 4 | import subprocess 5 | 6 | from cartoview import __compatible_with__, __version__ 7 | 8 | 9 | # -*- coding: utf-8 -*- 10 | ######################################################################### 11 | # 12 | # Copyright (C) 2016 OSGeo 13 | # 14 | # This program is free software: you can redistribute it and/or modify 15 | # it under the terms of the GNU General Public License as published by 16 | # the Free Software Foundation, either version 3 of the License, or 17 | # (at your option) any later version. 18 | # 19 | # This program is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | # GNU General Public License for more details. 23 | # 24 | # You should have received a copy of the GNU General Public License 25 | # along with this program. If not, see . 26 | # 27 | ######################################################################### 28 | 29 | 30 | def get_version(version=None): 31 | "Returns a PEP 386-compliant version number from VERSION." 32 | if version is None: 33 | from cartoview import __version__ as version 34 | else: 35 | assert len(version) == 5 36 | assert version[3] in ('unstable', 'beta', 'rc', 'final') 37 | 38 | # Now build the two parts of the version number: 39 | # main = X.Y[.Z] 40 | # sub = .devN - for pre-alpha releases 41 | # | {a|b|c}N - for alpha, beta and rc releases 42 | 43 | parts = 2 if version[2] == 0 else 3 44 | main = '.'.join(str(x) for x in version[:parts]) 45 | 46 | sub = '' 47 | if version[3] == 'unstable': 48 | git_changeset = get_git_changeset() 49 | if git_changeset: 50 | sub = '.dev%s' % git_changeset 51 | 52 | elif version[3] != 'final': 53 | mapping = {'beta': 'b', 'rc': 'rc'} 54 | sub = mapping[version[3]] + str(version[4]) 55 | 56 | return main + sub 57 | 58 | 59 | def get_git_changeset(): 60 | """Returns a numeric identifier of the latest git changeset. 61 | The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format. 62 | This value isn't guaranteed to be unique, but collisions are very unlikely, 63 | so it's sufficient for generating the development version numbers. 64 | """ 65 | repo_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 66 | git_show = subprocess.Popen('git show --pretty=format:%ct --quiet HEAD', 67 | stdout=subprocess.PIPE, stderr=subprocess.PIPE, 68 | shell=True, cwd=repo_dir, 69 | universal_newlines=True) 70 | timestamp = git_show.communicate()[0].partition('\n')[0] 71 | try: 72 | timestamp = datetime.datetime.utcfromtimestamp(int(timestamp)) 73 | except ValueError: 74 | return None 75 | return timestamp.strftime('%Y%m%d%H%M%S') 76 | 77 | 78 | def get_current_version(): 79 | return get_version(__version__) 80 | 81 | 82 | def get_backward_compatible(): 83 | backward_compatible = [ 84 | get_version(version) for version in __compatible_with__ 85 | ] 86 | return backward_compatible 87 | 88 | 89 | def json_version_info(): 90 | info = { 91 | 'current_version': get_current_version(), 92 | 'backward_versions': get_backward_compatible() 93 | } 94 | return json.dumps(info) 95 | -------------------------------------------------------------------------------- /cartoview/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import requests 3 | from django.shortcuts import render 4 | from pkg_resources import parse_version 5 | 6 | from .log_handler import get_logger 7 | from .version import get_current_version 8 | 9 | logger = get_logger(__name__) 10 | 11 | 12 | def check_version(request): 13 | r = requests.get("https://pypi.org/pypi/cartoview/json") 14 | _version = parse_version(get_current_version())._version 15 | release = _version.release 16 | version = [str(x) for x in release] 17 | current_version = ".".join(version) 18 | context = dict( 19 | latest_version=r.json()["info"]["version"], 20 | current_version=current_version) 21 | return render( 22 | request, 23 | "cartoview/check_version.js", 24 | context=context, 25 | content_type="text/javascript") 26 | -------------------------------------------------------------------------------- /cartoview/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cartoview project. 3 | 4 | This module contains the WSGI application used by Django's development server 5 | and any production WSGI deployments. It should expose a module-level variable 6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover 7 | this application via the ``WSGI_APPLICATION`` setting. 8 | 9 | Usually you will have the standard Django WSGI application here, but it also 10 | might make sense to replace the whole Django WSGI application with a custom one 11 | that later delegates to the Django one. For example, you could introduce WSGI 12 | middleware here, or combine a Django application with an application of another 13 | framework. 14 | 15 | """ 16 | import os 17 | 18 | from django.core.wsgi import get_wsgi_application 19 | 20 | # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cartoview.settings") 21 | os.environ["DJANGO_SETTINGS_MODULE"] = "cartoview.settings" 22 | # This application object is used by any WSGI server configured to use this 23 | # file. This includes Django's development server, if the WSGI_APPLICATION 24 | # setting points here. 25 | application = get_wsgi_application() 26 | 27 | # Apply WSGI middleware here. 28 | # from helloworld.wsgi import HelloWorldApplication 29 | # application = HelloWorldApplication(application) 30 | -------------------------------------------------------------------------------- /dev_config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.19.x/geoserver.war" 3 | DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.19.x/geonode-geoserver-ext-web-app-data.zip" 4 | JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" 5 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | postgis: 4 | image: kartoza/postgis:13 5 | volumes: 6 | - postgis-data:/var/lib/postgresql 7 | # - dbbackups:/backups 8 | env_file: 9 | - ./env/postgis.env 10 | expose: 11 | - "5432" 12 | restart: on-failure 13 | healthcheck: 14 | test: "exit 0" 15 | networks: 16 | -cartoview-internal: 17 | elasticsearch: 18 | image: elasticsearch:5.6.12-alpine 19 | restart: unless-stopped 20 | stdin_open: true 21 | tty: true 22 | expose: 23 | - "9300" 24 | - "9200" 25 | networks: 26 | -cartoview-internal: 27 | rabbitmq: 28 | image: rabbitmq:latest 29 | restart: unless-stopped 30 | expose: 31 | - "5672" 32 | - "15672" 33 | networks: 34 | -cartoview-internal: 35 | data-dir-conf: 36 | image: geonode/geoserver_data:2.19.x 37 | restart: on-failure 38 | container_name: gsconf4cartoview 39 | command: /bin/true 40 | volumes: 41 | - geoserver-dir:/geoserver_data/data 42 | geoserver: 43 | image: geonode/geoserver:2.19.x 44 | depends_on: 45 | - postgis 46 | - data-dir-conf 47 | restart: unless-stopped 48 | expose: 49 | - "8080" 50 | volumes: 51 | - geoserver-dir:/geoserver_data/data 52 | env_file: 53 | - ./env/tomcat.env 54 | networks: 55 | -cartoview-external: 56 | ipv4_address: 10.5.0.2 57 | -cartoview-internal: 58 | cartoview: 59 | build: . 60 | image: cartoview:latest 61 | container_name: cartoview_django 62 | command: bash -c "python manage.py cherry_server" 63 | restart: unless-stopped 64 | hostname: cartoview 65 | depends_on: 66 | - postgis 67 | - geoserver 68 | env_file: 69 | - ./env/django.env 70 | volumes: 71 | - "./:/usr/src/carto_app/cartoview" 72 | - geoserver-dir:/geoserver_data/data 73 | networks: 74 | -cartoview-external: 75 | ipv4_address: 10.5.0.3 76 | -cartoview-internal: 77 | expose: 78 | - "8000" 79 | celery: 80 | image: cartoview:latest 81 | container_name: cartoview_celery 82 | command: bash -c "celery -A cartoview.celery:app worker -B -E --statedb=./worker.state -s ./celerybeat-schedule --loglevel=INFO --concurrency=10 -n worker1@%h -f /var/log/celery.log" 83 | restart: unless-stopped 84 | hostname: celery 85 | depends_on: 86 | - postgis 87 | - rabbitmq 88 | - geoserver 89 | stdin_open: true 90 | env_file: 91 | - ./env/celery.env 92 | volumes: 93 | - "./:/code/" 94 | networks: 95 | -cartoview-internal: 96 | nginx: 97 | image: nginx:alpine 98 | restart: unless-stopped 99 | expose: 100 | - "80" 101 | volumes: 102 | - ./scripts/nginx/nginx.conf:/etc/nginx/nginx.conf 103 | - ./static/:/cartoview/static/ 104 | - ./uploaded/:/cartoview/uploaded/ 105 | networks: 106 | -cartoview-external: 107 | ipv4_address: 10.5.0.4 108 | -cartoview-internal: 109 | ports: 110 | - "80:80" 111 | networks: 112 | -cartoview-external: 113 | driver: bridge 114 | ipam: 115 | config: 116 | - subnet: 10.5.0.0/16 117 | -cartoview-internal: 118 | internal: true 119 | volumes: 120 | geoserver-dir: 121 | postgis-data: 122 | -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Frequently Asked Questions 3 | 4 | **1. What is Cartoview exactly? Is it a replacement for GeoNode?** 5 | 6 | [Cartoview](https://cartoview.net/) is a [Geo App market](https://appstore.cartoview.net/) for GeoNode. It is not a fork / improvement / reprlacement of GeoNode, but rather additional code aimed to make it more extensible to integrate third party apps directly from the browser. 7 | 8 | *** 9 | 10 | **2. What are the goals of Cartoview?** 11 | 12 | - Sharing GIS Apps. 13 | - Provide apps for common tasks like visualizing and querying feature services. 14 | - Extend the functions of the GeoNode SDI beyond data management. 15 | - Provide a solid core of utilities that can be used to help developers integrate and deploy their Geo apps. 16 | - Foster an ecosystem of apps extending easily deplyable and installable. 17 | 18 | *** 19 | 20 | **3. Can I use Cartoview with GeoNode Version 2.4 and earlier?** 21 | 22 | Cartoview starts working with GeoNode 2.5 23 | 24 | *** 25 | 26 | **4. I have an idea! What should I do?** 27 | 28 | Please [file an issue](https://github.com/cartologic/cartoview/issues/new). Issues are a great way to discuss new ideas, build consensus, and talk about implementation details. 29 | 30 | *** 31 | 32 | **5. I built something with Cartoview, can I show you?** 33 | 34 | Absolutely! Share it on Twitter with [@ahmednosman](https://twitter.com/ahmednosman) or [@Cartoview](https://twitter.com/CartoView). 35 | 36 | *** 37 | 38 | **6. I built a reusable app can I contribute it?** 39 | 40 | Of course! This is the purpose of Cartoview. Read the instructions on developing and deploying apps. Create an account on [Cartoview App market](https://appstore.cartoview.net/) and load your app. Your app will be immediately available to all Cartoview deployments. 41 | 42 | *** 43 | 44 | **7. What are the best Cartoview Apps?** 45 | 46 | - [ArcGIS Importer](https://appstore.cartoview.net/app/arcgis_importer/): This app allows importing ArcGIS feature layer into a PostGIS database while adding it to GeoServer and GeoNode. 47 | 48 | - [Data Manager](https://appstore.cartoview.net/app/data_manager/): Upload and puplish a [GeoPackage](https://www.geopackage.org/) to GeoServer and GeoNode. 49 | 50 | - [Terria Map](https://appstore.cartoview.net/app/cartoview_terriaJs/): Visulaize GeoNode maps using a library for building rich, web-based geospatial data platforms called [TerriaJS](https://terria.io/). 51 | 52 | - (Coming Soon) **Data Collection**: This app enables you to collect data through dynamically configured forms using mobile app and add them as features to an empty layer in GeoNode. 53 | 54 | *** 55 | 56 | **8. Running Cartoview on GeoNode and QGIS Server?** 57 | 58 | There is no reason for Cartoview not to work on this deployment. (This was never tested). Apps relying on GeoServer of course will not work. 59 | -------------------------------------------------------------------------------- /docs/contribute.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Contributing to Cartoview 3 | 4 | Please refer to each project's style guidelines for submitting patches and additions. 5 | 6 | In general, we follow the "fork-and-pull" Git workflow. 7 | 8 | - Fork the Repo on GitHub. 9 | - Clone the project to your own machine. 10 | - Commit changes to your own branch. 11 | - Push your work back up to your fork. 12 | - Submit a Pull request so that we can review your changes. 13 | 14 | 15 | !!! note 16 | Be sure to merge the latest from "upstream" before making a pull request. -------------------------------------------------------------------------------- /docs/css/custom.css: -------------------------------------------------------------------------------- 1 | .hljs, .admonition code{ 2 | background-color: #EEFFCC; 3 | } 4 | 5 | .hljs{ 6 | padding: 1em; 7 | } 8 | 9 | .wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul{ 10 | margin-bottom: 0; 11 | } 12 | 13 | .admonition{ 14 | margin: 10px 0px; 15 | } 16 | 17 | .wy-breadcrumbs-aside{ 18 | display: none !important; 19 | } -------------------------------------------------------------------------------- /docs/demo.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Cartoview Demo 3 | 4 | You can try Cartoview from the demo [here](http://try.cartoview.net/). It should allow you to easily and quickly, explore the main capabilities of Cartoview. 5 | 6 | ![Cartoview Demo!](img/demo/cartoview-demo.png "Cartoview Demo") 7 | 8 | Create an account, load some test data, and start interacting with different Web Mapping Applicaitons. 9 | 10 | ![Cartoview Apps!](img/demo/cartoview-apps.png "Cartoview Apps") 11 | -------------------------------------------------------------------------------- /docs/for-developers.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # For Developers 3 | 4 | Cartoview provides [GeoApp Market](https://appstore.cartoview.net/) for GIS Developers. 5 | 6 | ## Create and Add your django app to Cartoview 7 | 8 | *** 9 | 10 | Create a new empty app from **Cartoview App template** as below in your Cartoview project directory. 11 | 12 | ```shell 13 | cd cartoview_project/apps 14 | django-admin.py startapp --template=https://github.com/cartologic/Cartoview-app-template/archive/master.zip 15 | ``` 16 | 17 | Edit ``cartoview_project/apps/apps.json`` and add an entry for your app. If you can't find `apps.json`, create it and add the following lines: 18 | 19 | ```json 20 | { 21 | "app_name": { 22 | "active": true, 23 | "order": 1, 24 | "pending": false 25 | }, 26 | } 27 | ``` 28 | 29 | Add stores using the following command inside Cartoview project directory. 30 | 31 | ```shell 32 | python manage.py loaddata app_stores.json 33 | ``` 34 | 35 | Add the new app to the database using the admin interface at `/admin`. 36 | 37 | ![Developers app](img/for-developers/developers_app.png) 38 | 39 | !!! note 40 | Don't forget to check Single instance option if you want to test it for the first time. 41 | 42 | ![Developers app](img/for-developers/single_instance.PNG) 43 | 44 | Now open Cartoview, navigate to ``Apps``, your app should be there. 45 | 46 | ![Developers app](img/for-developers/apps_panel.PNG) 47 | 48 | Click ``Explore`` button to open the app home page. 49 | 50 | ![Developers app](img/for-developers/app_home.PNG) 51 | 52 | Congratulations, now you have created your first app on Cartoview. You can upload it to [Cartoview App market](https://appstore.cartoview.net/) to make use of the features provided by this market. 53 | -------------------------------------------------------------------------------- /docs/img/cartoview-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/cartoview-logo.png -------------------------------------------------------------------------------- /docs/img/demo/cartoview-apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/demo/cartoview-apps.png -------------------------------------------------------------------------------- /docs/img/demo/cartoview-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/demo/cartoview-demo.png -------------------------------------------------------------------------------- /docs/img/for-developers/app_home.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/for-developers/app_home.PNG -------------------------------------------------------------------------------- /docs/img/for-developers/apps_panel.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/for-developers/apps_panel.PNG -------------------------------------------------------------------------------- /docs/img/for-developers/developers_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/for-developers/developers_app.png -------------------------------------------------------------------------------- /docs/img/for-developers/single_instance.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/for-developers/single_instance.PNG -------------------------------------------------------------------------------- /docs/img/installation/Docker/cartoview_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/cartoview_admin.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/cartoview_browser.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/cartoview_browser.PNG -------------------------------------------------------------------------------- /docs/img/installation/Docker/cartoview_cli.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/cartoview_cli.PNG -------------------------------------------------------------------------------- /docs/img/installation/Docker/cartoview_docker.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/cartoview_docker.PNG -------------------------------------------------------------------------------- /docs/img/installation/Docker/cartoview_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/cartoview_logs.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/compose_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/compose_v2.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/geoserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/geoserver.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/geoserver_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/geoserver_admin.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/geoserver_pass1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/geoserver_pass1.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/geoserver_pass2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/geoserver_pass2.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/geoserver_pass3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/geoserver_pass3.png -------------------------------------------------------------------------------- /docs/img/installation/Docker/whale_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Docker/whale_icon.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/admin-configuration-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/admin-configuration-1.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/admin-configuration-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/admin-configuration-2.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/admin.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/apps.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/cartoview-directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/cartoview-directory.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/cartoview-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/cartoview-home.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/cartoview-services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/cartoview-services.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/db-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/db-mode.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/domain-ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/domain-ip.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/gis-db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/gis-db.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/installation-location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/installation-location.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/installing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/installing.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/launch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/launch.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/postgres-credentials.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/postgres-credentials.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/postgres-dir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/postgres-dir.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/restart-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/restart-service.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/server-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/server-details.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/services.png -------------------------------------------------------------------------------- /docs/img/installation/Installer/web-db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Installer/web-db.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/cartoview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/cartoview.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/geoserver-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/geoserver-login.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/geoserver-password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/geoserver-password.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/geoserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/geoserver.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/pycharm_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/pycharm_1.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/pycharm_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/pycharm_2.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/pycharm_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/pycharm_3.png -------------------------------------------------------------------------------- /docs/img/installation/Ubuntu/tomcat_manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Ubuntu/tomcat_manager.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/install_gdal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/install_gdal.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/install_python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/install_python.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/add-extension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/add-extension.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/create-database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/create-database.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/database-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/database-name.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/new-server-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/new-server-1.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/new-server-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/new-server-2.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/pgAdmin-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/pgAdmin-dashboard.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pgAdmin/set-password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pgAdmin/set-password.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/access-terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/access-terminal.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/add-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/add-path.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/postgres1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/postgres1.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/postgres2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/postgres2.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/postgres3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/postgres3.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/postgres4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/postgres4.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/postgres5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/postgres5.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/postgres/restart-postgres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/postgres/restart-postgres.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pycharm/env-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pycharm/env-settings.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pycharm/env-variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pycharm/env-variables.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pycharm/terminal-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pycharm/terminal-check.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/pycharm/terminal-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/pycharm/terminal-settings.png -------------------------------------------------------------------------------- /docs/img/installation/Windows/start-geoserver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/installation/Windows/start-geoserver.png -------------------------------------------------------------------------------- /docs/img/manage-apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/manage-apps.png -------------------------------------------------------------------------------- /docs/img/upload-app/add_package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/add_package.png -------------------------------------------------------------------------------- /docs/img/upload-app/app_manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/app_manager.png -------------------------------------------------------------------------------- /docs/img/upload-app/app_market.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/app_market.png -------------------------------------------------------------------------------- /docs/img/upload-app/app_on_appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/app_on_appstore.png -------------------------------------------------------------------------------- /docs/img/upload-app/create_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/create_app.png -------------------------------------------------------------------------------- /docs/img/upload-app/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/login.png -------------------------------------------------------------------------------- /docs/img/upload-app/my_apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/my_apps.png -------------------------------------------------------------------------------- /docs/img/upload-app/now_App_on_market.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/now_App_on_market.png -------------------------------------------------------------------------------- /docs/img/upload-app/repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/repo.png -------------------------------------------------------------------------------- /docs/img/upload-app/user_info_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/user_info_1.png -------------------------------------------------------------------------------- /docs/img/upload-app/user_info_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cartologic/cartoview/8e5c7d588a45c81f4c2c4ddda6275fb3c7a8320e/docs/img/upload-app/user_info_2.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | ## About Cartoview 3 | 4 | [**Cartoview**](https://cartoview.net/) is a web platform that extends the popular GeoNode SDI to provide the ability to create, share, and visualize GIS Web Mapping Applications easily and quickly from the browser. Cartoview Provides an [Appstore](https://appstore.cartoview.net/) for GIS Developers. 5 | 6 | ## GeoNode and Cartoview 7 | 8 | [GeoNode](https://geonode.org/) is an Open Source, Content Management System (CMS) for geospatial data. It is a web-based application and platform for developing geospatial information systems (GIS) and for deploying spatial data infrastructures (SDI). 9 | 10 | Cartoview enables communities of users to share geospatial applications, to collaborate on these applications, and to exchange the underlying data as Open Geospatial Consortium (OGC) compliant web services. 11 | 12 | Cartoview has been built utilizing open source software and open standards to make it available for all GIS operators and to maximize interoperability. Cartoview is developed and maintained by [Cartologic](https://cartologic.com/). 13 | -------------------------------------------------------------------------------- /docs/install-app.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Install App 3 | 4 | !!! note 5 | These steps works ONLY if Cartoview is up and running. 6 | 7 | To install apps from [GeoApp Market](https://appstore.cartoview.net/): 8 | 9 | Go to ``Apps`` tab, click ``Manage Apps`` button, and install the app you want. 10 | 11 | ![Install App](img/manage-apps.png "Install App") 12 | -------------------------------------------------------------------------------- /docs/installation/vagrant.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](../img/cartoview-logo.png) 2 | # Cartoview Core Installation | Vagrant 3 | 4 | ## Introduction 5 | This document describes the installation of Cartoview using Vagrant. 6 | 7 | Cartoview Installation with Vagrant will be available soon. 8 | -------------------------------------------------------------------------------- /docs/issues.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Issues 3 | 4 | If something isn't working the way you expected, please take a look at the [issues](https://github.com/cartologic/cartoview/issues) section on GitHub if your problem had been addressed already. 5 | 6 | If you found a new bug or want to request a new feature, we would love to hear from you. Please let us know by [submitting an issue](https://github.com/cartologic/cartoview/issues/new). 7 | -------------------------------------------------------------------------------- /docs/key-features.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Cartoview Key Features 3 | 4 | [GeoApp Market](https://appstore.cartoview.net/) for GIS Web Applications, Once you install GeoNode and Cartoview you will be able to install GIS applications directly from the browser. 5 | 6 | Configure and Publish web mapping applications directly from the browser. 7 | 8 | Cartoview leverages the data management and security infrastructures of [GeoNode](https://geonode.org/) to deploy and serve GIS applications. 9 | 10 | Developers can create applications and deploy them on the [GeoApp Market](https://appstore.cartoview.net/). 11 | 12 | Once the app is deployed it becomes available to all Cartoview deployments. 13 | -------------------------------------------------------------------------------- /docs/upload-app.md: -------------------------------------------------------------------------------- 1 | ![Cartoview Logo](img/cartoview-logo.png) 2 | # Upload App to Cartoview GeoApp Market 3 | 4 | After creating your app as mentioned at [For Developer's section](/for-developers), you can upload your app to [Carotview App Market](https://appstore.cartoview.net/) to be shared with Cartoview community and make the best use of features provided by Cartoview. 5 | 6 | ## Upload your app to Cartoview App market 7 | 8 | Visit [Cartoview App Market](https://appstore.cartoview.net/) 9 | 10 | ![App Market](img/upload-app/app_market.png) 11 | 12 | Login with your Google, Twitter or GitHub account. 13 | 14 | ![App Market](img/upload-app/login.png) 15 | 16 | After login, you will need to fill your info to submit apps. 17 | 18 | ![App Market](img/upload-app/my_apps.png) 19 | ![App Market](img/upload-app/repo.png) 20 | 21 | Now you can submit apps. 22 | 23 | ![App Market](img/upload-app/create_app.png) 24 | 25 | Fill the information about your app. 26 | 27 | ![App Market](img/upload-app/user_info_1.png) 28 | ![App Market](img/upload-app/user_info_2.png) 29 | 30 | !!! note 31 | You need to upload the app package as a zipped folder. 32 | 33 | ![App Market](img/upload-app/add_package.png) 34 | 35 | After submitting your app, it will need an approval. After it's approved, the status will change to be ``approved``. 36 | 37 | ![App Market](img/upload-app/app_manager.png) 38 | 39 | After approval, you will find your app on Cartoview App Market. 40 | 41 | ![App Market](img/upload-app/app_on_appstore.png) 42 | 43 | ![App Market](img/upload-app/now_App_on_market.png) 44 | -------------------------------------------------------------------------------- /env/celery.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgis://docker:docker@postgis:5432/cartoview 2 | DATASTORE_DATABASE_URL=postgis://docker:docker@postgis:5432/cartoview_datastore 3 | GEOSERVER_PUBLIC_LOCATION=http://10.5.0.4/geoserver/ 4 | GEOSERVER_LOCATION=http://geoserver:8080/geoserver/ 5 | SITEURL=http://10.5.0.4/ 6 | DOCKER=True 7 | ALLOWED_HOSTS=['*'] 8 | PROJECT_NAME=cartoview 9 | DEFAULT_BACKEND_DATASTORE=datastore 10 | ASYNC_SIGNALS=True 11 | DJANGO_SETTINGS_MODULE=cartoview.settings 12 | DOCKER_ENV=production 13 | IS_CELERY=true 14 | C_FORCE_ROOT=1 15 | PYTHONUNBUFFERED=0 16 | BROKER_URL=amqp://guest:guest@rabbitmq:5672/ 17 | -------------------------------------------------------------------------------- /env/django.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgis://docker:docker@postgis:5432/cartoview 2 | DATASTORE_DATABASE_URL=postgis://docker:docker@postgis:5432/cartoview_datastore 3 | GEOSERVER_WEB_UI_LOCATION=http://10.5.0.4/geoserver/ 4 | GEOSERVER_PUBLIC_LOCATION=http://10.5.0.4/geoserver/ 5 | GEOSERVER_LOCATION=http://geoserver:8080/geoserver/ 6 | GEOSERVER_ADMIN_USER=admin 7 | GEOSERVER_ADMIN_PASSWORD=geoserver 8 | DEFAULT_BACKEND_UPLOADER=geonode.importer 9 | SITEURL=http://10.5.0.4/ 10 | NGINX_LOCATION=http://nginx:80/ 11 | DOCKER=True 12 | ALLOWED_HOSTS=['*'] 13 | PROJECT_NAME=cartoview 14 | DEFAULT_BACKEND_DATASTORE=datastore 15 | DEBUG=False 16 | -------------------------------------------------------------------------------- /env/postgis.env: -------------------------------------------------------------------------------- 1 | POSTGRES_DB=cartoview,cartoview_datastore,cartoview_geodatabase 2 | POSTGRES_USER=docker 3 | POSTGRES_PASS=docker 4 | ALLOW_IP_RANGE=0.0.0.0/0 5 | POSTGRES_MULTIPLE_EXTENSIONS=postgis 6 | 7 | GEONODE_DATABASE=cartoview 8 | GEONODE_DATABASE_PASSWORD=cartoview 9 | GEONODE_GEODATABASE=cartoview_datastore 10 | GEONODE_GEODATABASE_PASSWORD=cartoview_datastore 11 | GEONODE_DATABASE_SCHEMA=public 12 | GEONODE_GEODATABASE_SCHEMA=public 13 | -------------------------------------------------------------------------------- /env/tomcat.env: -------------------------------------------------------------------------------- 1 | DATABASE_HOST=postgis 2 | DATABASE_PORT=5432 3 | 4 | GEONODE_DATABASE=cartoview 5 | GEONODE_DATABASE_PASSWORD=cartoview 6 | GEONODE_GEODATABASE=cartoview_datastore 7 | GEONODE_GEODATABASE_PASSWORD=cartoview_datastore 8 | GEONODE_DATABASE_SCHEMA=public 9 | GEONODE_GEODATABASE_SCHEMA=public 10 | 11 | GEOSERVER_WEB_UI_LOCATION=http://10.5.0.4/geoserver/ 12 | GEOSERVER_PUBLIC_LOCATION=http://10.5.0.4/geoserver/ 13 | GEOSERVER_LOCATION=http://geoserver:8080/geoserver/ 14 | GEOSERVER_ADMIN_USER=admin 15 | GEOSERVER_ADMIN_PASSWORD=geoserver 16 | 17 | OGC_REQUEST_TIMEOUT=30 18 | OGC_REQUEST_MAX_RETRIES=1 19 | OGC_REQUEST_BACKOFF_FACTOR=0.3 20 | OGC_REQUEST_POOL_MAXSIZE=10 21 | OGC_REQUEST_POOL_CONNECTIONS=10 22 | 23 | # Java Options & Memory 24 | ENABLE_JSONP=true 25 | outFormat=text/javascript 26 | GEOSERVER_JAVA_OPTS=-Djava.awt.headless=true -Xms2G -Xmx4G -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:PerfDataSamplingInterval=500 -XX:SoftRefLRUPolicyMSPerMB=36000 -XX:-UseGCOverheadLimit -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -DALLOW_ENV_PARAMETRIZATION=true -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3-Unsafe.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine 27 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cartoview.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Cartoview 2 | site_url: https://cartoview.net 3 | repo_url: https://github.com/cartologic/cartoview.git 4 | edit_uri: /docs/ 5 | repo_name: Github 6 | site_author: Cartologic 7 | copyright: Cartologic 8 | 9 | nav: 10 | - About: index.md 11 | - Key Features: key-features.md 12 | - Demo: demo.md 13 | - Installation: 14 | - Ubuntu: installation/ubuntu.md 15 | - Windows: installation/windows.md 16 | - Docker: installation/docker.md 17 | - Vagrant: installation/vagrant.md 18 | - Cartoview Project: installation/cartoview-project.md 19 | - Windows Installer: installation/windows-installer.md 20 | - Install App: install-app.md 21 | - For Developers: for-developers.md 22 | - Upload App to GeoApp Market: upload-app.md 23 | - Contribute: contribute.md 24 | - Issues: issues.md 25 | - Frequently Asked Questions: FAQ.md 26 | theme: readthedocs 27 | 28 | extra_css: 29 | - css/custom.css 30 | 31 | markdown_extensions: 32 | - admonition -------------------------------------------------------------------------------- /scripts/database/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | psql -U postgres -c "drop database template_postgis" 5 | psql -U postgres -c "drop database cartoview" 6 | psql -U postgres -c "drop database cartoview_data" 7 | psql -U postgres -c "drop database upload_test" 8 | psql -U postgres -c "drop database test_upload_test" 9 | psql -U postgres -c "drop user cartoview" 10 | psql -U postgres -c "create user cartoview CREATEDB SUPERUSER" 11 | psql -U postgres -c "ALTER USER cartoview WITH PASSWORD 'cartoview';" 12 | psql -U postgres -c "create database template_postgis" 13 | psql -U postgres -d template_postgis -c 'CREATE EXTENSION postgis;' 14 | psql -U postgres -d template_postgis -c 'GRANT ALL ON geometry_columns TO PUBLIC;' 15 | psql -U postgres -d template_postgis -c 'GRANT ALL ON spatial_ref_sys TO PUBLIC;' 16 | psql -U postgres -d template_postgis -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO cartoview;' 17 | psql -U postgres -c "create database cartoview OWNER cartoview TEMPLATE template_postgis" 18 | psql -U postgres -c "create database cartoview_data OWNER cartoview TEMPLATE template_postgis" -------------------------------------------------------------------------------- /scripts/docker/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bash "strict mode", to help catch problems and bugs in the shell 4 | # script. Every bash script you write should include this. See 5 | # http://redsymbol.net/articles/unofficial-bash-strict-mode/ for 6 | # details. 7 | set -euo pipefail 8 | 9 | # Tell apt-get we're never going to be able to give manual 10 | # feedback: 11 | export DEBIAN_FRONTEND=noninteractive 12 | 13 | # Update the package listing, so we know what package exist: 14 | apt-get update 15 | 16 | # Install security updates: 17 | apt-get -y upgrade 18 | 19 | # Install wget and gnupg 20 | apt-get install wget gnupg -y 21 | 22 | # Enable postgresql-client-13 23 | echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list 24 | echo "deb http://deb.debian.org/debian/ stable main contrib non-free" | tee /etc/apt/sources.list.d/debian.list 25 | wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - 26 | 27 | # To get GDAL 3.2.1 to fix this issue https://github.com/OSGeo/gdal/issues/1692 28 | # TODO: The following line should be removed if base image upgraded to Bullseye 29 | echo "deb http://deb.debian.org/debian/ bullseye main contrib non-free" | tee /etc/apt/sources.list.d/debian.list 30 | 31 | # add gdal repo 32 | #echo "deb http://http.us.debian.org/debian buster main non-free contrib" >>/etc/apt/sources.list 33 | #add-apt-repository ppa:ubuntugis/ppa && apt-get update 34 | 35 | # This section is borrowed from the official Django image but adds GDAL and others 36 | apt-get update && apt-get install -y \ 37 | libgdal-dev libpq-dev libxml2-dev \ 38 | libxml2 libxslt1-dev zlib1g-dev libjpeg-dev \ 39 | libmemcached-dev libldap2-dev libsasl2-dev libffi-dev 40 | 41 | apt-get update && apt-get install -y \ 42 | gcc zip gettext geoip-bin cron \ 43 | postgresql-client-13 \ 44 | sqlite3 spatialite-bin libsqlite3-mod-spatialite \ 45 | python3-dev python3-gdal python3-psycopg2 python3-ldap \ 46 | python3-pip python3-pil python3-lxml python3-pylibmc \ 47 | uwsgi uwsgi-plugin-python3 \ 48 | firefox-esr \ 49 | --no-install-recommends && rm -rf /var/lib/apt/lists/* 50 | 51 | # Prepraing dependencies 52 | apt-get update && apt-get install -y devscripts build-essential debhelper pkg-kde-tools sharutils 53 | 54 | # Install pip packages 55 | pip install pip --upgrade \ 56 | && pip install pygdal==$(gdal-config --version).* flower==0.9.4 57 | 58 | # Activate "memcached" 59 | apt install -y memcached 60 | pip install pylibmc \ 61 | && pip install sherlock 62 | 63 | # install geonode from commit hash if dev enabled 64 | #if [ "$GEONODE_DEV" = true ]; then 65 | # git clone https://github.com/GeoNode/geonode.git && 66 | # cd ${APP_DIR}/geonode && pip install . && 67 | # rm -rf /geonode 68 | #fi 69 | 70 | # create required dirs 71 | mkdir -p ${APP_DIR} 72 | 73 | # install cartoview [this will install GeoNode as a dependancy] 74 | cd ${APP_DIR}/cartoview && pip install -e . # && rm -rf /cartoview 75 | 76 | # cleanup image 77 | rm -rf ~/.cache/pip 78 | rm -rf /root/.cache 79 | apt autoremove --purge -y && apt autoclean -y && apt-get clean -y 80 | rm -rf /var/lib/apt/lists/* && apt-get clean -y && 81 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 82 | echo "Yes, do as I say!" | apt-get remove --force-yes login && 83 | dpkg --remove --force-depends wget 84 | -------------------------------------------------------------------------------- /scripts/misc/jetty-runner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /geoserver 5 | 6 | 7 | 8 | /WEB-INF/web.xml 9 | false 10 | 11 | org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern 12 | WONTMATCH 13 | 14 | -------------------------------------------------------------------------------- /scripts/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user nginx; 2 | worker_processes 1; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | include /etc/nginx/mime.types; 13 | default_type application/octet-stream; 14 | 15 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 16 | '$status $body_bytes_sent "$http_referer" ' 17 | '"$http_user_agent" "$http_x_forwarded_for"'; 18 | 19 | access_log /var/log/nginx/access.log main; 20 | 21 | sendfile on; 22 | #tcp_nopush on; 23 | 24 | keepalive_timeout 65; 25 | 26 | gzip on; 27 | gzip_min_length 500; 28 | gzip_proxied expired no-cache no-store private auth; 29 | gzip_types *; 30 | gzip_comp_level 9; 31 | server { 32 | listen 80; 33 | server_name localhost; 34 | index index.html index.htm; 35 | root /usr/share/nginx/html; 36 | location / { 37 | client_max_body_size 1024M; 38 | client_body_buffer_size 1024K; 39 | proxy_read_timeout 100000; 40 | proxy_set_header Host $host; 41 | proxy_pass http://cartoview:8000; 42 | } 43 | location /geoserver { 44 | proxy_pass http://geoserver:8080; 45 | proxy_set_header Host $http_host; 46 | proxy_set_header X-Real-IP $remote_addr; 47 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 48 | proxy_set_header X-Forwarded-Proto $scheme; 49 | } 50 | location /static { 51 | alias /cartoview/static/; 52 | } 53 | location /uploaded { 54 | alias /cartoview/uploaded/; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | # This flag says that the code is written to work on both Python 2 and Python 3 | # 3. If at all possible, it is good practice to do this. If you cannot, you 4 | # will need to generate wheels for each Python version that you support. 5 | universal=1 6 | 7 | [flake8] 8 | max-line-length = 120 9 | exclude=cartoview/*/migrations/*,management,scripts,docs,static,migrations,cartoview/*settings.py,pavement.py,cartoview/apps/ 10 | ignore=E121,E122,E124,E126,E226 11 | 12 | [nosetests] 13 | process-timeout=300 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | from setuptools import find_packages 4 | 5 | long_description = open('README.md').read() 6 | setup( 7 | name='cartoview', 8 | packages=find_packages(), 9 | version=__import__('cartoview').get_current_version(), 10 | description='Cartoview is a GIS web mapping application framework to \ 11 | easily share and deploy apps based on Geonode', 12 | long_description=long_description, 13 | long_description_content_type='text/markdown', 14 | author='Cartologic', 15 | author_email='info@cartologic.com', 16 | url='https://github.com/cartologic/cartoview', 17 | include_package_data=True, 18 | keywords=[ 19 | 'cartoview', 'gis', 'geonode', "django", "web mapping", "applications", 20 | "apps", "application management" 21 | ], 22 | classifiers=[ 23 | "Development Status :: 4 - Beta", "Framework :: Django :: 1.8", 24 | "Topic :: Scientific/Engineering :: GIS" 25 | ], 26 | license="BSD", 27 | install_requires=[ 28 | 'future', 'geonode==4.0.0rc0', 29 | 'Faker>=0.8.4', 30 | 'cherrypy==18.6.1', 31 | 'portalocker==1.3.0' 32 | ]) 33 | --------------------------------------------------------------------------------