igs-slm 0.1.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
- igs_slm-0.1.0b0.dist-info/METADATA +151 -0
- igs_slm-0.1.0b0.dist-info/RECORD +447 -0
- igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
- igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
- igs_tools/__init__.py +0 -0
- igs_tools/connection.py +88 -0
- igs_tools/defines/__init__.py +8 -0
- igs_tools/defines/constellation.py +21 -0
- igs_tools/defines/data_center.py +75 -0
- igs_tools/defines/rinex.py +49 -0
- igs_tools/directory.py +247 -0
- igs_tools/utils.py +66 -0
- slm/__init__.py +21 -0
- slm/admin.py +674 -0
- slm/api/edit/__init__.py +0 -0
- slm/api/edit/serializers.py +316 -0
- slm/api/edit/views.py +1632 -0
- slm/api/fields.py +89 -0
- slm/api/filter.py +504 -0
- slm/api/pagination.py +55 -0
- slm/api/permissions.py +65 -0
- slm/api/public/__init__.py +0 -0
- slm/api/public/serializers.py +249 -0
- slm/api/public/views.py +606 -0
- slm/api/serializers.py +132 -0
- slm/api/views.py +148 -0
- slm/apps.py +323 -0
- slm/authentication.py +198 -0
- slm/bin/__init__.py +0 -0
- slm/bin/startproject.py +262 -0
- slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
- slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
- slm/defines/AlertLevel.py +24 -0
- slm/defines/AntennaCalibration.py +25 -0
- slm/defines/AntennaFeatures.py +27 -0
- slm/defines/AntennaReferencePoint.py +22 -0
- slm/defines/Aspiration.py +13 -0
- slm/defines/CardinalDirection.py +19 -0
- slm/defines/CollocationStatus.py +12 -0
- slm/defines/EquipmentState.py +22 -0
- slm/defines/FlagSeverity.py +14 -0
- slm/defines/FractureSpacing.py +15 -0
- slm/defines/FrequencyStandardType.py +15 -0
- slm/defines/GeodesyMLVersion.py +48 -0
- slm/defines/ISOCountry.py +1194 -0
- slm/defines/Instrumentation.py +19 -0
- slm/defines/LogEntryType.py +30 -0
- slm/defines/SLMFileType.py +18 -0
- slm/defines/SiteFileUploadStatus.py +61 -0
- slm/defines/SiteLogFormat.py +49 -0
- slm/defines/SiteLogStatus.py +78 -0
- slm/defines/TectonicPlates.py +28 -0
- slm/defines/__init__.py +46 -0
- slm/forms.py +1126 -0
- slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
- slm/jinja2/slm/sitelog/legacy.log +346 -0
- slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
- slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
- slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
- slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
- slm/management/__init__.py +0 -0
- slm/management/commands/__init__.py +53 -0
- slm/management/commands/build_index.py +96 -0
- slm/management/commands/generate_sinex.py +675 -0
- slm/management/commands/head_from_index.py +541 -0
- slm/management/commands/import_archive.py +908 -0
- slm/management/commands/import_equipment.py +351 -0
- slm/management/commands/set_site.py +56 -0
- slm/management/commands/sitelog.py +144 -0
- slm/management/commands/synchronize.py +60 -0
- slm/management/commands/update_data_availability.py +167 -0
- slm/management/commands/validate_db.py +186 -0
- slm/management/commands/validate_gml.py +73 -0
- slm/map/__init__.py +1 -0
- slm/map/admin.py +5 -0
- slm/map/api/__init__.py +0 -0
- slm/map/api/edit/__init__.py +0 -0
- slm/map/api/edit/serializers.py +28 -0
- slm/map/api/edit/views.py +46 -0
- slm/map/api/public/__init__.py +0 -0
- slm/map/api/public/serializers.py +29 -0
- slm/map/api/public/views.py +64 -0
- slm/map/apps.py +7 -0
- slm/map/defines.py +53 -0
- slm/map/migrations/0001_initial.py +115 -0
- slm/map/migrations/__init__.py +0 -0
- slm/map/models.py +63 -0
- slm/map/static/slm/css/map.css +86 -0
- slm/map/static/slm/js/map.js +159 -0
- slm/map/templates/slm/map.html +374 -0
- slm/map/templates/slm/station/base.html +11 -0
- slm/map/templates/slm/station/edit.html +10 -0
- slm/map/templates/slm/top_nav.html +17 -0
- slm/map/templatetags/__init__.py +0 -0
- slm/map/templatetags/slm_map.py +18 -0
- slm/map/urls.py +25 -0
- slm/map/views.py +36 -0
- slm/middleware.py +29 -0
- slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
- slm/migrations/0001_initial.py +4826 -0
- slm/migrations/0002_alter_dataavailability_site.py +22 -0
- slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
- slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
- slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
- slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
- slm/migrations/0007_alter_dataavailability_rate.py +23 -0
- slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
- slm/migrations/0009_alter_archiveindex_end.py +21 -0
- slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
- slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
- slm/migrations/0012_alter_logentry_type.py +36 -0
- slm/migrations/0013_unpublishedfilesalert.py +48 -0
- slm/migrations/0014_sitelogpublished.py +48 -0
- slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
- slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
- slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
- slm/migrations/0018_afix_deleted.py +34 -0
- slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
- slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
- slm/migrations/0020_alter_manufacturer_options.py +16 -0
- slm/migrations/0021_alter_siteform_report_type.py +23 -0
- slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
- slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
- slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
- slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
- slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
- slm/migrations/0029_manufacturer_full_name.py +17 -0
- slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
- slm/migrations/__init__.py +0 -0
- slm/migrations/load_satellitesystems.py +27 -0
- slm/models/__init__.py +118 -0
- slm/models/about.py +14 -0
- slm/models/alerts.py +1204 -0
- slm/models/data.py +58 -0
- slm/models/equipment.py +229 -0
- slm/models/help.py +14 -0
- slm/models/index.py +428 -0
- slm/models/sitelog.py +4279 -0
- slm/models/system.py +723 -0
- slm/models/user.py +304 -0
- slm/parsing/__init__.py +786 -0
- slm/parsing/legacy/__init__.py +4 -0
- slm/parsing/legacy/binding.py +817 -0
- slm/parsing/legacy/parser.py +377 -0
- slm/parsing/xsd/__init__.py +34 -0
- slm/parsing/xsd/binding.py +86 -0
- slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
- slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
- slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
- slm/parsing/xsd/parser.py +116 -0
- slm/parsing/xsd/resolver.py +28 -0
- slm/receivers/__init__.py +11 -0
- slm/receivers/alerts.py +87 -0
- slm/receivers/cleanup.py +41 -0
- slm/receivers/event_loggers.py +175 -0
- slm/receivers/index.py +67 -0
- slm/settings/__init__.py +55 -0
- slm/settings/auth.py +15 -0
- slm/settings/ckeditor.py +14 -0
- slm/settings/debug.py +47 -0
- slm/settings/internationalization.py +12 -0
- slm/settings/logging.py +113 -0
- slm/settings/platform/__init__.py +0 -0
- slm/settings/platform/darwin.py +10 -0
- slm/settings/rest.py +21 -0
- slm/settings/root.py +152 -0
- slm/settings/routines.py +43 -0
- slm/settings/secrets.py +37 -0
- slm/settings/security.py +5 -0
- slm/settings/slm.py +188 -0
- slm/settings/static_templates.py +53 -0
- slm/settings/templates.py +29 -0
- slm/settings/uploads.py +8 -0
- slm/settings/urls.py +126 -0
- slm/settings/validation.py +196 -0
- slm/signals.py +250 -0
- slm/singleton.py +49 -0
- slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
- slm/static/rest_framework/css/bootstrap.min.css +7 -0
- slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
- slm/static/rest_framework/css/default.css +82 -0
- slm/static/rest_framework/css/prettify.css +30 -0
- slm/static/rest_framework/docs/css/base.css +344 -0
- slm/static/rest_framework/docs/css/highlight.css +125 -0
- slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
- slm/static/rest_framework/docs/img/favicon.ico +0 -0
- slm/static/rest_framework/docs/img/grid.png +0 -0
- slm/static/rest_framework/docs/js/api.js +321 -0
- slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
- slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
- slm/static/rest_framework/img/grid.png +0 -0
- slm/static/rest_framework/js/ajax-form.js +127 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
- slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
- slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
- slm/static/rest_framework/js/csrf.js +52 -0
- slm/static/rest_framework/js/default.js +47 -0
- slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
- slm/static/rest_framework/js/prettify-min.js +28 -0
- slm/static/slm/css/admin.css +3 -0
- slm/static/slm/css/defines.css +82 -0
- slm/static/slm/css/forms.css +1 -0
- slm/static/slm/css/style.css +1004 -0
- slm/static/slm/img/email-branding.png +0 -0
- slm/static/slm/img/favicon.ico +0 -0
- slm/static/slm/img/login-bg.jpg +0 -0
- slm/static/slm/img/slm-logo.svg +4 -0
- slm/static/slm/js/autocomplete.js +341 -0
- slm/static/slm/js/enums.js +322 -0
- slm/static/slm/js/fileIcons.js +30 -0
- slm/static/slm/js/form.js +404 -0
- slm/static/slm/js/formWidget.js +23 -0
- slm/static/slm/js/persistable.js +33 -0
- slm/static/slm/js/slm.js +1028 -0
- slm/static/slm/js/time24.js +212 -0
- slm/static_templates/slm/css/defines.css +26 -0
- slm/static_templates/slm/js/enums.js +28 -0
- slm/static_templates/slm/js/fileIcons.js +16 -0
- slm/static_templates/slm/js/urls.js +5 -0
- slm/templates/account/base.html +20 -0
- slm/templates/account/email/base.html +43 -0
- slm/templates/account/email/base_message.txt +7 -0
- slm/templates/account/email/email_confirmation_message.html +16 -0
- slm/templates/account/email/email_confirmation_message.txt +7 -0
- slm/templates/account/email/email_confirmation_signup_message.html +1 -0
- slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
- slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
- slm/templates/account/email/email_confirmation_subject.txt +4 -0
- slm/templates/account/email/password_reset_key_message.html +28 -0
- slm/templates/account/email/password_reset_key_message.txt +9 -0
- slm/templates/account/email/password_reset_key_subject.txt +4 -0
- slm/templates/account/email/unknown_account_message.html +25 -0
- slm/templates/account/email/unknown_account_message.txt +12 -0
- slm/templates/account/email/unknown_account_subject.txt +4 -0
- slm/templates/account/login.html +67 -0
- slm/templates/account/logout.html +38 -0
- slm/templates/account/password_change.html +48 -0
- slm/templates/account/password_reset.html +51 -0
- slm/templates/account/password_reset_done.html +20 -0
- slm/templates/account/password_reset_from_key.html +52 -0
- slm/templates/account/password_reset_from_key_done.html +17 -0
- slm/templates/admin/base.html +7 -0
- slm/templates/messages.html +8 -0
- slm/templates/rest_framework/README +16 -0
- slm/templates/rest_framework/admin/detail.html +10 -0
- slm/templates/rest_framework/admin/dict_value.html +11 -0
- slm/templates/rest_framework/admin/list.html +32 -0
- slm/templates/rest_framework/admin/list_value.html +11 -0
- slm/templates/rest_framework/admin/simple_list_value.html +2 -0
- slm/templates/rest_framework/admin.html +282 -0
- slm/templates/rest_framework/api.html +3 -0
- slm/templates/rest_framework/base.html +334 -0
- slm/templates/rest_framework/docs/auth/basic.html +42 -0
- slm/templates/rest_framework/docs/auth/session.html +40 -0
- slm/templates/rest_framework/docs/auth/token.html +41 -0
- slm/templates/rest_framework/docs/document.html +37 -0
- slm/templates/rest_framework/docs/error.html +71 -0
- slm/templates/rest_framework/docs/index.html +55 -0
- slm/templates/rest_framework/docs/interact.html +57 -0
- slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
- slm/templates/rest_framework/docs/langs/javascript.html +15 -0
- slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/python.html +13 -0
- slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/shell.html +6 -0
- slm/templates/rest_framework/docs/link.html +113 -0
- slm/templates/rest_framework/docs/sidebar.html +78 -0
- slm/templates/rest_framework/filters/base.html +16 -0
- slm/templates/rest_framework/filters/ordering.html +17 -0
- slm/templates/rest_framework/filters/search.html +13 -0
- slm/templates/rest_framework/horizontal/checkbox.html +23 -0
- slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
- slm/templates/rest_framework/horizontal/dict_field.html +11 -0
- slm/templates/rest_framework/horizontal/fieldset.html +16 -0
- slm/templates/rest_framework/horizontal/form.html +6 -0
- slm/templates/rest_framework/horizontal/input.html +21 -0
- slm/templates/rest_framework/horizontal/list_field.html +11 -0
- slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
- slm/templates/rest_framework/horizontal/radio.html +42 -0
- slm/templates/rest_framework/horizontal/select.html +36 -0
- slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
- slm/templates/rest_framework/horizontal/textarea.html +21 -0
- slm/templates/rest_framework/inline/checkbox.html +8 -0
- slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
- slm/templates/rest_framework/inline/dict_field.html +9 -0
- slm/templates/rest_framework/inline/fieldset.html +6 -0
- slm/templates/rest_framework/inline/form.html +8 -0
- slm/templates/rest_framework/inline/input.html +9 -0
- slm/templates/rest_framework/inline/list_field.html +9 -0
- slm/templates/rest_framework/inline/list_fieldset.html +3 -0
- slm/templates/rest_framework/inline/radio.html +25 -0
- slm/templates/rest_framework/inline/select.html +24 -0
- slm/templates/rest_framework/inline/select_multiple.html +25 -0
- slm/templates/rest_framework/inline/textarea.html +9 -0
- slm/templates/rest_framework/login.html +3 -0
- slm/templates/rest_framework/login_base.html +65 -0
- slm/templates/rest_framework/pagination/numbers.html +47 -0
- slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
- slm/templates/rest_framework/raw_data_form.html +11 -0
- slm/templates/rest_framework/schema.js +3 -0
- slm/templates/rest_framework/vertical/checkbox.html +16 -0
- slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
- slm/templates/rest_framework/vertical/dict_field.html +7 -0
- slm/templates/rest_framework/vertical/fieldset.html +13 -0
- slm/templates/rest_framework/vertical/form.html +6 -0
- slm/templates/rest_framework/vertical/input.html +17 -0
- slm/templates/rest_framework/vertical/list_field.html +7 -0
- slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
- slm/templates/rest_framework/vertical/radio.html +40 -0
- slm/templates/rest_framework/vertical/select.html +34 -0
- slm/templates/rest_framework/vertical/select_multiple.html +31 -0
- slm/templates/rest_framework/vertical/textarea.html +17 -0
- slm/templates/slm/about.html +21 -0
- slm/templates/slm/alerts/alert.html +15 -0
- slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
- slm/templates/slm/alerts/importalert.html +10 -0
- slm/templates/slm/alerts.html +18 -0
- slm/templates/slm/auth_menu.html +41 -0
- slm/templates/slm/base.html +195 -0
- slm/templates/slm/emails/alert_issued.html +31 -0
- slm/templates/slm/emails/alert_issued.txt +9 -0
- slm/templates/slm/emails/base.html +6 -0
- slm/templates/slm/emails/changes_rejected.txt +7 -0
- slm/templates/slm/emails/review_requested.txt +7 -0
- slm/templates/slm/forms/widgets/auto_complete.html +21 -0
- slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
- slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
- slm/templates/slm/forms/widgets/inline_multi.html +1 -0
- slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
- slm/templates/slm/forms/widgets/time24.html +37 -0
- slm/templates/slm/help.html +54 -0
- slm/templates/slm/messages.html +13 -0
- slm/templates/slm/new_site.html +88 -0
- slm/templates/slm/profile.html +57 -0
- slm/templates/slm/register.html +40 -0
- slm/templates/slm/reports/file_log.html +43 -0
- slm/templates/slm/reports/head_log.html +23 -0
- slm/templates/slm/reports/head_report.html +55 -0
- slm/templates/slm/reports/index_log.html +23 -0
- slm/templates/slm/reports/index_report.html +71 -0
- slm/templates/slm/station/alert.html +8 -0
- slm/templates/slm/station/alerts.html +19 -0
- slm/templates/slm/station/base.html +104 -0
- slm/templates/slm/station/download.html +87 -0
- slm/templates/slm/station/edit.html +283 -0
- slm/templates/slm/station/form.html +110 -0
- slm/templates/slm/station/log.html +18 -0
- slm/templates/slm/station/review.html +461 -0
- slm/templates/slm/station/upload.html +295 -0
- slm/templates/slm/station/uploads/attachment.html +20 -0
- slm/templates/slm/station/uploads/geodesyml.html +1 -0
- slm/templates/slm/station/uploads/image.html +27 -0
- slm/templates/slm/station/uploads/json.html +0 -0
- slm/templates/slm/station/uploads/legacy.html +77 -0
- slm/templates/slm/top_nav.html +14 -0
- slm/templates/slm/user_activity.html +16 -0
- slm/templates/slm/widgets/alert_scroll.html +135 -0
- slm/templates/slm/widgets/filelist.html +258 -0
- slm/templates/slm/widgets/legend.html +12 -0
- slm/templates/slm/widgets/log_scroll.html +88 -0
- slm/templates/slm/widgets/stationlist.html +233 -0
- slm/templatetags/__init__.py +0 -0
- slm/templatetags/jinja2.py +9 -0
- slm/templatetags/slm.py +459 -0
- slm/urls.py +148 -0
- slm/utils.py +299 -0
- slm/validators.py +297 -0
- slm/views.py +654 -0
- slm/widgets.py +134 -0
slm/views.py
ADDED
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Handles web requests and responses.
|
|
3
|
+
|
|
4
|
+
NOTES:
|
|
5
|
+
Holds important functions for each page.
|
|
6
|
+
Data processing, validation, etc. lives here.
|
|
7
|
+
|
|
8
|
+
ADD MORE COMMENTS
|
|
9
|
+
|
|
10
|
+
MORE INFO:
|
|
11
|
+
https://docs.djangoproject.com/en/stable/topics/http/views/
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from enum import Enum
|
|
15
|
+
|
|
16
|
+
from django.conf import settings
|
|
17
|
+
from django.contrib.auth import get_user_model
|
|
18
|
+
from django.contrib.auth.decorators import login_required
|
|
19
|
+
from django.core.exceptions import PermissionDenied
|
|
20
|
+
from django.db.models import Max, Q
|
|
21
|
+
from django.db.models.fields import NOT_PROVIDED
|
|
22
|
+
from django.http import Http404, HttpResponseNotFound
|
|
23
|
+
from django.template.exceptions import TemplateDoesNotExist
|
|
24
|
+
from django.template.loader import get_template
|
|
25
|
+
from django.utils.decorators import method_decorator
|
|
26
|
+
from django.views.generic import TemplateView
|
|
27
|
+
|
|
28
|
+
from slm import defines
|
|
29
|
+
from slm.api.edit.views import StationFilterForm
|
|
30
|
+
from slm.defines import (
|
|
31
|
+
AlertLevel,
|
|
32
|
+
SiteFileUploadStatus,
|
|
33
|
+
SiteLogFormat,
|
|
34
|
+
SiteLogStatus,
|
|
35
|
+
SLMFileType,
|
|
36
|
+
)
|
|
37
|
+
from slm.forms import (
|
|
38
|
+
NewSiteForm,
|
|
39
|
+
RichTextForm,
|
|
40
|
+
SiteAntennaForm,
|
|
41
|
+
SiteCollocationForm,
|
|
42
|
+
SiteFileForm,
|
|
43
|
+
SiteFormForm,
|
|
44
|
+
SiteFrequencyStandardForm,
|
|
45
|
+
SiteHumiditySensorForm,
|
|
46
|
+
SiteIdentificationForm,
|
|
47
|
+
SiteLocalEpisodicEffectsForm,
|
|
48
|
+
SiteLocationForm,
|
|
49
|
+
SiteMoreInformationForm,
|
|
50
|
+
SiteMultiPathSourcesForm,
|
|
51
|
+
SiteOperationalContactForm,
|
|
52
|
+
SiteOtherInstrumentationForm,
|
|
53
|
+
SitePressureSensorForm,
|
|
54
|
+
SiteRadioInterferencesForm,
|
|
55
|
+
SiteReceiverForm,
|
|
56
|
+
SiteResponsibleAgencyForm,
|
|
57
|
+
SiteSignalObstructionsForm,
|
|
58
|
+
SiteSurveyedLocalTiesForm,
|
|
59
|
+
SiteTemperatureSensorForm,
|
|
60
|
+
SiteWaterVaporRadiometerForm,
|
|
61
|
+
UserForm,
|
|
62
|
+
UserProfileForm,
|
|
63
|
+
)
|
|
64
|
+
from slm.models import (
|
|
65
|
+
About,
|
|
66
|
+
Agency,
|
|
67
|
+
Alert,
|
|
68
|
+
ArchivedSiteLog,
|
|
69
|
+
Help,
|
|
70
|
+
Network,
|
|
71
|
+
Site,
|
|
72
|
+
SiteFileUpload,
|
|
73
|
+
SiteLocation,
|
|
74
|
+
SiteSubSection,
|
|
75
|
+
)
|
|
76
|
+
from slm.parsing import Error, Warn
|
|
77
|
+
|
|
78
|
+
User = get_user_model()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@method_decorator(login_required, name="dispatch")
|
|
82
|
+
class SLMView(TemplateView):
|
|
83
|
+
DEFINES = {
|
|
84
|
+
name: define
|
|
85
|
+
for name, define in vars(defines).items()
|
|
86
|
+
if isinstance(define, type) and issubclass(define, Enum)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
def get_context_data(self, **kwargs):
|
|
90
|
+
context = super().get_context_data(**kwargs)
|
|
91
|
+
context.update(self.DEFINES)
|
|
92
|
+
Alert.objects.all().delete_expired()
|
|
93
|
+
max_alert = Alert.objects.visible_to(self.request.user).aggregate(Max("level"))[
|
|
94
|
+
"level__max"
|
|
95
|
+
]
|
|
96
|
+
if max_alert is NOT_PROVIDED:
|
|
97
|
+
max_alert = None
|
|
98
|
+
|
|
99
|
+
context["user"] = self.request.user
|
|
100
|
+
context["alert_level"] = AlertLevel(max_alert) if max_alert else None
|
|
101
|
+
|
|
102
|
+
context["SLM_ORG_NAME"] = getattr(settings, "SLM_ORG_NAME", None)
|
|
103
|
+
context["is_moderator"] = (
|
|
104
|
+
self.request.user.is_superuser if self.request.user else None
|
|
105
|
+
)
|
|
106
|
+
context["networks"] = Network.objects.all()
|
|
107
|
+
if self.request.user.is_superuser:
|
|
108
|
+
context["user_agencies"] = Agency.objects.all()
|
|
109
|
+
else:
|
|
110
|
+
context["user_agencies"] = self.request.user.agencies.all()
|
|
111
|
+
return context
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class StationContextView(SLMView):
|
|
115
|
+
station = None
|
|
116
|
+
agencies = None
|
|
117
|
+
sites = None
|
|
118
|
+
site = None
|
|
119
|
+
|
|
120
|
+
@method_decorator(login_required)
|
|
121
|
+
def dispatch(self, request, *args, **kwargs):
|
|
122
|
+
return super().dispatch(request, *args, **kwargs)
|
|
123
|
+
|
|
124
|
+
def get_context_data(self, **kwargs):
|
|
125
|
+
context = super().get_context_data(**kwargs)
|
|
126
|
+
self.station = kwargs.get("station", None)
|
|
127
|
+
self.sites = Site.objects.editable_by(self.request.user)
|
|
128
|
+
self.site = (
|
|
129
|
+
Site.objects.filter(name__iexact=self.station)
|
|
130
|
+
.editable_by(self.request.user)
|
|
131
|
+
.first()
|
|
132
|
+
)
|
|
133
|
+
initial = None
|
|
134
|
+
if self.request.GET:
|
|
135
|
+
station_filter = StationFilterForm(data=self.request.GET)
|
|
136
|
+
station_filter.full_clean()
|
|
137
|
+
if station_filter.errors:
|
|
138
|
+
raise Http404(station_filter.errors)
|
|
139
|
+
initial = station_filter.cleaned_data
|
|
140
|
+
filter_form = StationFilterForm(initial=initial)
|
|
141
|
+
if self.site:
|
|
142
|
+
self.agencies = [agency for agency in self.site.agencies.all()]
|
|
143
|
+
location = SiteLocation.objects.filter(site=self.site).head()
|
|
144
|
+
if location and location.llh:
|
|
145
|
+
context["station_position"] = (location.llh[0], location.llh[1])
|
|
146
|
+
context["attn_files"] = (
|
|
147
|
+
self.site.sitefileuploads.available_to(self.request.user)
|
|
148
|
+
.filter(status=SiteFileUploadStatus.UNPUBLISHED)
|
|
149
|
+
.count()
|
|
150
|
+
)
|
|
151
|
+
else:
|
|
152
|
+
self.agencies = filter_form.initial.get("agency", [])
|
|
153
|
+
|
|
154
|
+
max_alert = (
|
|
155
|
+
Alert.objects.visible_to(self.request.user)
|
|
156
|
+
.for_site(self.site)
|
|
157
|
+
.aggregate(Max("level"))["level__max"]
|
|
158
|
+
)
|
|
159
|
+
if max_alert is NOT_PROVIDED:
|
|
160
|
+
max_alert = None
|
|
161
|
+
|
|
162
|
+
context.update(
|
|
163
|
+
{
|
|
164
|
+
"num_sites": self.sites.count(),
|
|
165
|
+
"station": self.station if self.station else None,
|
|
166
|
+
"site": self.site if self.site else None,
|
|
167
|
+
"agencies": self.agencies,
|
|
168
|
+
"is_moderator": (
|
|
169
|
+
self.site.is_moderator(self.request.user) if self.site else None
|
|
170
|
+
),
|
|
171
|
+
# some non-moderators may be able to publish a some changes
|
|
172
|
+
"can_publish": (
|
|
173
|
+
self.site.can_publish(self.request.user) if self.site else None
|
|
174
|
+
),
|
|
175
|
+
"is_publishable": self.site.is_publishable() if self.site else None,
|
|
176
|
+
"link_view": (
|
|
177
|
+
"slm:edit"
|
|
178
|
+
if self.request.resolver_match.view_name
|
|
179
|
+
not in {
|
|
180
|
+
"slm:alerts",
|
|
181
|
+
"slm:download",
|
|
182
|
+
"slm:review",
|
|
183
|
+
"slm:log",
|
|
184
|
+
"slm:edit",
|
|
185
|
+
}
|
|
186
|
+
else self.request.resolver_match.view_name
|
|
187
|
+
),
|
|
188
|
+
"station_alert_level": (AlertLevel(max_alert) if max_alert else None),
|
|
189
|
+
"site_alerts": Alert.objects.site_alerts(),
|
|
190
|
+
"filter_form": filter_form,
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
if self.station:
|
|
195
|
+
try:
|
|
196
|
+
self.station = Site.objects.get(name=context["station"])
|
|
197
|
+
if (
|
|
198
|
+
not self.request.user.is_superuser
|
|
199
|
+
and self.station not in self.sites
|
|
200
|
+
):
|
|
201
|
+
raise PermissionDenied()
|
|
202
|
+
except Site.DoesNotExist:
|
|
203
|
+
raise Http404(f'Site {context["station"]} was not found!')
|
|
204
|
+
return context
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class EditView(StationContextView):
|
|
208
|
+
"""
|
|
209
|
+
This is the view that creates and renders a context when a user requests
|
|
210
|
+
to edit a site log. Site log edit forms do not render a giant form for the
|
|
211
|
+
entire site log. The specific section being edited is part of the request
|
|
212
|
+
url. So the job of this view is to compile enough context to render the
|
|
213
|
+
status and error information for all sections as well as all of the
|
|
214
|
+
information required to edit the requested section.
|
|
215
|
+
"""
|
|
216
|
+
|
|
217
|
+
template_name = "slm/station/edit.html"
|
|
218
|
+
|
|
219
|
+
FORMS = {
|
|
220
|
+
form.Meta.model.section_slug(): form
|
|
221
|
+
for form in [
|
|
222
|
+
SiteFormForm,
|
|
223
|
+
SiteIdentificationForm,
|
|
224
|
+
SiteLocationForm,
|
|
225
|
+
SiteReceiverForm,
|
|
226
|
+
SiteAntennaForm,
|
|
227
|
+
SiteSurveyedLocalTiesForm,
|
|
228
|
+
SiteFrequencyStandardForm,
|
|
229
|
+
SiteCollocationForm,
|
|
230
|
+
SiteHumiditySensorForm,
|
|
231
|
+
SitePressureSensorForm,
|
|
232
|
+
SiteTemperatureSensorForm,
|
|
233
|
+
SiteWaterVaporRadiometerForm,
|
|
234
|
+
SiteOtherInstrumentationForm,
|
|
235
|
+
SiteRadioInterferencesForm,
|
|
236
|
+
SiteMultiPathSourcesForm,
|
|
237
|
+
SiteSignalObstructionsForm,
|
|
238
|
+
SiteLocalEpisodicEffectsForm,
|
|
239
|
+
SiteOperationalContactForm,
|
|
240
|
+
SiteResponsibleAgencyForm,
|
|
241
|
+
SiteMoreInformationForm,
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
def get_context_data(self, **kwargs):
|
|
246
|
+
"""
|
|
247
|
+
Builds a context that contains the sections and their meta information
|
|
248
|
+
as well as forms bound ot the site log data at head for the section
|
|
249
|
+
being edited. The context dictionary includes all StationContextView
|
|
250
|
+
context as well as:
|
|
251
|
+
|
|
252
|
+
..code-block::
|
|
253
|
+
|
|
254
|
+
# forms contains the information needed to render the forms in the
|
|
255
|
+
# central edit pane
|
|
256
|
+
'forms': [...], # bound form instances to section models at head
|
|
257
|
+
# for the section being edited. If the section
|
|
258
|
+
# does not allow subsections it will be a list of
|
|
259
|
+
# length 1, if it does allow subections, it will
|
|
260
|
+
# be a list of bound subsection forms and the
|
|
261
|
+
# first instance in the list will be an unbound
|
|
262
|
+
# form used to add new subsections
|
|
263
|
+
|
|
264
|
+
'multi': True, # True if the section being edited has subsections
|
|
265
|
+
'section_id': str, # The identifier of the section being edited
|
|
266
|
+
'section_name': str, # The display name of the section
|
|
267
|
+
|
|
268
|
+
# dictionary of sections in render-order - keys are section_names
|
|
269
|
+
# this dictionary contains the meta information needed to render
|
|
270
|
+
# the navigation
|
|
271
|
+
'sections': {
|
|
272
|
+
'Section Name': {
|
|
273
|
+
'flags': int, # the cumulative number of error flags on
|
|
274
|
+
# this section
|
|
275
|
+
'id': str, # section_id
|
|
276
|
+
|
|
277
|
+
# the SiteLogStatus of the section
|
|
278
|
+
'status': SiteLogStatus
|
|
279
|
+
|
|
280
|
+
'subsections': {
|
|
281
|
+
'Subsection Name': {
|
|
282
|
+
'active': False, # True if subsection is selected
|
|
283
|
+
'flags': # the number of error flags the subsection
|
|
284
|
+
'id': str, # section_id
|
|
285
|
+
|
|
286
|
+
# the SiteLogStatus of the section
|
|
287
|
+
'status': SiteLogStatus
|
|
288
|
+
},
|
|
289
|
+
...
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
...
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
"""
|
|
296
|
+
context = super().get_context_data(**kwargs)
|
|
297
|
+
if not self.site:
|
|
298
|
+
raise Http404(f'Station {kwargs.get("station", "")} does not exist!')
|
|
299
|
+
context.update(
|
|
300
|
+
{
|
|
301
|
+
"section_id": kwargs.get("section", None),
|
|
302
|
+
"sections": {},
|
|
303
|
+
"forms": [],
|
|
304
|
+
"station_images": self.site.sitefileuploads.available_to(
|
|
305
|
+
self.request.user
|
|
306
|
+
).filter(
|
|
307
|
+
status=SiteFileUploadStatus.PUBLISHED,
|
|
308
|
+
file_type=SLMFileType.SITE_IMAGE,
|
|
309
|
+
),
|
|
310
|
+
"station_attachments": self.site.sitefileuploads.available_to(
|
|
311
|
+
self.request.user
|
|
312
|
+
).filter(
|
|
313
|
+
status=SiteFileUploadStatus.PUBLISHED,
|
|
314
|
+
file_type=SLMFileType.ATTACHMENT,
|
|
315
|
+
),
|
|
316
|
+
}
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
section = self.FORMS.get(kwargs.get("section", None), None)
|
|
320
|
+
if section:
|
|
321
|
+
context["section_name"] = section.section_name()
|
|
322
|
+
context["multi"] = issubclass(section._meta.model, SiteSubSection)
|
|
323
|
+
|
|
324
|
+
# create the context of our form tree - the form/edit templates are
|
|
325
|
+
# responsible for rendering this structure in html
|
|
326
|
+
for section_id, form in self.FORMS.items():
|
|
327
|
+
if hasattr(form, "NAV_HEADING"):
|
|
328
|
+
context["sections"].setdefault(
|
|
329
|
+
form.NAV_HEADING,
|
|
330
|
+
{
|
|
331
|
+
"id": form.group_name(),
|
|
332
|
+
"flags": 0,
|
|
333
|
+
"status": SiteLogStatus.EMPTY,
|
|
334
|
+
"active": False,
|
|
335
|
+
"subsections": {},
|
|
336
|
+
},
|
|
337
|
+
)["subsections"][form.section_name()] = {
|
|
338
|
+
"id": form.section_name().lower().replace(" ", ""),
|
|
339
|
+
"group": form.group_name(), # todo remove
|
|
340
|
+
"parent": form.group_name(),
|
|
341
|
+
"flags": 0,
|
|
342
|
+
"active": False,
|
|
343
|
+
"status": SiteLogStatus.EMPTY,
|
|
344
|
+
}
|
|
345
|
+
if section is form:
|
|
346
|
+
context["parent"] = form.group_name()
|
|
347
|
+
|
|
348
|
+
else:
|
|
349
|
+
context["sections"][form.section_name()] = {
|
|
350
|
+
"id": form.section_name().lower().replace(" ", ""),
|
|
351
|
+
"flags": 0,
|
|
352
|
+
"status": SiteLogStatus.EMPTY,
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if issubclass(form._meta.model, SiteSubSection):
|
|
356
|
+
# for subsections we need to:
|
|
357
|
+
# 1) set nav heading meta information
|
|
358
|
+
# 2) add sections for all children
|
|
359
|
+
# 3) populate the subsections of the requested edit form
|
|
360
|
+
|
|
361
|
+
heading = context["sections"][
|
|
362
|
+
getattr(form, "NAV_HEADING", form.section_name())
|
|
363
|
+
]
|
|
364
|
+
subheading = None
|
|
365
|
+
if hasattr(form, "NAV_HEADING"):
|
|
366
|
+
subheading = heading["subsections"][form.section_name()]
|
|
367
|
+
|
|
368
|
+
for inst in (
|
|
369
|
+
form._meta.model.objects.station(self.station)
|
|
370
|
+
.head(include_deleted=True)
|
|
371
|
+
.sort(reverse=True)
|
|
372
|
+
):
|
|
373
|
+
if section is form:
|
|
374
|
+
# if this is our requested form for editing - populate
|
|
375
|
+
# it with data from head
|
|
376
|
+
context["forms"].append(
|
|
377
|
+
form(
|
|
378
|
+
instance=inst,
|
|
379
|
+
initial={
|
|
380
|
+
field: getattr(inst, field)
|
|
381
|
+
for field in form._meta.fields
|
|
382
|
+
},
|
|
383
|
+
)
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
heading["flags"] += inst.num_flags if inst else 0
|
|
387
|
+
heading["status"] = heading.get("status", inst.mod_status).merge(
|
|
388
|
+
inst.mod_status
|
|
389
|
+
)
|
|
390
|
+
if subheading:
|
|
391
|
+
subheading.setdefault("flags", 0)
|
|
392
|
+
subheading["flags"] += inst.num_flags if inst else 0
|
|
393
|
+
subheading["status"] = subheading.get(
|
|
394
|
+
"status", inst.mod_status
|
|
395
|
+
).merge(inst.mod_status)
|
|
396
|
+
|
|
397
|
+
if section is form:
|
|
398
|
+
# if this is the edit section we add an empty form as the
|
|
399
|
+
# first form in the context, the template knows to render
|
|
400
|
+
# this form as the 'add' subsection form
|
|
401
|
+
context["forms"].insert(0, form(initial={"site": self.station}))
|
|
402
|
+
context["copy_last_on_add"] = [
|
|
403
|
+
field
|
|
404
|
+
for field in getattr(form, "COPY_LAST_ON_ADD", [])
|
|
405
|
+
if field not in {"id", "subsection"}
|
|
406
|
+
# guard against these ^ fields being included -
|
|
407
|
+
# will break things
|
|
408
|
+
]
|
|
409
|
+
heading["active"] = heading.get("active", True) | True
|
|
410
|
+
if subheading:
|
|
411
|
+
subheading["active"] = True
|
|
412
|
+
|
|
413
|
+
# add form (sub-sub section) numbers
|
|
414
|
+
number = 1
|
|
415
|
+
for form in reversed(context["forms"]):
|
|
416
|
+
if not getattr(form.instance, "is_deleted", False):
|
|
417
|
+
form.form_number = number
|
|
418
|
+
number += 1
|
|
419
|
+
|
|
420
|
+
else:
|
|
421
|
+
instance = form._meta.model.objects.station(
|
|
422
|
+
self.station
|
|
423
|
+
).head() # we always edit on head
|
|
424
|
+
if section is form:
|
|
425
|
+
# only one form is requested per edit view request - if
|
|
426
|
+
# this section is that form we need to populate it with
|
|
427
|
+
# data
|
|
428
|
+
context["forms"].append(
|
|
429
|
+
form(
|
|
430
|
+
instance=instance,
|
|
431
|
+
initial=(
|
|
432
|
+
{
|
|
433
|
+
field: getattr(instance, field, None)
|
|
434
|
+
for field in form._meta.fields
|
|
435
|
+
}
|
|
436
|
+
if instance
|
|
437
|
+
else {"site": self.station}
|
|
438
|
+
),
|
|
439
|
+
)
|
|
440
|
+
)
|
|
441
|
+
context["sections"][form.section_name()]["active"] = True
|
|
442
|
+
|
|
443
|
+
# for all sections we need to set status and number of flags
|
|
444
|
+
context["sections"][form.section_name()]["flags"] = (
|
|
445
|
+
instance.num_flags if instance else 0
|
|
446
|
+
)
|
|
447
|
+
context["sections"][form.section_name()]["status"] = (
|
|
448
|
+
instance.mod_status if instance else SiteLogStatus.EMPTY
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
return context
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
class StationAlertsView(StationContextView):
|
|
455
|
+
template_name = "slm/station/alerts.html"
|
|
456
|
+
|
|
457
|
+
def get_context_data(self, **kwargs):
|
|
458
|
+
context = super().get_context_data(**kwargs)
|
|
459
|
+
context["exclude_targets"] = True
|
|
460
|
+
return context
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class UploadView(StationContextView):
|
|
464
|
+
template_name = "slm/station/upload.html"
|
|
465
|
+
|
|
466
|
+
def get_context_data(self, file=None, **kwargs):
|
|
467
|
+
context = super().get_context_data(**kwargs)
|
|
468
|
+
if file:
|
|
469
|
+
try:
|
|
470
|
+
file = SiteFileUpload.objects.get(pk=file)
|
|
471
|
+
except SiteFileUpload.DoesNotExist:
|
|
472
|
+
raise Http404(f"File {file} does not exist.")
|
|
473
|
+
context["file"] = file
|
|
474
|
+
if file.context:
|
|
475
|
+
context.update(file.context)
|
|
476
|
+
if "findings" in context:
|
|
477
|
+
errors = 0
|
|
478
|
+
warnings = 0
|
|
479
|
+
for lineno, finding in context["findings"].items():
|
|
480
|
+
if finding[0] == Error.level:
|
|
481
|
+
errors += 1
|
|
482
|
+
elif finding[0] == Warn.level:
|
|
483
|
+
warnings += 1
|
|
484
|
+
context["finding_errors"] = errors
|
|
485
|
+
context["finding_warnings"] = warnings
|
|
486
|
+
|
|
487
|
+
if file.file_type in {SLMFileType.SITE_IMAGE, SLMFileType.ATTACHMENT}:
|
|
488
|
+
context["form"] = SiteFileForm(instance=file)
|
|
489
|
+
context["num_files"] = SiteFileUpload.objects.filter(site=self.site).count()
|
|
490
|
+
context["MAX_UPLOAD_MB"] = getattr(settings, "SLM_MAX_UPLOAD_SIZE_MB", 100)
|
|
491
|
+
context["link_view"] = "slm:upload"
|
|
492
|
+
return context
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class NewSiteView(StationContextView):
|
|
496
|
+
template_name = "slm/new_site.html"
|
|
497
|
+
|
|
498
|
+
def get_context_data(self, **kwargs):
|
|
499
|
+
context = super().get_context_data(**kwargs)
|
|
500
|
+
context["form"] = NewSiteForm(
|
|
501
|
+
initial=(
|
|
502
|
+
{"agencies": self.request.user.agencies.all()}
|
|
503
|
+
if not self.request.user.is_superuser
|
|
504
|
+
else {}
|
|
505
|
+
)
|
|
506
|
+
)
|
|
507
|
+
if not self.request.user.is_superuser:
|
|
508
|
+
context["form"].fields["agencies"].queryset = self.request.user.agencies
|
|
509
|
+
return context
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
class IndexView(StationContextView):
|
|
513
|
+
template_name = "slm/station/base.html"
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
class DownloadView(StationContextView):
|
|
517
|
+
template_name = "slm/station/download.html"
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
class UserProfileView(SLMView):
|
|
521
|
+
template_name = "slm/profile.html"
|
|
522
|
+
|
|
523
|
+
@method_decorator(login_required)
|
|
524
|
+
def get(self, request, *args, **kwargs):
|
|
525
|
+
return self.render_to_response(
|
|
526
|
+
{
|
|
527
|
+
**self.get_context_data(**kwargs),
|
|
528
|
+
"user_form": UserForm(instance=request.user),
|
|
529
|
+
"profile_form": UserProfileForm(instance=request.user.profile),
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
class LogView(StationContextView):
|
|
535
|
+
template_name = "slm/station/log.html"
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
class UserActivityLogView(SLMView):
|
|
539
|
+
template_name = "slm/user_activity.html"
|
|
540
|
+
|
|
541
|
+
def get_context_data(self, log_user=None, **kwargs):
|
|
542
|
+
context = super().get_context_data()
|
|
543
|
+
try:
|
|
544
|
+
if log_user:
|
|
545
|
+
# must be a super user to see other people's log history
|
|
546
|
+
# todo configurable perm for this? like is mod for user's
|
|
547
|
+
# agency?
|
|
548
|
+
if not self.request.user.is_superuser:
|
|
549
|
+
raise PermissionDenied()
|
|
550
|
+
|
|
551
|
+
context["log_user"] = get_user_model().objects.get(pk=log_user)
|
|
552
|
+
else:
|
|
553
|
+
# otherwise we're getting the logged in user's log history
|
|
554
|
+
context["log_user"] = self.request.user
|
|
555
|
+
|
|
556
|
+
except get_user_model().DoesNotExist:
|
|
557
|
+
raise Http404()
|
|
558
|
+
|
|
559
|
+
return context
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class StationReviewView(StationContextView):
|
|
563
|
+
template_name = "slm/station/review.html"
|
|
564
|
+
|
|
565
|
+
LOG_FORMATS = {
|
|
566
|
+
fmt
|
|
567
|
+
for fmt in SiteLogFormat
|
|
568
|
+
if fmt not in {SiteLogFormat.JSON, SiteLogFormat.LEGACY}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
def get_context_data(self, **kwargs):
|
|
572
|
+
ctx = super().get_context_data(**kwargs)
|
|
573
|
+
|
|
574
|
+
# we use legacy log files on the ascii 9 char review stack if no 9 char file is available
|
|
575
|
+
review_stack = {fmt: [] for fmt in self.LOG_FORMATS}
|
|
576
|
+
for fmt in self.LOG_FORMATS:
|
|
577
|
+
fmt_q = Q(log_format=fmt)
|
|
578
|
+
if fmt is SiteLogFormat.ASCII_9CHAR:
|
|
579
|
+
fmt_q |= Q(log_format=SiteLogFormat.LEGACY)
|
|
580
|
+
for archive in (
|
|
581
|
+
ArchivedSiteLog.objects.filter(Q(site=self.site) & fmt_q)
|
|
582
|
+
.order_by("-index__begin", "-log_format")
|
|
583
|
+
.values_list("index__begin", "id")
|
|
584
|
+
.distinct("index__begin")
|
|
585
|
+
):
|
|
586
|
+
review_stack[fmt].append((archive[0], archive[1]))
|
|
587
|
+
ctx = {
|
|
588
|
+
**ctx,
|
|
589
|
+
"richtextform": RichTextForm(),
|
|
590
|
+
"default_format": SiteLogFormat.ASCII_9CHAR,
|
|
591
|
+
"log_formats": self.LOG_FORMATS,
|
|
592
|
+
"review_stack": review_stack,
|
|
593
|
+
"needs_publish": self.station.needs_publish(),
|
|
594
|
+
}
|
|
595
|
+
if ctx["needs_publish"]:
|
|
596
|
+
for fmt in self.LOG_FORMATS:
|
|
597
|
+
ctx["review_stack"][fmt].insert(0, (None, None))
|
|
598
|
+
return ctx
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class AlertsView(SLMView):
|
|
602
|
+
template_name = "slm/alerts.html"
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
class AlertView(StationContextView):
|
|
606
|
+
template_name = "slm/station/alert.html"
|
|
607
|
+
template_map = {}
|
|
608
|
+
alert = None
|
|
609
|
+
|
|
610
|
+
def get_template(self, alert):
|
|
611
|
+
if alert.__class__ not in self.template_map:
|
|
612
|
+
try:
|
|
613
|
+
self.template_map[alert.__class__] = get_template(
|
|
614
|
+
f"slm/alerts/{alert.__class__.__name__.lower()}.html"
|
|
615
|
+
)
|
|
616
|
+
except TemplateDoesNotExist:
|
|
617
|
+
self.template_map[alert.__class__] = get_template(
|
|
618
|
+
"slm/alerts/alert.html"
|
|
619
|
+
)
|
|
620
|
+
return self.template_map[alert.__class__]
|
|
621
|
+
|
|
622
|
+
def get_context_data(self, **kwargs):
|
|
623
|
+
if hasattr(self.alert, "site") and self.alert.site:
|
|
624
|
+
kwargs["station"] = self.alert.site.name
|
|
625
|
+
context = super().get_context_data(**kwargs)
|
|
626
|
+
context.update(
|
|
627
|
+
{
|
|
628
|
+
**self.alert.context,
|
|
629
|
+
"alert_template": self.get_template(self.alert).origin.template_name,
|
|
630
|
+
"exclude_targets": True,
|
|
631
|
+
}
|
|
632
|
+
)
|
|
633
|
+
return context
|
|
634
|
+
|
|
635
|
+
def get(self, request, *args, **kwargs):
|
|
636
|
+
try:
|
|
637
|
+
self.alert = Alert.objects.get(pk=kwargs.pop("alert", None))
|
|
638
|
+
except Alert.DoesNotExist:
|
|
639
|
+
return HttpResponseNotFound()
|
|
640
|
+
return super().get(request, *args, **kwargs)
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
class HelpView(SLMView):
|
|
644
|
+
template_name = "slm/help.html"
|
|
645
|
+
|
|
646
|
+
def get_context_data(self, **kwargs):
|
|
647
|
+
return {**super().get_context_data(**kwargs), "help": Help.load()}
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
class AboutView(SLMView):
|
|
651
|
+
template_name = "slm/about.html"
|
|
652
|
+
|
|
653
|
+
def get_context_data(self, **kwargs):
|
|
654
|
+
return {**super().get_context_data(**kwargs), "about": About.load()}
|