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.
Files changed (447) hide show
  1. igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
  2. igs_slm-0.1.0b0.dist-info/METADATA +151 -0
  3. igs_slm-0.1.0b0.dist-info/RECORD +447 -0
  4. igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
  5. igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
  6. igs_tools/__init__.py +0 -0
  7. igs_tools/connection.py +88 -0
  8. igs_tools/defines/__init__.py +8 -0
  9. igs_tools/defines/constellation.py +21 -0
  10. igs_tools/defines/data_center.py +75 -0
  11. igs_tools/defines/rinex.py +49 -0
  12. igs_tools/directory.py +247 -0
  13. igs_tools/utils.py +66 -0
  14. slm/__init__.py +21 -0
  15. slm/admin.py +674 -0
  16. slm/api/edit/__init__.py +0 -0
  17. slm/api/edit/serializers.py +316 -0
  18. slm/api/edit/views.py +1632 -0
  19. slm/api/fields.py +89 -0
  20. slm/api/filter.py +504 -0
  21. slm/api/pagination.py +55 -0
  22. slm/api/permissions.py +65 -0
  23. slm/api/public/__init__.py +0 -0
  24. slm/api/public/serializers.py +249 -0
  25. slm/api/public/views.py +606 -0
  26. slm/api/serializers.py +132 -0
  27. slm/api/views.py +148 -0
  28. slm/apps.py +323 -0
  29. slm/authentication.py +198 -0
  30. slm/bin/__init__.py +0 -0
  31. slm/bin/startproject.py +262 -0
  32. slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
  33. slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
  34. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
  35. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
  36. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
  37. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
  38. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
  39. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
  40. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
  41. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
  42. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
  43. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
  44. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
  45. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
  46. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
  47. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
  48. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
  49. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
  50. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
  51. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
  52. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
  53. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
  54. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
  55. slm/defines/AlertLevel.py +24 -0
  56. slm/defines/AntennaCalibration.py +25 -0
  57. slm/defines/AntennaFeatures.py +27 -0
  58. slm/defines/AntennaReferencePoint.py +22 -0
  59. slm/defines/Aspiration.py +13 -0
  60. slm/defines/CardinalDirection.py +19 -0
  61. slm/defines/CollocationStatus.py +12 -0
  62. slm/defines/EquipmentState.py +22 -0
  63. slm/defines/FlagSeverity.py +14 -0
  64. slm/defines/FractureSpacing.py +15 -0
  65. slm/defines/FrequencyStandardType.py +15 -0
  66. slm/defines/GeodesyMLVersion.py +48 -0
  67. slm/defines/ISOCountry.py +1194 -0
  68. slm/defines/Instrumentation.py +19 -0
  69. slm/defines/LogEntryType.py +30 -0
  70. slm/defines/SLMFileType.py +18 -0
  71. slm/defines/SiteFileUploadStatus.py +61 -0
  72. slm/defines/SiteLogFormat.py +49 -0
  73. slm/defines/SiteLogStatus.py +78 -0
  74. slm/defines/TectonicPlates.py +28 -0
  75. slm/defines/__init__.py +46 -0
  76. slm/forms.py +1126 -0
  77. slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
  78. slm/jinja2/slm/sitelog/legacy.log +346 -0
  79. slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
  80. slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
  81. slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
  82. slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
  83. slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
  84. slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
  85. slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
  86. slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
  87. slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
  88. slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
  89. slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
  90. slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
  91. slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
  92. slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
  93. slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
  94. slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
  95. slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
  96. slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
  97. slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
  98. slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
  99. slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
  100. slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
  101. slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
  102. slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
  103. slm/management/__init__.py +0 -0
  104. slm/management/commands/__init__.py +53 -0
  105. slm/management/commands/build_index.py +96 -0
  106. slm/management/commands/generate_sinex.py +675 -0
  107. slm/management/commands/head_from_index.py +541 -0
  108. slm/management/commands/import_archive.py +908 -0
  109. slm/management/commands/import_equipment.py +351 -0
  110. slm/management/commands/set_site.py +56 -0
  111. slm/management/commands/sitelog.py +144 -0
  112. slm/management/commands/synchronize.py +60 -0
  113. slm/management/commands/update_data_availability.py +167 -0
  114. slm/management/commands/validate_db.py +186 -0
  115. slm/management/commands/validate_gml.py +73 -0
  116. slm/map/__init__.py +1 -0
  117. slm/map/admin.py +5 -0
  118. slm/map/api/__init__.py +0 -0
  119. slm/map/api/edit/__init__.py +0 -0
  120. slm/map/api/edit/serializers.py +28 -0
  121. slm/map/api/edit/views.py +46 -0
  122. slm/map/api/public/__init__.py +0 -0
  123. slm/map/api/public/serializers.py +29 -0
  124. slm/map/api/public/views.py +64 -0
  125. slm/map/apps.py +7 -0
  126. slm/map/defines.py +53 -0
  127. slm/map/migrations/0001_initial.py +115 -0
  128. slm/map/migrations/__init__.py +0 -0
  129. slm/map/models.py +63 -0
  130. slm/map/static/slm/css/map.css +86 -0
  131. slm/map/static/slm/js/map.js +159 -0
  132. slm/map/templates/slm/map.html +374 -0
  133. slm/map/templates/slm/station/base.html +11 -0
  134. slm/map/templates/slm/station/edit.html +10 -0
  135. slm/map/templates/slm/top_nav.html +17 -0
  136. slm/map/templatetags/__init__.py +0 -0
  137. slm/map/templatetags/slm_map.py +18 -0
  138. slm/map/urls.py +25 -0
  139. slm/map/views.py +36 -0
  140. slm/middleware.py +29 -0
  141. slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
  142. slm/migrations/0001_initial.py +4826 -0
  143. slm/migrations/0002_alter_dataavailability_site.py +22 -0
  144. slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
  145. slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
  146. slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
  147. slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
  148. slm/migrations/0007_alter_dataavailability_rate.py +23 -0
  149. slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
  150. slm/migrations/0009_alter_archiveindex_end.py +21 -0
  151. slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
  152. slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
  153. slm/migrations/0012_alter_logentry_type.py +36 -0
  154. slm/migrations/0013_unpublishedfilesalert.py +48 -0
  155. slm/migrations/0014_sitelogpublished.py +48 -0
  156. slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
  157. slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
  158. slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
  159. slm/migrations/0018_afix_deleted.py +34 -0
  160. slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
  161. slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
  162. slm/migrations/0020_alter_manufacturer_options.py +16 -0
  163. slm/migrations/0021_alter_siteform_report_type.py +23 -0
  164. slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
  165. slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
  166. slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
  167. slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
  168. slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
  169. slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
  170. slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
  171. slm/migrations/0029_manufacturer_full_name.py +17 -0
  172. slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
  173. slm/migrations/__init__.py +0 -0
  174. slm/migrations/load_satellitesystems.py +27 -0
  175. slm/models/__init__.py +118 -0
  176. slm/models/about.py +14 -0
  177. slm/models/alerts.py +1204 -0
  178. slm/models/data.py +58 -0
  179. slm/models/equipment.py +229 -0
  180. slm/models/help.py +14 -0
  181. slm/models/index.py +428 -0
  182. slm/models/sitelog.py +4279 -0
  183. slm/models/system.py +723 -0
  184. slm/models/user.py +304 -0
  185. slm/parsing/__init__.py +786 -0
  186. slm/parsing/legacy/__init__.py +4 -0
  187. slm/parsing/legacy/binding.py +817 -0
  188. slm/parsing/legacy/parser.py +377 -0
  189. slm/parsing/xsd/__init__.py +34 -0
  190. slm/parsing/xsd/binding.py +86 -0
  191. slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
  192. slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
  193. slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
  194. slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
  195. slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
  196. slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
  197. slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
  198. slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
  199. slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
  200. slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
  201. slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
  202. slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
  203. slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
  204. slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
  205. slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
  206. slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
  207. slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
  208. slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
  209. slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
  210. slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
  211. slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
  212. slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
  213. slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
  214. slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
  215. slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
  216. slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
  217. slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
  218. slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
  219. slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
  220. slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
  221. slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
  222. slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
  223. slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
  224. slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
  225. slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
  226. slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
  227. slm/parsing/xsd/parser.py +116 -0
  228. slm/parsing/xsd/resolver.py +28 -0
  229. slm/receivers/__init__.py +11 -0
  230. slm/receivers/alerts.py +87 -0
  231. slm/receivers/cleanup.py +41 -0
  232. slm/receivers/event_loggers.py +175 -0
  233. slm/receivers/index.py +67 -0
  234. slm/settings/__init__.py +55 -0
  235. slm/settings/auth.py +15 -0
  236. slm/settings/ckeditor.py +14 -0
  237. slm/settings/debug.py +47 -0
  238. slm/settings/internationalization.py +12 -0
  239. slm/settings/logging.py +113 -0
  240. slm/settings/platform/__init__.py +0 -0
  241. slm/settings/platform/darwin.py +10 -0
  242. slm/settings/rest.py +21 -0
  243. slm/settings/root.py +152 -0
  244. slm/settings/routines.py +43 -0
  245. slm/settings/secrets.py +37 -0
  246. slm/settings/security.py +5 -0
  247. slm/settings/slm.py +188 -0
  248. slm/settings/static_templates.py +53 -0
  249. slm/settings/templates.py +29 -0
  250. slm/settings/uploads.py +8 -0
  251. slm/settings/urls.py +126 -0
  252. slm/settings/validation.py +196 -0
  253. slm/signals.py +250 -0
  254. slm/singleton.py +49 -0
  255. slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
  256. slm/static/rest_framework/css/bootstrap.min.css +7 -0
  257. slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
  258. slm/static/rest_framework/css/default.css +82 -0
  259. slm/static/rest_framework/css/prettify.css +30 -0
  260. slm/static/rest_framework/docs/css/base.css +344 -0
  261. slm/static/rest_framework/docs/css/highlight.css +125 -0
  262. slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
  263. slm/static/rest_framework/docs/img/favicon.ico +0 -0
  264. slm/static/rest_framework/docs/img/grid.png +0 -0
  265. slm/static/rest_framework/docs/js/api.js +321 -0
  266. slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
  267. slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
  268. slm/static/rest_framework/img/grid.png +0 -0
  269. slm/static/rest_framework/js/ajax-form.js +127 -0
  270. slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
  271. slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
  272. slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
  273. slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
  274. slm/static/rest_framework/js/csrf.js +52 -0
  275. slm/static/rest_framework/js/default.js +47 -0
  276. slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
  277. slm/static/rest_framework/js/prettify-min.js +28 -0
  278. slm/static/slm/css/admin.css +3 -0
  279. slm/static/slm/css/defines.css +82 -0
  280. slm/static/slm/css/forms.css +1 -0
  281. slm/static/slm/css/style.css +1004 -0
  282. slm/static/slm/img/email-branding.png +0 -0
  283. slm/static/slm/img/favicon.ico +0 -0
  284. slm/static/slm/img/login-bg.jpg +0 -0
  285. slm/static/slm/img/slm-logo.svg +4 -0
  286. slm/static/slm/js/autocomplete.js +341 -0
  287. slm/static/slm/js/enums.js +322 -0
  288. slm/static/slm/js/fileIcons.js +30 -0
  289. slm/static/slm/js/form.js +404 -0
  290. slm/static/slm/js/formWidget.js +23 -0
  291. slm/static/slm/js/persistable.js +33 -0
  292. slm/static/slm/js/slm.js +1028 -0
  293. slm/static/slm/js/time24.js +212 -0
  294. slm/static_templates/slm/css/defines.css +26 -0
  295. slm/static_templates/slm/js/enums.js +28 -0
  296. slm/static_templates/slm/js/fileIcons.js +16 -0
  297. slm/static_templates/slm/js/urls.js +5 -0
  298. slm/templates/account/base.html +20 -0
  299. slm/templates/account/email/base.html +43 -0
  300. slm/templates/account/email/base_message.txt +7 -0
  301. slm/templates/account/email/email_confirmation_message.html +16 -0
  302. slm/templates/account/email/email_confirmation_message.txt +7 -0
  303. slm/templates/account/email/email_confirmation_signup_message.html +1 -0
  304. slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
  305. slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
  306. slm/templates/account/email/email_confirmation_subject.txt +4 -0
  307. slm/templates/account/email/password_reset_key_message.html +28 -0
  308. slm/templates/account/email/password_reset_key_message.txt +9 -0
  309. slm/templates/account/email/password_reset_key_subject.txt +4 -0
  310. slm/templates/account/email/unknown_account_message.html +25 -0
  311. slm/templates/account/email/unknown_account_message.txt +12 -0
  312. slm/templates/account/email/unknown_account_subject.txt +4 -0
  313. slm/templates/account/login.html +67 -0
  314. slm/templates/account/logout.html +38 -0
  315. slm/templates/account/password_change.html +48 -0
  316. slm/templates/account/password_reset.html +51 -0
  317. slm/templates/account/password_reset_done.html +20 -0
  318. slm/templates/account/password_reset_from_key.html +52 -0
  319. slm/templates/account/password_reset_from_key_done.html +17 -0
  320. slm/templates/admin/base.html +7 -0
  321. slm/templates/messages.html +8 -0
  322. slm/templates/rest_framework/README +16 -0
  323. slm/templates/rest_framework/admin/detail.html +10 -0
  324. slm/templates/rest_framework/admin/dict_value.html +11 -0
  325. slm/templates/rest_framework/admin/list.html +32 -0
  326. slm/templates/rest_framework/admin/list_value.html +11 -0
  327. slm/templates/rest_framework/admin/simple_list_value.html +2 -0
  328. slm/templates/rest_framework/admin.html +282 -0
  329. slm/templates/rest_framework/api.html +3 -0
  330. slm/templates/rest_framework/base.html +334 -0
  331. slm/templates/rest_framework/docs/auth/basic.html +42 -0
  332. slm/templates/rest_framework/docs/auth/session.html +40 -0
  333. slm/templates/rest_framework/docs/auth/token.html +41 -0
  334. slm/templates/rest_framework/docs/document.html +37 -0
  335. slm/templates/rest_framework/docs/error.html +71 -0
  336. slm/templates/rest_framework/docs/index.html +55 -0
  337. slm/templates/rest_framework/docs/interact.html +57 -0
  338. slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
  339. slm/templates/rest_framework/docs/langs/javascript.html +15 -0
  340. slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
  341. slm/templates/rest_framework/docs/langs/python.html +13 -0
  342. slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
  343. slm/templates/rest_framework/docs/langs/shell.html +6 -0
  344. slm/templates/rest_framework/docs/link.html +113 -0
  345. slm/templates/rest_framework/docs/sidebar.html +78 -0
  346. slm/templates/rest_framework/filters/base.html +16 -0
  347. slm/templates/rest_framework/filters/ordering.html +17 -0
  348. slm/templates/rest_framework/filters/search.html +13 -0
  349. slm/templates/rest_framework/horizontal/checkbox.html +23 -0
  350. slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
  351. slm/templates/rest_framework/horizontal/dict_field.html +11 -0
  352. slm/templates/rest_framework/horizontal/fieldset.html +16 -0
  353. slm/templates/rest_framework/horizontal/form.html +6 -0
  354. slm/templates/rest_framework/horizontal/input.html +21 -0
  355. slm/templates/rest_framework/horizontal/list_field.html +11 -0
  356. slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
  357. slm/templates/rest_framework/horizontal/radio.html +42 -0
  358. slm/templates/rest_framework/horizontal/select.html +36 -0
  359. slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
  360. slm/templates/rest_framework/horizontal/textarea.html +21 -0
  361. slm/templates/rest_framework/inline/checkbox.html +8 -0
  362. slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
  363. slm/templates/rest_framework/inline/dict_field.html +9 -0
  364. slm/templates/rest_framework/inline/fieldset.html +6 -0
  365. slm/templates/rest_framework/inline/form.html +8 -0
  366. slm/templates/rest_framework/inline/input.html +9 -0
  367. slm/templates/rest_framework/inline/list_field.html +9 -0
  368. slm/templates/rest_framework/inline/list_fieldset.html +3 -0
  369. slm/templates/rest_framework/inline/radio.html +25 -0
  370. slm/templates/rest_framework/inline/select.html +24 -0
  371. slm/templates/rest_framework/inline/select_multiple.html +25 -0
  372. slm/templates/rest_framework/inline/textarea.html +9 -0
  373. slm/templates/rest_framework/login.html +3 -0
  374. slm/templates/rest_framework/login_base.html +65 -0
  375. slm/templates/rest_framework/pagination/numbers.html +47 -0
  376. slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
  377. slm/templates/rest_framework/raw_data_form.html +11 -0
  378. slm/templates/rest_framework/schema.js +3 -0
  379. slm/templates/rest_framework/vertical/checkbox.html +16 -0
  380. slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
  381. slm/templates/rest_framework/vertical/dict_field.html +7 -0
  382. slm/templates/rest_framework/vertical/fieldset.html +13 -0
  383. slm/templates/rest_framework/vertical/form.html +6 -0
  384. slm/templates/rest_framework/vertical/input.html +17 -0
  385. slm/templates/rest_framework/vertical/list_field.html +7 -0
  386. slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
  387. slm/templates/rest_framework/vertical/radio.html +40 -0
  388. slm/templates/rest_framework/vertical/select.html +34 -0
  389. slm/templates/rest_framework/vertical/select_multiple.html +31 -0
  390. slm/templates/rest_framework/vertical/textarea.html +17 -0
  391. slm/templates/slm/about.html +21 -0
  392. slm/templates/slm/alerts/alert.html +15 -0
  393. slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
  394. slm/templates/slm/alerts/importalert.html +10 -0
  395. slm/templates/slm/alerts.html +18 -0
  396. slm/templates/slm/auth_menu.html +41 -0
  397. slm/templates/slm/base.html +195 -0
  398. slm/templates/slm/emails/alert_issued.html +31 -0
  399. slm/templates/slm/emails/alert_issued.txt +9 -0
  400. slm/templates/slm/emails/base.html +6 -0
  401. slm/templates/slm/emails/changes_rejected.txt +7 -0
  402. slm/templates/slm/emails/review_requested.txt +7 -0
  403. slm/templates/slm/forms/widgets/auto_complete.html +21 -0
  404. slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
  405. slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
  406. slm/templates/slm/forms/widgets/inline_multi.html +1 -0
  407. slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
  408. slm/templates/slm/forms/widgets/time24.html +37 -0
  409. slm/templates/slm/help.html +54 -0
  410. slm/templates/slm/messages.html +13 -0
  411. slm/templates/slm/new_site.html +88 -0
  412. slm/templates/slm/profile.html +57 -0
  413. slm/templates/slm/register.html +40 -0
  414. slm/templates/slm/reports/file_log.html +43 -0
  415. slm/templates/slm/reports/head_log.html +23 -0
  416. slm/templates/slm/reports/head_report.html +55 -0
  417. slm/templates/slm/reports/index_log.html +23 -0
  418. slm/templates/slm/reports/index_report.html +71 -0
  419. slm/templates/slm/station/alert.html +8 -0
  420. slm/templates/slm/station/alerts.html +19 -0
  421. slm/templates/slm/station/base.html +104 -0
  422. slm/templates/slm/station/download.html +87 -0
  423. slm/templates/slm/station/edit.html +283 -0
  424. slm/templates/slm/station/form.html +110 -0
  425. slm/templates/slm/station/log.html +18 -0
  426. slm/templates/slm/station/review.html +461 -0
  427. slm/templates/slm/station/upload.html +295 -0
  428. slm/templates/slm/station/uploads/attachment.html +20 -0
  429. slm/templates/slm/station/uploads/geodesyml.html +1 -0
  430. slm/templates/slm/station/uploads/image.html +27 -0
  431. slm/templates/slm/station/uploads/json.html +0 -0
  432. slm/templates/slm/station/uploads/legacy.html +77 -0
  433. slm/templates/slm/top_nav.html +14 -0
  434. slm/templates/slm/user_activity.html +16 -0
  435. slm/templates/slm/widgets/alert_scroll.html +135 -0
  436. slm/templates/slm/widgets/filelist.html +258 -0
  437. slm/templates/slm/widgets/legend.html +12 -0
  438. slm/templates/slm/widgets/log_scroll.html +88 -0
  439. slm/templates/slm/widgets/stationlist.html +233 -0
  440. slm/templatetags/__init__.py +0 -0
  441. slm/templatetags/jinja2.py +9 -0
  442. slm/templatetags/slm.py +459 -0
  443. slm/urls.py +148 -0
  444. slm/utils.py +299 -0
  445. slm/validators.py +297 -0
  446. slm/views.py +654 -0
  447. slm/widgets.py +134 -0
@@ -0,0 +1,606 @@
1
+ import json
2
+ from datetime import datetime
3
+
4
+ import django_filters
5
+ from crispy_forms.helper import FormHelper
6
+ from crispy_forms.layout import Div, Field, Fieldset, Layout, Submit
7
+ from django import forms
8
+ from django.db.models import Prefetch, Q
9
+ from django.http import FileResponse
10
+ from django.utils.translation import gettext as _
11
+ from django_enum.filters import EnumFilter
12
+ from django_filters.rest_framework import DjangoFilterBackend, FilterSet
13
+ from rest_framework import mixins, viewsets
14
+ from rest_framework.filters import OrderingFilter
15
+
16
+ from slm.api.filter import (
17
+ BaseStationFilter,
18
+ CrispyFormCompat,
19
+ SiteSearchFilter,
20
+ SLMBooleanFilter,
21
+ SLMDateTimeFilter,
22
+ )
23
+ from slm.api.pagination import DataTablesPagination
24
+ from slm.api.public.serializers import ( # DOMESSerializer
25
+ AgencySerializer,
26
+ AntennaSerializer,
27
+ ArchiveSerializer,
28
+ ManufacturerSerializer,
29
+ NetworkSerializer,
30
+ RadomeSerializer,
31
+ ReceiverSerializer,
32
+ SiteFileUploadSerializer,
33
+ StationListSerializer,
34
+ StationNameSerializer,
35
+ )
36
+ from slm.api.views import BaseSiteLogDownloadViewSet
37
+ from slm.defines import EquipmentState, SiteLogFormat, SiteLogStatus
38
+ from slm.forms import EnumMultipleChoiceField, SLMBooleanField
39
+ from slm.forms import StationFilterForm as BaseStationFilterForm
40
+ from slm.models import (
41
+ Agency,
42
+ Antenna,
43
+ ArchivedSiteLog,
44
+ Equipment,
45
+ Manufacturer,
46
+ Network,
47
+ Radome,
48
+ Receiver,
49
+ Site,
50
+ SiteFileUpload,
51
+ SiteReceiver,
52
+ SiteTideGauge,
53
+ )
54
+
55
+
56
+ class StationFilterForm(BaseStationFilterForm):
57
+ include_former = SLMBooleanField(
58
+ label=_("Include Former"),
59
+ help_text=_(
60
+ "Include stations that are no longer maintained as part of any "
61
+ "of our networks."
62
+ ),
63
+ initial=False,
64
+ required=False,
65
+ )
66
+
67
+ include_proposed = SLMBooleanField(
68
+ label=_("Include Proposed"),
69
+ help_text=_(
70
+ "Include stations that are proposed for future inclusion in one "
71
+ "of our networks."
72
+ ),
73
+ initial=False,
74
+ required=False,
75
+ )
76
+
77
+ @property
78
+ def helper(self):
79
+ helper = FormHelper()
80
+ helper.form_method = "GET"
81
+ helper.disable_csrf = True
82
+ helper.form_id = "slm-station-filter"
83
+ helper.layout = Layout(
84
+ Div(
85
+ Div(
86
+ "station",
87
+ Field("satellite_system", wrapper_class="form-switch"),
88
+ Field("frequency_standard", wrapper_class="form-switch"),
89
+ css_class="col-3",
90
+ ),
91
+ Div(
92
+ Fieldset(
93
+ _("Equipment Filters"),
94
+ Field("current", wrapper_class="form-switch"),
95
+ "receiver",
96
+ "antenna",
97
+ "radome",
98
+ css_class="slm-form-group",
99
+ ),
100
+ css_class="col-4",
101
+ ),
102
+ Div(
103
+ "agency",
104
+ "network",
105
+ Field("country", css_class="slm-country search-input"),
106
+ Field("include_former", wrapper_class="form-switch"),
107
+ Field("include_proposed", wrapper_class="form-switch"),
108
+ "geography",
109
+ css_class="col-5",
110
+ ),
111
+ css_class="row",
112
+ ),
113
+ Submit("", _("Submit"), css_class="btn btn-primary"),
114
+ )
115
+ helper.attrs = {
116
+ "data_slm_initial": json.dumps(
117
+ {
118
+ field.name: field.field.initial
119
+ for field in self
120
+ if field.field.initial
121
+ }
122
+ )
123
+ }
124
+ return helper
125
+
126
+
127
+ class StationFilter(BaseStationFilter):
128
+ include_former = SLMBooleanFilter(
129
+ method="filter_former", field_name="include_former"
130
+ )
131
+
132
+ include_proposed = SLMBooleanFilter(
133
+ method="filter_proposed", field_name="include_proposed"
134
+ )
135
+
136
+ def filter_former(self, queryset, name, value):
137
+ if not value:
138
+ return queryset.filter(~Q(status=SiteLogStatus.FORMER))
139
+ return queryset
140
+
141
+ def filter_proposed(self, queryset, name, value):
142
+ if not value:
143
+ return queryset.filter(~Q(status=SiteLogStatus.PROPOSED))
144
+ return queryset
145
+
146
+ def get_form_class(self):
147
+ return StationFilterForm
148
+
149
+ @property
150
+ def restrict_published(self):
151
+ return True
152
+
153
+
154
+ class DataTablesListMixin(mixins.ListModelMixin):
155
+ """
156
+ A mixin for adapting list views to work with the datatables library.
157
+ """
158
+
159
+ pagination_class = DataTablesPagination
160
+
161
+
162
+ class StationNameViewSet(
163
+ mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet
164
+ ):
165
+ queryset = Site.objects.public()
166
+ serializer_class = StationNameSerializer
167
+ permission_classes = []
168
+
169
+ class StationNameFilter(CrispyFormCompat, FilterSet):
170
+ """
171
+ Todo chain with station filer.
172
+ """
173
+
174
+ name = django_filters.CharFilter(lookup_expr="icontains", distinct=True)
175
+
176
+ class Meta:
177
+ model = Site
178
+ fields = ("name",)
179
+ distinct = True
180
+
181
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
182
+ filterset_class = StationNameFilter
183
+ ordering = ("name",)
184
+
185
+
186
+ class StationListViewSet(
187
+ DataTablesListMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet
188
+ ):
189
+ serializer_class = StationListSerializer
190
+ permission_classes = []
191
+ lookup_field = "name"
192
+ lookup_url_kwarg = "station"
193
+
194
+ filter_backends = (DjangoFilterBackend, OrderingFilter, SiteSearchFilter)
195
+
196
+ filterset_class = StationFilter
197
+ ordering_fields = [
198
+ "name",
199
+ "last_data", # 'lat', 'lon', 'elev',
200
+ ]
201
+
202
+ # if you update these you have to also update
203
+ search_fields = (
204
+ "name",
205
+ "agencies__name",
206
+ "agencies__shortname",
207
+ "networks__name",
208
+ "sitelocation__city",
209
+ "sitereceiver__serial_number",
210
+ "sitereceiver__firmware",
211
+ "siteidentification__iers_domes_number",
212
+ "sitemoreinformation__primary",
213
+ "siteantenna__antenna_type__model",
214
+ "siteantenna__radome_type__model",
215
+ "sitereceiver__receiver_type__model",
216
+ )
217
+ ordering = ("name",)
218
+
219
+ def get_queryset(self):
220
+ return (
221
+ Site.objects.prefetch_related(
222
+ "agencies",
223
+ "networks",
224
+ Prefetch(
225
+ "sitereceiver_set",
226
+ queryset=SiteReceiver.objects.published()
227
+ .prefetch_related("satellite_system")
228
+ .order_by("-installed"),
229
+ ),
230
+ Prefetch(
231
+ "tide_gauge_distances",
232
+ queryset=SiteTideGauge.objects.prefetch_related("gauge").order_by(
233
+ "-distance"
234
+ ),
235
+ ),
236
+ )
237
+ .with_location_fields("city", "state", "country", "xyz", "llh")
238
+ .with_identification_fields("cdp_number", iers_domes_number="domes_number")
239
+ .with_antenna_fields(
240
+ "antcal",
241
+ antenna_type__model="antenna_type",
242
+ radome_type__model="radome_type",
243
+ serial_number="antenna_serial_number",
244
+ marker_une="antenna_marker_une",
245
+ )
246
+ .with_receiver_fields(
247
+ "firmware",
248
+ "serial_number",
249
+ receiver_type__model="receiver_type",
250
+ )
251
+ .with_frequency_standard_fields(standard_type="frequency_standard")
252
+ .with_info_fields(primary="data_center")
253
+ .public()
254
+ .availability()
255
+ .distinct()
256
+ )
257
+
258
+
259
+ class SiteLogDownloadViewSet(BaseSiteLogDownloadViewSet):
260
+ # limit downloads to public sites only!
261
+ # requests for non-public sites will return 404s
262
+ pass
263
+
264
+
265
+ class SiteFileUploadViewSet(
266
+ DataTablesListMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet
267
+ ):
268
+ serializer_class = SiteFileUploadSerializer
269
+ permission_classes = []
270
+
271
+ class FileFilter(CrispyFormCompat, FilterSet):
272
+ site = django_filters.CharFilter(method="find_by_name")
273
+
274
+ name = django_filters.CharFilter(field_name="name", lookup_expr="istartswith")
275
+
276
+ def find_by_name(self, queryset, name, value):
277
+ return queryset.filter(site__name__istartswith=value)
278
+
279
+ class Meta:
280
+ model = SiteFileUpload
281
+ fields = ("name", "site", "mimetype", "file_type")
282
+
283
+ def retrieve(self, request, *args, **kwargs):
284
+ """
285
+ A function view for downloading files that have been uploaded to
286
+ a site. This allows unathenticated downloads of public files and
287
+ authenticated download of any file available to the authenticated user.
288
+
289
+ :param request: Django request object
290
+ :return: Either a 404 or a FileResponse object containing the file.
291
+ """
292
+
293
+ file = self.get_object()
294
+ if request.GET.get("thumbnail", None):
295
+ file = file.thumbnail
296
+ else:
297
+ file = file.file
298
+ return FileResponse(
299
+ file.open("rb"),
300
+ filename=file.name,
301
+ # note this might not match the name on disk
302
+ as_attachment=True,
303
+ )
304
+
305
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
306
+ filterset_class = FileFilter
307
+ ordering_fields = ["-timestamp", "name", "site"]
308
+
309
+ def get_queryset(self):
310
+ return SiteFileUpload.objects.public().select_related("site")
311
+
312
+
313
+ """
314
+ todo - waiting on DOMES data model change
315
+ class DOMESViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
316
+
317
+ serializer_class = DOMESSerializer
318
+ permission_classes = []
319
+
320
+ class DOMESFilter(FilterSet):
321
+ model = django_filters.CharFilter(lookup_expr='icontains')
322
+ in_use = django_filters.BooleanFilter(
323
+ method='in_use_filter',
324
+ distinct=True
325
+ )
326
+
327
+ def in_use_filter(self, queryset, name, value):
328
+ if value:
329
+ return queryset.filter(
330
+ site_receivers__isnull=False
331
+ ).distinct()
332
+ return queryset
333
+
334
+ class Meta:
335
+ model = Site
336
+ fields = ('id', 'domes_')
337
+ distinct = True
338
+
339
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
340
+ filterset_class = DOMESFilter
341
+ ordering_fields = ('model',)
342
+ ordering = ('model',)
343
+
344
+ def get_queryset(self):
345
+ return Site.objects.select_related('manufacturer')
346
+ """
347
+
348
+
349
+ class EquipmentFilterForm(CrispyFormCompat, forms.Form):
350
+ model = forms.CharField(required=False)
351
+
352
+ state = EnumMultipleChoiceField(
353
+ EquipmentState,
354
+ help_text=_("Include equipment codings in these states."),
355
+ label=_("Coding Status"),
356
+ required=False,
357
+ )
358
+ in_use = forms.BooleanField(
359
+ required=False,
360
+ help_text=_("Only equipment that is in active use."),
361
+ label=_("In Use"),
362
+ )
363
+
364
+ manufacturer = forms.CharField(required=False)
365
+
366
+
367
+ class EquipmentFilter(CrispyFormCompat, FilterSet):
368
+ model = django_filters.CharFilter(lookup_expr="icontains")
369
+ in_use = django_filters.BooleanFilter(
370
+ method="in_use_filter", distinct=True, label="In Use"
371
+ )
372
+ manufacturer = django_filters.CharFilter(method="manufacturer_filter")
373
+ state = django_filters.MultipleChoiceFilter(
374
+ choices=EquipmentState.choices, distinct=True
375
+ )
376
+ related_formfield = None
377
+
378
+ def manufacturer_filter(self, queryset, name, value):
379
+ if value:
380
+ return queryset.filter(manufacturer__name__icontains=value).distinct()
381
+ return queryset
382
+
383
+ def in_use_filter(self, queryset, name, value):
384
+ if value:
385
+ return queryset.filter(
386
+ Q(**{f"{self.related_formfield}__isnull": False})
387
+ & Q(**{f"{self.related_formfield}__published": True})
388
+ & Q(**{f"{self.related_formfield}__removed__isnull": True})
389
+ & Q(
390
+ **{
391
+ f"{self.related_formfield}__site__status__in": SiteLogStatus.active_states()
392
+ }
393
+ )
394
+ ).distinct()
395
+ return queryset
396
+
397
+ def get_form_class(self):
398
+ return EquipmentFilterForm
399
+
400
+ def filter_queryset(self, queryset):
401
+ """
402
+ By default
403
+ """
404
+ qryst = super().filter_queryset(queryset)
405
+ if self.data.get("state", None):
406
+ return qryst
407
+ return qryst.filter(state=EquipmentState.ACTIVE)
408
+
409
+ class Meta:
410
+ model = Equipment
411
+ fields = ("model", "in_use", "manufacturer", "state")
412
+ distinct = True
413
+
414
+
415
+ class ReceiverViewSet(
416
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
417
+ ):
418
+ serializer_class = ReceiverSerializer
419
+ permission_classes = []
420
+
421
+ class ReceiverFilter(EquipmentFilter):
422
+ related_formfield = "site_receivers"
423
+
424
+ class Meta(EquipmentFilter.Meta):
425
+ model = Receiver
426
+
427
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
428
+ filterset_class = ReceiverFilter
429
+ ordering_fields = ("model",)
430
+ ordering = ("model",)
431
+
432
+ def get_queryset(self):
433
+ return Receiver.objects.select_related("manufacturer").prefetch_related(
434
+ "replaced"
435
+ )
436
+
437
+
438
+ class AntennaViewSet(
439
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
440
+ ):
441
+ serializer_class = AntennaSerializer
442
+ permission_classes = []
443
+
444
+ class AntennaFilter(EquipmentFilter):
445
+ related_formfield = "site_antennas"
446
+
447
+ class Meta(EquipmentFilter.Meta):
448
+ model = Antenna
449
+
450
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
451
+ filterset_class = AntennaFilter
452
+ ordering_fields = ("model",)
453
+ ordering = ("model",)
454
+
455
+ def get_queryset(self):
456
+ return Antenna.objects.select_related("manufacturer").prefetch_related(
457
+ "replaced"
458
+ )
459
+
460
+
461
+ class RadomeViewSet(
462
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
463
+ ):
464
+ serializer_class = RadomeSerializer
465
+ permission_classes = []
466
+
467
+ class RadomeFilter(EquipmentFilter):
468
+ related_formfield = "site_radomes"
469
+
470
+ class Meta(EquipmentFilter.Meta):
471
+ model = Radome
472
+
473
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
474
+ filterset_class = RadomeFilter
475
+ ordering_fields = ("model",)
476
+ ordering = ("model",)
477
+
478
+ def get_queryset(self):
479
+ return Radome.objects.select_related("manufacturer").prefetch_related(
480
+ "replaced"
481
+ )
482
+
483
+
484
+ class ManufacturerViewSet(
485
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
486
+ ):
487
+ serializer_class = ManufacturerSerializer
488
+ permission_classes = []
489
+
490
+ class ManufacturerFilter(CrispyFormCompat, FilterSet):
491
+ name = django_filters.CharFilter(lookup_expr="icontains")
492
+
493
+ class Meta:
494
+ model = Manufacturer
495
+ fields = ("name",)
496
+ distinct = True
497
+
498
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
499
+ filterset_class = ManufacturerFilter
500
+ ordering_fields = ("name",)
501
+ ordering = ("name",)
502
+
503
+ def get_queryset(self):
504
+ return Manufacturer.objects.all()
505
+
506
+
507
+ class AgencyViewSet(
508
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
509
+ ):
510
+ serializer_class = AgencySerializer
511
+ permission_classes = []
512
+
513
+ class AgencyFilter(CrispyFormCompat, FilterSet):
514
+ name = django_filters.CharFilter(lookup_expr="icontains")
515
+ abbr = django_filters.CharFilter(
516
+ lookup_expr="icontains", field_name="short_name"
517
+ )
518
+
519
+ search = django_filters.CharFilter(method="name_or_abbr")
520
+
521
+ def name_or_abbr(self, queryset, name, value):
522
+ return queryset.filter(
523
+ Q(name__icontains=value) | Q(shortname__icontains=value)
524
+ )
525
+
526
+ class Meta:
527
+ model = Agency
528
+ fields = ("name", "abbr", "search")
529
+
530
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
531
+ filterset_class = AgencyFilter
532
+ ordering_fields = ("name", "shortname")
533
+ ordering = ("name", "shortname")
534
+
535
+ def get_queryset(self):
536
+ return Agency.objects.visible_to(self.request.user)
537
+
538
+
539
+ class NetworkViewSet(
540
+ mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet
541
+ ):
542
+ serializer_class = NetworkSerializer
543
+ permission_classes = []
544
+
545
+ class NetworkFilter(CrispyFormCompat, FilterSet):
546
+ name = django_filters.CharFilter(lookup_expr="icontains")
547
+
548
+ class Meta:
549
+ model = Network
550
+ fields = ("name",)
551
+
552
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
553
+ filterset_class = NetworkFilter
554
+ ordering_fields = ("name",)
555
+ ordering = ("name",)
556
+
557
+ def get_queryset(self):
558
+ return Network.objects.public()
559
+
560
+
561
+ class ArchiveViewSet(
562
+ mixins.RetrieveModelMixin, DataTablesListMixin, viewsets.GenericViewSet
563
+ ):
564
+ serializer_class = ArchiveSerializer
565
+ permission_classes = []
566
+
567
+ class ArchiveFilter(CrispyFormCompat, FilterSet):
568
+ site = django_filters.CharFilter(
569
+ field_name="site__name",
570
+ help_text=_("The site of the archived log to download."),
571
+ )
572
+
573
+ log_format = EnumFilter(
574
+ enum=SiteLogFormat,
575
+ help_text=_("The format of the archived log to download."),
576
+ )
577
+
578
+ epoch = SLMDateTimeFilter(
579
+ method="at_epoch",
580
+ initial=lambda: datetime.now(),
581
+ help_text=_(
582
+ "Get the archive that was active at this given date or " "datetime."
583
+ ),
584
+ )
585
+
586
+ def at_epoch(self, queryset, name, value):
587
+ return queryset.filter(
588
+ Q(index__begin__lte=value)
589
+ & (Q(index__end__isnull=True) | Q(index__end__gt=value))
590
+ )
591
+
592
+ class Meta:
593
+ model = ArchivedSiteLog
594
+ fields = ["site", "epoch", "log_format"]
595
+
596
+ filter_backends = (DjangoFilterBackend, OrderingFilter)
597
+ filterset_class = ArchiveFilter
598
+ ordering_fields = ("timestamp",)
599
+ ordering = ("-timestamp",)
600
+
601
+ def retrieve(self, request, *args, **kwargs):
602
+ archive = self.get_object()
603
+ return FileResponse(archive.file, filename=archive.name)
604
+
605
+ def get_queryset(self):
606
+ return ArchivedSiteLog.objects.select_related("index", "site")