is the command to do this on unixy systems
+
+# runs tests in the context of the django development server
+# by default the --verbose flag is passed to pytest for more detailed output
+# all arguments passed to this script are passed to pytest
+
+docker compose -f docker-compose.dev.yml exec web pytest -v $*
diff --git a/static/leaflet.ajax.js b/static/leaflet.ajax.js
new file mode 100644
index 00000000..8f5b5d83
--- /dev/null
+++ b/static/leaflet.ajax.js
@@ -0,0 +1,690 @@
+(function e(t, n, r) {
+ function s(o, u) {
+ if (!n[o]) {
+ if (!t[o]) {
+ var a = typeof require == "function" && require;
+ if (!u && a) return a(o, !0);
+ if (i) return i(o, !0);
+ var f = new Error("Cannot find module '" + o + "'");
+ throw ((f.code = "MODULE_NOT_FOUND"), f);
+ }
+ var l = (n[o] = { exports: {} });
+ t[o][0].call(
+ l.exports,
+ function (e) {
+ var n = t[o][1][e];
+ return s(n ? n : e);
+ },
+ l,
+ l.exports,
+ e,
+ t,
+ n,
+ r
+ );
+ }
+ return n[o].exports;
+ }
+ var i = typeof require == "function" && require;
+ for (var o = 0; o < r.length; o++) s(r[o]);
+ return s;
+})(
+ {
+ 1: [
+ function (require, module, exports) {
+ "use strict";
+ var immediate = require("immediate");
+
+ /* istanbul ignore next */
+ function INTERNAL() {}
+
+ var handlers = {};
+
+ var REJECTED = ["REJECTED"];
+ var FULFILLED = ["FULFILLED"];
+ var PENDING = ["PENDING"];
+
+ module.exports = exports = Promise;
+
+ function Promise(resolver) {
+ if (typeof resolver !== "function") {
+ throw new TypeError("resolver must be a function");
+ }
+ this.state = PENDING;
+ this.queue = [];
+ this.outcome = void 0;
+ if (resolver !== INTERNAL) {
+ safelyResolveThenable(this, resolver);
+ }
+ }
+
+ Promise.prototype["catch"] = function (onRejected) {
+ return this.then(null, onRejected);
+ };
+ Promise.prototype.then = function (onFulfilled, onRejected) {
+ if (
+ (typeof onFulfilled !== "function" && this.state === FULFILLED) ||
+ (typeof onRejected !== "function" && this.state === REJECTED)
+ ) {
+ return this;
+ }
+ var promise = new this.constructor(INTERNAL);
+ if (this.state !== PENDING) {
+ var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
+ unwrap(promise, resolver, this.outcome);
+ } else {
+ this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
+ }
+
+ return promise;
+ };
+ function QueueItem(promise, onFulfilled, onRejected) {
+ this.promise = promise;
+ if (typeof onFulfilled === "function") {
+ this.onFulfilled = onFulfilled;
+ this.callFulfilled = this.otherCallFulfilled;
+ }
+ if (typeof onRejected === "function") {
+ this.onRejected = onRejected;
+ this.callRejected = this.otherCallRejected;
+ }
+ }
+ QueueItem.prototype.callFulfilled = function (value) {
+ handlers.resolve(this.promise, value);
+ };
+ QueueItem.prototype.otherCallFulfilled = function (value) {
+ unwrap(this.promise, this.onFulfilled, value);
+ };
+ QueueItem.prototype.callRejected = function (value) {
+ handlers.reject(this.promise, value);
+ };
+ QueueItem.prototype.otherCallRejected = function (value) {
+ unwrap(this.promise, this.onRejected, value);
+ };
+
+ function unwrap(promise, func, value) {
+ immediate(function () {
+ var returnValue;
+ try {
+ returnValue = func(value);
+ } catch (e) {
+ return handlers.reject(promise, e);
+ }
+ if (returnValue === promise) {
+ handlers.reject(
+ promise,
+ new TypeError("Cannot resolve promise with itself")
+ );
+ } else {
+ handlers.resolve(promise, returnValue);
+ }
+ });
+ }
+
+ handlers.resolve = function (self, value) {
+ var result = tryCatch(getThen, value);
+ if (result.status === "error") {
+ return handlers.reject(self, result.value);
+ }
+ var thenable = result.value;
+
+ if (thenable) {
+ safelyResolveThenable(self, thenable);
+ } else {
+ self.state = FULFILLED;
+ self.outcome = value;
+ var i = -1;
+ var len = self.queue.length;
+ while (++i < len) {
+ self.queue[i].callFulfilled(value);
+ }
+ }
+ return self;
+ };
+ handlers.reject = function (self, error) {
+ self.state = REJECTED;
+ self.outcome = error;
+ var i = -1;
+ var len = self.queue.length;
+ while (++i < len) {
+ self.queue[i].callRejected(error);
+ }
+ return self;
+ };
+
+ function getThen(obj) {
+ // Make sure we only access the accessor once as required by the spec
+ var then = obj && obj.then;
+ if (obj && typeof obj === "object" && typeof then === "function") {
+ return function appyThen() {
+ then.apply(obj, arguments);
+ };
+ }
+ }
+
+ function safelyResolveThenable(self, thenable) {
+ // Either fulfill, reject or reject with error
+ var called = false;
+ function onError(value) {
+ if (called) {
+ return;
+ }
+ called = true;
+ handlers.reject(self, value);
+ }
+
+ function onSuccess(value) {
+ if (called) {
+ return;
+ }
+ called = true;
+ handlers.resolve(self, value);
+ }
+
+ function tryToUnwrap() {
+ thenable(onSuccess, onError);
+ }
+
+ var result = tryCatch(tryToUnwrap);
+ if (result.status === "error") {
+ onError(result.value);
+ }
+ }
+
+ function tryCatch(func, value) {
+ var out = {};
+ try {
+ out.value = func(value);
+ out.status = "success";
+ } catch (e) {
+ out.status = "error";
+ out.value = e;
+ }
+ return out;
+ }
+
+ exports.resolve = resolve;
+ function resolve(value) {
+ if (value instanceof this) {
+ return value;
+ }
+ return handlers.resolve(new this(INTERNAL), value);
+ }
+
+ exports.reject = reject;
+ function reject(reason) {
+ var promise = new this(INTERNAL);
+ return handlers.reject(promise, reason);
+ }
+
+ exports.all = all;
+ function all(iterable) {
+ var self = this;
+ if (Object.prototype.toString.call(iterable) !== "[object Array]") {
+ return this.reject(new TypeError("must be an array"));
+ }
+
+ var len = iterable.length;
+ var called = false;
+ if (!len) {
+ return this.resolve([]);
+ }
+
+ var values = new Array(len);
+ var resolved = 0;
+ var i = -1;
+ var promise = new this(INTERNAL);
+
+ while (++i < len) {
+ allResolver(iterable[i], i);
+ }
+ return promise;
+ function allResolver(value, i) {
+ self.resolve(value).then(resolveFromAll, function (error) {
+ if (!called) {
+ called = true;
+ handlers.reject(promise, error);
+ }
+ });
+ function resolveFromAll(outValue) {
+ values[i] = outValue;
+ if (++resolved === len && !called) {
+ called = true;
+ handlers.resolve(promise, values);
+ }
+ }
+ }
+ }
+
+ exports.race = race;
+ function race(iterable) {
+ var self = this;
+ if (Object.prototype.toString.call(iterable) !== "[object Array]") {
+ return this.reject(new TypeError("must be an array"));
+ }
+
+ var len = iterable.length;
+ var called = false;
+ if (!len) {
+ return this.resolve([]);
+ }
+
+ var i = -1;
+ var promise = new this(INTERNAL);
+
+ while (++i < len) {
+ resolver(iterable[i]);
+ }
+ return promise;
+ function resolver(value) {
+ self.resolve(value).then(
+ function (response) {
+ if (!called) {
+ called = true;
+ handlers.resolve(promise, response);
+ }
+ },
+ function (error) {
+ if (!called) {
+ called = true;
+ handlers.reject(promise, error);
+ }
+ }
+ );
+ }
+ }
+ },
+ { immediate: 2 },
+ ],
+ 2: [
+ function (require, module, exports) {
+ (function (global) {
+ "use strict";
+ var Mutation =
+ global.MutationObserver || global.WebKitMutationObserver;
+
+ var scheduleDrain;
+
+ {
+ if (Mutation) {
+ var called = 0;
+ var observer = new Mutation(nextTick);
+ var element = global.document.createTextNode("");
+ observer.observe(element, {
+ characterData: true,
+ });
+ scheduleDrain = function () {
+ element.data = called = ++called % 2;
+ };
+ } else if (
+ !global.setImmediate &&
+ typeof global.MessageChannel !== "undefined"
+ ) {
+ var channel = new global.MessageChannel();
+ channel.port1.onmessage = nextTick;
+ scheduleDrain = function () {
+ channel.port2.postMessage(0);
+ };
+ } else if (
+ "document" in global &&
+ "onreadystatechange" in global.document.createElement("script")
+ ) {
+ scheduleDrain = function () {
+ // Create a
@@ -48,7 +53,12 @@
This site is currently under development.
-
+
+
+ {{ redirect_to_login_immediately }}
+
+
+
@@ -60,9 +70,8 @@
-
- {{ redirect_to_login_immediately }}
-
+
+
-