- Hi, {{user.first_name}} + Today, {% now "D, M j" %} - Today, {% now "D, M j" %} + Events {% for event in today %} {{event.date|date:"D, M j"}} @@ -21,12 +26,10 @@ Edit {% empty %} - Nothing for today. + No events for today. {% endfor %} - - Add event - + {% if upcoming_events %} Upcoming (next seven days) {% for event in upcoming_events %} @@ -42,7 +45,127 @@ {% endfor %} + {% endif %} See all events + + Add event + + + To-do's + + + Overdue + + {% regroup overdue_todos by employee as overdue_list %} + {% for employee in overdue_list %} + {{employee.grouper}} + {% for todo in employee.list %} + + + + {{todo.description}} + {% if todo.due_date %}{{todo.due_date}}{% endif %} + + {% if not todo.employee.archived %} + edit + delete + {% endif %} + + + + {% csrf_token %} + + + + + + cancel + + + + {% endfor %} + {% endfor %} + + + Due today + {% regroup todos by employee as todo_list %} + {% for employee in todo_list %} + {{employee.grouper}} + {% for todo in employee.list %} + + + + {{todo.description}} + {% if todo.due_date %}{{todo.due_date}}{% endif %} + + {% if not todo.employee.archived %} + edit + delete + {% endif %} + + + + {% csrf_token %} + + + + + + cancel + + + + {% endfor %} + {% endfor %} + + + Recent Activity diff --git a/accounts/views.py b/accounts/views.py index 3489992..0c8035c 100755 --- a/accounts/views.py +++ b/accounts/views.py @@ -13,7 +13,7 @@ from django.contrib.auth.models import User from .models import Profile from .forms import AccountUpdateForm, ProfileUpdateForm -from board.models import LogEntry, Event +from board.models import LogEntry, Event, Todo class ProfileView(LoginRequiredMixin, TemplateView): @@ -26,6 +26,14 @@ class ProfileView(LoginRequiredMixin, TemplateView): enddate = today + timedelta(days=7) context['profile'] = self.request.user.profile context['latest_activity'] = LogEntry.objects.all()[:10] + context['todos'] = Todo.objects.filter( + due_date=today, + completed=False + ) + context['overdue_todos'] = Todo.objects.filter( + due_date__lt=today, + completed=False + ) context['today'] = Event.objects.filter( date=today ) diff --git a/board/forms.py b/board/forms.py index 0305e3c..b57b9dd 100644 --- a/board/forms.py +++ b/board/forms.py @@ -71,23 +71,29 @@ class LogEntryForm(forms.ModelForm): class TodoForm(forms.ModelForm): class Meta: model = Todo - fields = ('completed', 'description') + fields = ('completed', 'description', 'due_date') widgets = { 'completed': forms.CheckboxInput(attrs = { 'class': 'todo__checkbox', }), 'description': forms.TextInput(attrs = { 'autofocus': 'autofocus' + }), + 'due_date': forms.DateInput(attrs = { + 'type': 'date' }) } class TodoCreateForm(forms.ModelForm): class Meta: model = Todo - fields = ('description',) + fields = ('description', 'due_date') widgets = { 'description': forms.TextInput(attrs = { 'autofocus': 'autofocus' + }), + 'due_date': forms.DateInput(attrs = { + 'type': 'date' }) } diff --git a/board/migrations/0002_todo_due_date.py b/board/migrations/0002_todo_due_date.py new file mode 100644 index 0000000..ef37bab --- /dev/null +++ b/board/migrations/0002_todo_due_date.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.5 on 2021-08-04 22:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('board', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='todo', + name='due_date', + field=models.DateField(blank=True, null=True), + ), + ] diff --git a/board/models.py b/board/models.py index 2bb444f..d92f91e 100644 --- a/board/models.py +++ b/board/models.py @@ -1,5 +1,6 @@ from django.db import models from django.urls import reverse_lazy, reverse +from datetime import datetime from django.utils import timezone @@ -48,10 +49,18 @@ class LogEntry(models.Model): class Todo(models.Model): employee = models.ForeignKey(Employee, on_delete=models.CASCADE) description = models.CharField(max_length=64) + due_date = models.DateField(blank=True, null=True) completed = models.BooleanField(default=False) completed_at = models.DateTimeField(blank=True, null=True) + def is_due(self): + today = timezone.localtime(timezone.now()).date() + if self.due_date == today: + return True + else: + return False + def __str__(self): return f"{self.employee}: {self.description}" diff --git a/board/templates/board/employee_detail.html b/board/templates/board/employee_detail.html index 4f57e28..c1e3972 100644 --- a/board/templates/board/employee_detail.html +++ b/board/templates/board/employee_detail.html @@ -2,6 +2,7 @@ {% load static %} {% block head %} + {% endblock %} diff --git a/board/templates/board/todo_detail.html b/board/templates/board/todo_detail.html index 34e6ec3..207bee5 100644 --- a/board/templates/board/todo_detail.html +++ b/board/templates/board/todo_detail.html @@ -1,13 +1,46 @@ - - - - - - {{todo.description}} - - {% if not employee.archived %} - Edit… - Delete… - {% endif %} + + + + {{todo.description}} + {% if todo.due_date %}{{todo.due_date}}{% endif %} + + {% if not employee.archived %} + edit + delete + {% endif %} + + + + {% csrf_token %} + + + + + + cancel + \ No newline at end of file diff --git a/board/templates/board/todo_list.html b/board/templates/board/todo_list.html index 0372432..d090522 100644 --- a/board/templates/board/todo_list.html +++ b/board/templates/board/todo_list.html @@ -1,4 +1,4 @@ - + {% for todo in todo_list %} {% include "board/todo_detail.html" with todo=todo %} {% endfor %} diff --git a/onboard/celery.py b/onboard/celery.py index 0fa169f..2f48a21 100644 --- a/onboard/celery.py +++ b/onboard/celery.py @@ -3,7 +3,7 @@ import os from celery import Celery # Set the default Django settings module for the 'celery' program. -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'onboard.settings_dev') +# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'onboard.settings_dev') app = Celery('onboard') diff --git a/static/images/checkmark.svg b/static/images/checkmark.svg new file mode 100644 index 0000000..88f2812 --- /dev/null +++ b/static/images/checkmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/scripts/controllers/todo_controller.js b/static/scripts/controllers/todo_controller.js new file mode 100644 index 0000000..473db35 --- /dev/null +++ b/static/scripts/controllers/todo_controller.js @@ -0,0 +1,140 @@ +import getCookie from "../get_cookie.js"; + +export default class extends Stimulus.Controller { + static values = { url: String, deleteUrl: String } + static get targets() { + return [ "completed", "form", "display", "checkbox" ] + } + + connect() { + this.editing = false + } + + // load() { + // fetch(`${this.urlValue}`) + // .then((response) => response.text()) + // .then((html) => { + // this.formTarget.innerHTML = html; + // if (this.formTarget.querySelector("[name=destroy]")) { + // this.destroyButton = this.formTarget.querySelector("[name=destroy]") + // this.destroyButton.addEventListener("click", this.destroy.bind(this)) + // } + // if (this.formTarget.querySelector("[name=edit]")) { + // this.editButton = this.formTarget.querySelector("[name=edit]") + // this.editButton.addEventListener("click", this.edit.bind(this)) + // } + // }) + // } + + validate() { + const inputs = new Set() + this.formTarget.querySelectorAll("input").forEach(input => { + inputs.add(input.checkValidity()) + }) + + let valid = (inputs.has(false)) ? false : true + + return valid + } + + change(event) { + if (event.target.type === "checkbox") { + this.post(event) + } + } + + edit(event) { + this.formTarget.classList.remove("--hidden") + this.displayTarget.classList.add("--hidden") + this.editing = true + } + + toggle(event) { + if (this.checkboxTarget.checked == true) { + this.checkboxTarget.checked = false + } else { + this.checkboxTarget.checked = true + } + if (this.validate()) { + this.post() + } + } + + cancel(event) { + if (event) { + event.preventDefault() + } + if (this.editing) { + this.formTarget.classList.add("--hidden") + this.displayTarget.classList.remove("--hidden") + this.editing = false + } + } + + + post(event) { + if (event) { + event.preventDefault() + } + // construct a new FormData object from the html form + const formData = new FormData(this.formTarget) + + // get the csrftoken + const csrftoken = getCookie("csrftoken") + + const options = { + method: "POST", + body: new URLSearchParams(formData), + mode: "same-origin", + }; + + // construct a new Request passing in the csrftoken + const request = new Request(`${this.urlValue}`, { + headers: { "X-CSRFToken": csrftoken }, + }) + + // finally make the post request and wait for the server to respond + fetch(request, options) + .then((response) => response.text()) + .then((html) => { + this.element.outerHTML = html + }) + .catch((error) => { + return error; + }) + } + + destroy(event) { + const confirmation = confirm( + "Are you sure you would like to delete this entry?" + ) + + if (confirmation) { + // get the csrftoken + const csrftoken = getCookie("csrftoken") + + const options = { + method: "POST", + mode: "same-origin", + }; + + // construct a new Request passing in the csrftoken + const request = new Request(`${this.deleteUrlValue}`, { + headers: { "X-CSRFToken": csrftoken }, + }) + + // finally make the post request and wait for the server to respond + fetch(request, options) + .then((response) => response.text()) + .then((html) => { + this.element.innerHTML = html; + setTimeout(() => { + this.element.remove() + }, 3000) + }) + .catch((error) => { + return error; + }) + } + } +} \ No newline at end of file diff --git a/static/scripts/index.js b/static/scripts/index.js index 13c460f..8ffd283 100644 --- a/static/scripts/index.js +++ b/static/scripts/index.js @@ -1,11 +1,20 @@ -import Form from "./form.js"; -import View from "./view.js"; +// import Form from "./form.js"; +// import View from "./view.js"; + +// import TodoListController from "./controllers/todo_list_controller.js" +import TodoController from "./controllers/todo_controller.js" // constructor(element, forms, templateName, addButton, destination) -const todoListView = new View( - document.querySelector("#todos"), - ".todo_form", - "#todo__list" -) \ No newline at end of file +// const todoListView = new View( +// document.querySelector("#todos"), +// ".todo_form", +// "#todo__list" +// ) + + + +const application = Stimulus.Application.start() +// application.register("todo-list", TodoListController) +application.register("todo", TodoController) diff --git a/static/scripts/stimulus.umd.js b/static/scripts/stimulus.umd.js new file mode 100644 index 0000000..d9e5c40 --- /dev/null +++ b/static/scripts/stimulus.umd.js @@ -0,0 +1,2294 @@ +/* +Stimulus 2.0.0 +Copyright © 2020 Basecamp, LLC + */ +(function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, + factory(global.Stimulus = {})); +})(this, (function(exports) { + "use strict"; + var EventListener = function() { + function EventListener(eventTarget, eventName, eventOptions) { + this.eventTarget = eventTarget; + this.eventName = eventName; + this.eventOptions = eventOptions; + this.unorderedBindings = new Set; + } + EventListener.prototype.connect = function() { + this.eventTarget.addEventListener(this.eventName, this, this.eventOptions); + }; + EventListener.prototype.disconnect = function() { + this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions); + }; + EventListener.prototype.bindingConnected = function(binding) { + this.unorderedBindings.add(binding); + }; + EventListener.prototype.bindingDisconnected = function(binding) { + this.unorderedBindings.delete(binding); + }; + EventListener.prototype.handleEvent = function(event) { + var extendedEvent = extendEvent(event); + for (var _i = 0, _a = this.bindings; _i < _a.length; _i++) { + var binding = _a[_i]; + if (extendedEvent.immediatePropagationStopped) { + break; + } else { + binding.handleEvent(extendedEvent); + } + } + }; + Object.defineProperty(EventListener.prototype, "bindings", { + get: function() { + return Array.from(this.unorderedBindings).sort((function(left, right) { + var leftIndex = left.index, rightIndex = right.index; + return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0; + })); + }, + enumerable: false, + configurable: true + }); + return EventListener; + }(); + function extendEvent(event) { + if ("immediatePropagationStopped" in event) { + return event; + } else { + var stopImmediatePropagation_1 = event.stopImmediatePropagation; + return Object.assign(event, { + immediatePropagationStopped: false, + stopImmediatePropagation: function() { + this.immediatePropagationStopped = true; + stopImmediatePropagation_1.call(this); + } + }); + } + } + var Dispatcher = function() { + function Dispatcher(application) { + this.application = application; + this.eventListenerMaps = new Map; + this.started = false; + } + Dispatcher.prototype.start = function() { + if (!this.started) { + this.started = true; + this.eventListeners.forEach((function(eventListener) { + return eventListener.connect(); + })); + } + }; + Dispatcher.prototype.stop = function() { + if (this.started) { + this.started = false; + this.eventListeners.forEach((function(eventListener) { + return eventListener.disconnect(); + })); + } + }; + Object.defineProperty(Dispatcher.prototype, "eventListeners", { + get: function() { + return Array.from(this.eventListenerMaps.values()).reduce((function(listeners, map) { + return listeners.concat(Array.from(map.values())); + }), []); + }, + enumerable: false, + configurable: true + }); + Dispatcher.prototype.bindingConnected = function(binding) { + this.fetchEventListenerForBinding(binding).bindingConnected(binding); + }; + Dispatcher.prototype.bindingDisconnected = function(binding) { + this.fetchEventListenerForBinding(binding).bindingDisconnected(binding); + }; + Dispatcher.prototype.handleError = function(error, message, detail) { + if (detail === void 0) { + detail = {}; + } + this.application.handleError(error, "Error " + message, detail); + }; + Dispatcher.prototype.fetchEventListenerForBinding = function(binding) { + var eventTarget = binding.eventTarget, eventName = binding.eventName, eventOptions = binding.eventOptions; + return this.fetchEventListener(eventTarget, eventName, eventOptions); + }; + Dispatcher.prototype.fetchEventListener = function(eventTarget, eventName, eventOptions) { + var eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); + var cacheKey = this.cacheKey(eventName, eventOptions); + var eventListener = eventListenerMap.get(cacheKey); + if (!eventListener) { + eventListener = this.createEventListener(eventTarget, eventName, eventOptions); + eventListenerMap.set(cacheKey, eventListener); + } + return eventListener; + }; + Dispatcher.prototype.createEventListener = function(eventTarget, eventName, eventOptions) { + var eventListener = new EventListener(eventTarget, eventName, eventOptions); + if (this.started) { + eventListener.connect(); + } + return eventListener; + }; + Dispatcher.prototype.fetchEventListenerMapForEventTarget = function(eventTarget) { + var eventListenerMap = this.eventListenerMaps.get(eventTarget); + if (!eventListenerMap) { + eventListenerMap = new Map; + this.eventListenerMaps.set(eventTarget, eventListenerMap); + } + return eventListenerMap; + }; + Dispatcher.prototype.cacheKey = function(eventName, eventOptions) { + var parts = [ eventName ]; + Object.keys(eventOptions).sort().forEach((function(key) { + parts.push("" + (eventOptions[key] ? "" : "!") + key); + })); + return parts.join(":"); + }; + return Dispatcher; + }(); + var descriptorPattern = /^((.+?)(@(window|document))?->)?(.+?)(#([^:]+?))(:(.+))?$/; + function parseActionDescriptorString(descriptorString) { + var source = descriptorString.trim(); + var matches = source.match(descriptorPattern) || []; + return { + eventTarget: parseEventTarget(matches[4]), + eventName: matches[2], + eventOptions: matches[9] ? parseEventOptions(matches[9]) : {}, + identifier: matches[5], + methodName: matches[7] + }; + } + function parseEventTarget(eventTargetName) { + if (eventTargetName == "window") { + return window; + } else if (eventTargetName == "document") { + return document; + } + } + function parseEventOptions(eventOptions) { + return eventOptions.split(":").reduce((function(options, token) { + var _a; + return Object.assign(options, (_a = {}, _a[token.replace(/^!/, "")] = !/^!/.test(token), + _a)); + }), {}); + } + function stringifyEventTarget(eventTarget) { + if (eventTarget == window) { + return "window"; + } else if (eventTarget == document) { + return "document"; + } + } + var Action = function() { + function Action(element, index, descriptor) { + this.element = element; + this.index = index; + this.eventTarget = descriptor.eventTarget || element; + this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name"); + this.eventOptions = descriptor.eventOptions || {}; + this.identifier = descriptor.identifier || error("missing identifier"); + this.methodName = descriptor.methodName || error("missing method name"); + } + Action.forToken = function(token) { + return new this(token.element, token.index, parseActionDescriptorString(token.content)); + }; + Action.prototype.toString = function() { + var eventNameSuffix = this.eventTargetName ? "@" + this.eventTargetName : ""; + return "" + this.eventName + eventNameSuffix + "->" + this.identifier + "#" + this.methodName; + }; + Object.defineProperty(Action.prototype, "eventTargetName", { + get: function() { + return stringifyEventTarget(this.eventTarget); + }, + enumerable: false, + configurable: true + }); + return Action; + }(); + var defaultEventNames = { + a: function(e) { + return "click"; + }, + button: function(e) { + return "click"; + }, + form: function(e) { + return "submit"; + }, + input: function(e) { + return e.getAttribute("type") == "submit" ? "click" : "input"; + }, + select: function(e) { + return "change"; + }, + textarea: function(e) { + return "input"; + } + }; + function getDefaultEventNameForElement(element) { + var tagName = element.tagName.toLowerCase(); + if (tagName in defaultEventNames) { + return defaultEventNames[tagName](element); + } + } + function error(message) { + throw new Error(message); + } + var Binding = function() { + function Binding(context, action) { + this.context = context; + this.action = action; + } + Object.defineProperty(Binding.prototype, "index", { + get: function() { + return this.action.index; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "eventTarget", { + get: function() { + return this.action.eventTarget; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "eventOptions", { + get: function() { + return this.action.eventOptions; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "identifier", { + get: function() { + return this.context.identifier; + }, + enumerable: false, + configurable: true + }); + Binding.prototype.handleEvent = function(event) { + if (this.willBeInvokedByEvent(event)) { + this.invokeWithEvent(event); + } + }; + Object.defineProperty(Binding.prototype, "eventName", { + get: function() { + return this.action.eventName; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "method", { + get: function() { + var method = this.controller[this.methodName]; + if (typeof method == "function") { + return method; + } + throw new Error('Action "' + this.action + '" references undefined method "' + this.methodName + '"'); + }, + enumerable: false, + configurable: true + }); + Binding.prototype.invokeWithEvent = function(event) { + try { + this.method.call(this.controller, event); + } catch (error) { + var _a = this, identifier = _a.identifier, controller = _a.controller, element = _a.element, index = _a.index; + var detail = { + identifier: identifier, + controller: controller, + element: element, + index: index, + event: event + }; + this.context.handleError(error, 'invoking action "' + this.action + '"', detail); + } + }; + Binding.prototype.willBeInvokedByEvent = function(event) { + var eventTarget = event.target; + if (this.element === eventTarget) { + return true; + } else if (eventTarget instanceof Element && this.element.contains(eventTarget)) { + return this.scope.containsElement(eventTarget); + } else { + return this.scope.containsElement(this.action.element); + } + }; + Object.defineProperty(Binding.prototype, "controller", { + get: function() { + return this.context.controller; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "methodName", { + get: function() { + return this.action.methodName; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "element", { + get: function() { + return this.scope.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Binding.prototype, "scope", { + get: function() { + return this.context.scope; + }, + enumerable: false, + configurable: true + }); + return Binding; + }(); + var ElementObserver = function() { + function ElementObserver(element, delegate) { + var _this = this; + this.element = element; + this.started = false; + this.delegate = delegate; + this.elements = new Set; + this.mutationObserver = new MutationObserver((function(mutations) { + return _this.processMutations(mutations); + })); + } + ElementObserver.prototype.start = function() { + if (!this.started) { + this.started = true; + this.mutationObserver.observe(this.element, { + attributes: true, + childList: true, + subtree: true + }); + this.refresh(); + } + }; + ElementObserver.prototype.stop = function() { + if (this.started) { + this.mutationObserver.takeRecords(); + this.mutationObserver.disconnect(); + this.started = false; + } + }; + ElementObserver.prototype.refresh = function() { + if (this.started) { + var matches = new Set(this.matchElementsInTree()); + for (var _i = 0, _a = Array.from(this.elements); _i < _a.length; _i++) { + var element = _a[_i]; + if (!matches.has(element)) { + this.removeElement(element); + } + } + for (var _b = 0, _c = Array.from(matches); _b < _c.length; _b++) { + var element = _c[_b]; + this.addElement(element); + } + } + }; + ElementObserver.prototype.processMutations = function(mutations) { + if (this.started) { + for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) { + var mutation = mutations_1[_i]; + this.processMutation(mutation); + } + } + }; + ElementObserver.prototype.processMutation = function(mutation) { + if (mutation.type == "attributes") { + this.processAttributeChange(mutation.target, mutation.attributeName); + } else if (mutation.type == "childList") { + this.processRemovedNodes(mutation.removedNodes); + this.processAddedNodes(mutation.addedNodes); + } + }; + ElementObserver.prototype.processAttributeChange = function(node, attributeName) { + var element = node; + if (this.elements.has(element)) { + if (this.delegate.elementAttributeChanged && this.matchElement(element)) { + this.delegate.elementAttributeChanged(element, attributeName); + } else { + this.removeElement(element); + } + } else if (this.matchElement(element)) { + this.addElement(element); + } + }; + ElementObserver.prototype.processRemovedNodes = function(nodes) { + for (var _i = 0, _a = Array.from(nodes); _i < _a.length; _i++) { + var node = _a[_i]; + var element = this.elementFromNode(node); + if (element) { + this.processTree(element, this.removeElement); + } + } + }; + ElementObserver.prototype.processAddedNodes = function(nodes) { + for (var _i = 0, _a = Array.from(nodes); _i < _a.length; _i++) { + var node = _a[_i]; + var element = this.elementFromNode(node); + if (element && this.elementIsActive(element)) { + this.processTree(element, this.addElement); + } + } + }; + ElementObserver.prototype.matchElement = function(element) { + return this.delegate.matchElement(element); + }; + ElementObserver.prototype.matchElementsInTree = function(tree) { + if (tree === void 0) { + tree = this.element; + } + return this.delegate.matchElementsInTree(tree); + }; + ElementObserver.prototype.processTree = function(tree, processor) { + for (var _i = 0, _a = this.matchElementsInTree(tree); _i < _a.length; _i++) { + var element = _a[_i]; + processor.call(this, element); + } + }; + ElementObserver.prototype.elementFromNode = function(node) { + if (node.nodeType == Node.ELEMENT_NODE) { + return node; + } + }; + ElementObserver.prototype.elementIsActive = function(element) { + if (element.isConnected != this.element.isConnected) { + return false; + } else { + return this.element.contains(element); + } + }; + ElementObserver.prototype.addElement = function(element) { + if (!this.elements.has(element)) { + if (this.elementIsActive(element)) { + this.elements.add(element); + if (this.delegate.elementMatched) { + this.delegate.elementMatched(element); + } + } + } + }; + ElementObserver.prototype.removeElement = function(element) { + if (this.elements.has(element)) { + this.elements.delete(element); + if (this.delegate.elementUnmatched) { + this.delegate.elementUnmatched(element); + } + } + }; + return ElementObserver; + }(); + var AttributeObserver = function() { + function AttributeObserver(element, attributeName, delegate) { + this.attributeName = attributeName; + this.delegate = delegate; + this.elementObserver = new ElementObserver(element, this); + } + Object.defineProperty(AttributeObserver.prototype, "element", { + get: function() { + return this.elementObserver.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(AttributeObserver.prototype, "selector", { + get: function() { + return "[" + this.attributeName + "]"; + }, + enumerable: false, + configurable: true + }); + AttributeObserver.prototype.start = function() { + this.elementObserver.start(); + }; + AttributeObserver.prototype.stop = function() { + this.elementObserver.stop(); + }; + AttributeObserver.prototype.refresh = function() { + this.elementObserver.refresh(); + }; + Object.defineProperty(AttributeObserver.prototype, "started", { + get: function() { + return this.elementObserver.started; + }, + enumerable: false, + configurable: true + }); + AttributeObserver.prototype.matchElement = function(element) { + return element.hasAttribute(this.attributeName); + }; + AttributeObserver.prototype.matchElementsInTree = function(tree) { + var match = this.matchElement(tree) ? [ tree ] : []; + var matches = Array.from(tree.querySelectorAll(this.selector)); + return match.concat(matches); + }; + AttributeObserver.prototype.elementMatched = function(element) { + if (this.delegate.elementMatchedAttribute) { + this.delegate.elementMatchedAttribute(element, this.attributeName); + } + }; + AttributeObserver.prototype.elementUnmatched = function(element) { + if (this.delegate.elementUnmatchedAttribute) { + this.delegate.elementUnmatchedAttribute(element, this.attributeName); + } + }; + AttributeObserver.prototype.elementAttributeChanged = function(element, attributeName) { + if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) { + this.delegate.elementAttributeValueChanged(element, attributeName); + } + }; + return AttributeObserver; + }(); + var StringMapObserver = function() { + function StringMapObserver(element, delegate) { + var _this = this; + this.element = element; + this.delegate = delegate; + this.started = false; + this.stringMap = new Map; + this.mutationObserver = new MutationObserver((function(mutations) { + return _this.processMutations(mutations); + })); + } + StringMapObserver.prototype.start = function() { + if (!this.started) { + this.started = true; + this.mutationObserver.observe(this.element, { + attributes: true + }); + this.refresh(); + } + }; + StringMapObserver.prototype.stop = function() { + if (this.started) { + this.mutationObserver.takeRecords(); + this.mutationObserver.disconnect(); + this.started = false; + } + }; + StringMapObserver.prototype.refresh = function() { + if (this.started) { + for (var _i = 0, _a = this.knownAttributeNames; _i < _a.length; _i++) { + var attributeName = _a[_i]; + this.refreshAttribute(attributeName); + } + } + }; + StringMapObserver.prototype.processMutations = function(mutations) { + if (this.started) { + for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) { + var mutation = mutations_1[_i]; + this.processMutation(mutation); + } + } + }; + StringMapObserver.prototype.processMutation = function(mutation) { + var attributeName = mutation.attributeName; + if (attributeName) { + this.refreshAttribute(attributeName); + } + }; + StringMapObserver.prototype.refreshAttribute = function(attributeName) { + var key = this.delegate.getStringMapKeyForAttribute(attributeName); + if (key != null) { + if (!this.stringMap.has(attributeName)) { + this.stringMapKeyAdded(key, attributeName); + } + var value = this.element.getAttribute(attributeName); + if (this.stringMap.get(attributeName) != value) { + this.stringMapValueChanged(value, key); + } + if (value == null) { + this.stringMap.delete(attributeName); + this.stringMapKeyRemoved(key, attributeName); + } else { + this.stringMap.set(attributeName, value); + } + } + }; + StringMapObserver.prototype.stringMapKeyAdded = function(key, attributeName) { + if (this.delegate.stringMapKeyAdded) { + this.delegate.stringMapKeyAdded(key, attributeName); + } + }; + StringMapObserver.prototype.stringMapValueChanged = function(value, key) { + if (this.delegate.stringMapValueChanged) { + this.delegate.stringMapValueChanged(value, key); + } + }; + StringMapObserver.prototype.stringMapKeyRemoved = function(key, attributeName) { + if (this.delegate.stringMapKeyRemoved) { + this.delegate.stringMapKeyRemoved(key, attributeName); + } + }; + Object.defineProperty(StringMapObserver.prototype, "knownAttributeNames", { + get: function() { + return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames))); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(StringMapObserver.prototype, "currentAttributeNames", { + get: function() { + return Array.from(this.element.attributes).map((function(attribute) { + return attribute.name; + })); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(StringMapObserver.prototype, "recordedAttributeNames", { + get: function() { + return Array.from(this.stringMap.keys()); + }, + enumerable: false, + configurable: true + }); + return StringMapObserver; + }(); + function add(map, key, value) { + fetch(map, key).add(value); + } + function del(map, key, value) { + fetch(map, key).delete(value); + prune(map, key); + } + function fetch(map, key) { + var values = map.get(key); + if (!values) { + values = new Set; + map.set(key, values); + } + return values; + } + function prune(map, key) { + var values = map.get(key); + if (values != null && values.size == 0) { + map.delete(key); + } + } + var Multimap = function() { + function Multimap() { + this.valuesByKey = new Map; + } + Object.defineProperty(Multimap.prototype, "values", { + get: function() { + var sets = Array.from(this.valuesByKey.values()); + return sets.reduce((function(values, set) { + return values.concat(Array.from(set)); + }), []); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Multimap.prototype, "size", { + get: function() { + var sets = Array.from(this.valuesByKey.values()); + return sets.reduce((function(size, set) { + return size + set.size; + }), 0); + }, + enumerable: false, + configurable: true + }); + Multimap.prototype.add = function(key, value) { + add(this.valuesByKey, key, value); + }; + Multimap.prototype.delete = function(key, value) { + del(this.valuesByKey, key, value); + }; + Multimap.prototype.has = function(key, value) { + var values = this.valuesByKey.get(key); + return values != null && values.has(value); + }; + Multimap.prototype.hasKey = function(key) { + return this.valuesByKey.has(key); + }; + Multimap.prototype.hasValue = function(value) { + var sets = Array.from(this.valuesByKey.values()); + return sets.some((function(set) { + return set.has(value); + })); + }; + Multimap.prototype.getValuesForKey = function(key) { + var values = this.valuesByKey.get(key); + return values ? Array.from(values) : []; + }; + Multimap.prototype.getKeysForValue = function(value) { + return Array.from(this.valuesByKey).filter((function(_a) { + var key = _a[0], values = _a[1]; + return values.has(value); + })).map((function(_a) { + var key = _a[0], values = _a[1]; + return key; + })); + }; + return Multimap; + }(); + var __extends = window && window.__extends || function() { + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || { + __proto__: [] + } instanceof Array && function(d, b) { + d.__proto__ = b; + } || function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __); + }; + }(); + var IndexedMultimap = function(_super) { + __extends(IndexedMultimap, _super); + function IndexedMultimap() { + var _this = _super.call(this) || this; + _this.keysByValue = new Map; + return _this; + } + Object.defineProperty(IndexedMultimap.prototype, "values", { + get: function() { + return Array.from(this.keysByValue.keys()); + }, + enumerable: false, + configurable: true + }); + IndexedMultimap.prototype.add = function(key, value) { + _super.prototype.add.call(this, key, value); + add(this.keysByValue, value, key); + }; + IndexedMultimap.prototype.delete = function(key, value) { + _super.prototype.delete.call(this, key, value); + del(this.keysByValue, value, key); + }; + IndexedMultimap.prototype.hasValue = function(value) { + return this.keysByValue.has(value); + }; + IndexedMultimap.prototype.getKeysForValue = function(value) { + var set = this.keysByValue.get(value); + return set ? Array.from(set) : []; + }; + return IndexedMultimap; + }(Multimap); + var TokenListObserver = function() { + function TokenListObserver(element, attributeName, delegate) { + this.attributeObserver = new AttributeObserver(element, attributeName, this); + this.delegate = delegate; + this.tokensByElement = new Multimap; + } + Object.defineProperty(TokenListObserver.prototype, "started", { + get: function() { + return this.attributeObserver.started; + }, + enumerable: false, + configurable: true + }); + TokenListObserver.prototype.start = function() { + this.attributeObserver.start(); + }; + TokenListObserver.prototype.stop = function() { + this.attributeObserver.stop(); + }; + TokenListObserver.prototype.refresh = function() { + this.attributeObserver.refresh(); + }; + Object.defineProperty(TokenListObserver.prototype, "element", { + get: function() { + return this.attributeObserver.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TokenListObserver.prototype, "attributeName", { + get: function() { + return this.attributeObserver.attributeName; + }, + enumerable: false, + configurable: true + }); + TokenListObserver.prototype.elementMatchedAttribute = function(element) { + this.tokensMatched(this.readTokensForElement(element)); + }; + TokenListObserver.prototype.elementAttributeValueChanged = function(element) { + var _a = this.refreshTokensForElement(element), unmatchedTokens = _a[0], matchedTokens = _a[1]; + this.tokensUnmatched(unmatchedTokens); + this.tokensMatched(matchedTokens); + }; + TokenListObserver.prototype.elementUnmatchedAttribute = function(element) { + this.tokensUnmatched(this.tokensByElement.getValuesForKey(element)); + }; + TokenListObserver.prototype.tokensMatched = function(tokens) { + var _this = this; + tokens.forEach((function(token) { + return _this.tokenMatched(token); + })); + }; + TokenListObserver.prototype.tokensUnmatched = function(tokens) { + var _this = this; + tokens.forEach((function(token) { + return _this.tokenUnmatched(token); + })); + }; + TokenListObserver.prototype.tokenMatched = function(token) { + this.delegate.tokenMatched(token); + this.tokensByElement.add(token.element, token); + }; + TokenListObserver.prototype.tokenUnmatched = function(token) { + this.delegate.tokenUnmatched(token); + this.tokensByElement.delete(token.element, token); + }; + TokenListObserver.prototype.refreshTokensForElement = function(element) { + var previousTokens = this.tokensByElement.getValuesForKey(element); + var currentTokens = this.readTokensForElement(element); + var firstDifferingIndex = zip(previousTokens, currentTokens).findIndex((function(_a) { + var previousToken = _a[0], currentToken = _a[1]; + return !tokensAreEqual(previousToken, currentToken); + })); + if (firstDifferingIndex == -1) { + return [ [], [] ]; + } else { + return [ previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex) ]; + } + }; + TokenListObserver.prototype.readTokensForElement = function(element) { + var attributeName = this.attributeName; + var tokenString = element.getAttribute(attributeName) || ""; + return parseTokenString(tokenString, element, attributeName); + }; + return TokenListObserver; + }(); + function parseTokenString(tokenString, element, attributeName) { + return tokenString.trim().split(/\s+/).filter((function(content) { + return content.length; + })).map((function(content, index) { + return { + element: element, + attributeName: attributeName, + content: content, + index: index + }; + })); + } + function zip(left, right) { + var length = Math.max(left.length, right.length); + return Array.from({ + length: length + }, (function(_, index) { + return [ left[index], right[index] ]; + })); + } + function tokensAreEqual(left, right) { + return left && right && left.index == right.index && left.content == right.content; + } + var ValueListObserver = function() { + function ValueListObserver(element, attributeName, delegate) { + this.tokenListObserver = new TokenListObserver(element, attributeName, this); + this.delegate = delegate; + this.parseResultsByToken = new WeakMap; + this.valuesByTokenByElement = new WeakMap; + } + Object.defineProperty(ValueListObserver.prototype, "started", { + get: function() { + return this.tokenListObserver.started; + }, + enumerable: false, + configurable: true + }); + ValueListObserver.prototype.start = function() { + this.tokenListObserver.start(); + }; + ValueListObserver.prototype.stop = function() { + this.tokenListObserver.stop(); + }; + ValueListObserver.prototype.refresh = function() { + this.tokenListObserver.refresh(); + }; + Object.defineProperty(ValueListObserver.prototype, "element", { + get: function() { + return this.tokenListObserver.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ValueListObserver.prototype, "attributeName", { + get: function() { + return this.tokenListObserver.attributeName; + }, + enumerable: false, + configurable: true + }); + ValueListObserver.prototype.tokenMatched = function(token) { + var element = token.element; + var value = this.fetchParseResultForToken(token).value; + if (value) { + this.fetchValuesByTokenForElement(element).set(token, value); + this.delegate.elementMatchedValue(element, value); + } + }; + ValueListObserver.prototype.tokenUnmatched = function(token) { + var element = token.element; + var value = this.fetchParseResultForToken(token).value; + if (value) { + this.fetchValuesByTokenForElement(element).delete(token); + this.delegate.elementUnmatchedValue(element, value); + } + }; + ValueListObserver.prototype.fetchParseResultForToken = function(token) { + var parseResult = this.parseResultsByToken.get(token); + if (!parseResult) { + parseResult = this.parseToken(token); + this.parseResultsByToken.set(token, parseResult); + } + return parseResult; + }; + ValueListObserver.prototype.fetchValuesByTokenForElement = function(element) { + var valuesByToken = this.valuesByTokenByElement.get(element); + if (!valuesByToken) { + valuesByToken = new Map; + this.valuesByTokenByElement.set(element, valuesByToken); + } + return valuesByToken; + }; + ValueListObserver.prototype.parseToken = function(token) { + try { + var value = this.delegate.parseValueForToken(token); + return { + value: value + }; + } catch (error) { + return { + error: error + }; + } + }; + return ValueListObserver; + }(); + var BindingObserver = function() { + function BindingObserver(context, delegate) { + this.context = context; + this.delegate = delegate; + this.bindingsByAction = new Map; + } + BindingObserver.prototype.start = function() { + if (!this.valueListObserver) { + this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this); + this.valueListObserver.start(); + } + }; + BindingObserver.prototype.stop = function() { + if (this.valueListObserver) { + this.valueListObserver.stop(); + delete this.valueListObserver; + this.disconnectAllActions(); + } + }; + Object.defineProperty(BindingObserver.prototype, "element", { + get: function() { + return this.context.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(BindingObserver.prototype, "identifier", { + get: function() { + return this.context.identifier; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(BindingObserver.prototype, "actionAttribute", { + get: function() { + return this.schema.actionAttribute; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(BindingObserver.prototype, "schema", { + get: function() { + return this.context.schema; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(BindingObserver.prototype, "bindings", { + get: function() { + return Array.from(this.bindingsByAction.values()); + }, + enumerable: false, + configurable: true + }); + BindingObserver.prototype.connectAction = function(action) { + var binding = new Binding(this.context, action); + this.bindingsByAction.set(action, binding); + this.delegate.bindingConnected(binding); + }; + BindingObserver.prototype.disconnectAction = function(action) { + var binding = this.bindingsByAction.get(action); + if (binding) { + this.bindingsByAction.delete(action); + this.delegate.bindingDisconnected(binding); + } + }; + BindingObserver.prototype.disconnectAllActions = function() { + var _this = this; + this.bindings.forEach((function(binding) { + return _this.delegate.bindingDisconnected(binding); + })); + this.bindingsByAction.clear(); + }; + BindingObserver.prototype.parseValueForToken = function(token) { + var action = Action.forToken(token); + if (action.identifier == this.identifier) { + return action; + } + }; + BindingObserver.prototype.elementMatchedValue = function(element, action) { + this.connectAction(action); + }; + BindingObserver.prototype.elementUnmatchedValue = function(element, action) { + this.disconnectAction(action); + }; + return BindingObserver; + }(); + var ValueObserver = function() { + function ValueObserver(context, receiver) { + this.context = context; + this.receiver = receiver; + this.stringMapObserver = new StringMapObserver(this.element, this); + this.valueDescriptorMap = this.controller.valueDescriptorMap; + this.invokeChangedCallbacksForDefaultValues(); + } + ValueObserver.prototype.start = function() { + this.stringMapObserver.start(); + }; + ValueObserver.prototype.stop = function() { + this.stringMapObserver.stop(); + }; + Object.defineProperty(ValueObserver.prototype, "element", { + get: function() { + return this.context.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(ValueObserver.prototype, "controller", { + get: function() { + return this.context.controller; + }, + enumerable: false, + configurable: true + }); + ValueObserver.prototype.getStringMapKeyForAttribute = function(attributeName) { + if (attributeName in this.valueDescriptorMap) { + return this.valueDescriptorMap[attributeName].name; + } + }; + ValueObserver.prototype.stringMapValueChanged = function(attributeValue, name) { + this.invokeChangedCallbackForValue(name); + }; + ValueObserver.prototype.invokeChangedCallbacksForDefaultValues = function() { + for (var _i = 0, _a = this.valueDescriptors; _i < _a.length; _i++) { + var _b = _a[_i], key = _b.key, name_1 = _b.name, defaultValue = _b.defaultValue; + if (defaultValue != undefined && !this.controller.data.has(key)) { + this.invokeChangedCallbackForValue(name_1); + } + } + }; + ValueObserver.prototype.invokeChangedCallbackForValue = function(name) { + var methodName = name + "Changed"; + var method = this.receiver[methodName]; + if (typeof method == "function") { + var value = this.receiver[name]; + method.call(this.receiver, value); + } + }; + Object.defineProperty(ValueObserver.prototype, "valueDescriptors", { + get: function() { + var valueDescriptorMap = this.valueDescriptorMap; + return Object.keys(valueDescriptorMap).map((function(key) { + return valueDescriptorMap[key]; + })); + }, + enumerable: false, + configurable: true + }); + return ValueObserver; + }(); + var Context = function() { + function Context(module, scope) { + this.module = module; + this.scope = scope; + this.controller = new module.controllerConstructor(this); + this.bindingObserver = new BindingObserver(this, this.dispatcher); + this.valueObserver = new ValueObserver(this, this.controller); + try { + this.controller.initialize(); + } catch (error) { + this.handleError(error, "initializing controller"); + } + } + Context.prototype.connect = function() { + this.bindingObserver.start(); + this.valueObserver.start(); + try { + this.controller.connect(); + } catch (error) { + this.handleError(error, "connecting controller"); + } + }; + Context.prototype.disconnect = function() { + try { + this.controller.disconnect(); + } catch (error) { + this.handleError(error, "disconnecting controller"); + } + this.valueObserver.stop(); + this.bindingObserver.stop(); + }; + Object.defineProperty(Context.prototype, "application", { + get: function() { + return this.module.application; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Context.prototype, "identifier", { + get: function() { + return this.module.identifier; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Context.prototype, "schema", { + get: function() { + return this.application.schema; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Context.prototype, "dispatcher", { + get: function() { + return this.application.dispatcher; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Context.prototype, "element", { + get: function() { + return this.scope.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Context.prototype, "parentElement", { + get: function() { + return this.element.parentElement; + }, + enumerable: false, + configurable: true + }); + Context.prototype.handleError = function(error, message, detail) { + if (detail === void 0) { + detail = {}; + } + var _a = this, identifier = _a.identifier, controller = _a.controller, element = _a.element; + detail = Object.assign({ + identifier: identifier, + controller: controller, + element: element + }, detail); + this.application.handleError(error, "Error " + message, detail); + }; + return Context; + }(); + function readInheritableStaticArrayValues(constructor, propertyName) { + var ancestors = getAncestorsForConstructor(constructor); + return Array.from(ancestors.reduce((function(values, constructor) { + getOwnStaticArrayValues(constructor, propertyName).forEach((function(name) { + return values.add(name); + })); + return values; + }), new Set)); + } + function readInheritableStaticObjectPairs(constructor, propertyName) { + var ancestors = getAncestorsForConstructor(constructor); + return ancestors.reduce((function(pairs, constructor) { + pairs.push.apply(pairs, getOwnStaticObjectPairs(constructor, propertyName)); + return pairs; + }), []); + } + function getAncestorsForConstructor(constructor) { + var ancestors = []; + while (constructor) { + ancestors.push(constructor); + constructor = Object.getPrototypeOf(constructor); + } + return ancestors.reverse(); + } + function getOwnStaticArrayValues(constructor, propertyName) { + var definition = constructor[propertyName]; + return Array.isArray(definition) ? definition : []; + } + function getOwnStaticObjectPairs(constructor, propertyName) { + var definition = constructor[propertyName]; + return definition ? Object.keys(definition).map((function(key) { + return [ key, definition[key] ]; + })) : []; + } + var __extends$1 = window && window.__extends || function() { + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || { + __proto__: [] + } instanceof Array && function(d, b) { + d.__proto__ = b; + } || function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); + }; + return function(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __); + }; + }(); + var __spreadArrays = window && window.__spreadArrays || function() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, + k++) r[k] = a[j]; + return r; + }; + function bless(constructor) { + return shadow(constructor, getBlessedProperties(constructor)); + } + function shadow(constructor, properties) { + var shadowConstructor = extend(constructor); + var shadowProperties = getShadowProperties(constructor.prototype, properties); + Object.defineProperties(shadowConstructor.prototype, shadowProperties); + return shadowConstructor; + } + function getBlessedProperties(constructor) { + var blessings = readInheritableStaticArrayValues(constructor, "blessings"); + return blessings.reduce((function(blessedProperties, blessing) { + var properties = blessing(constructor); + for (var key in properties) { + var descriptor = blessedProperties[key] || {}; + blessedProperties[key] = Object.assign(descriptor, properties[key]); + } + return blessedProperties; + }), {}); + } + function getShadowProperties(prototype, properties) { + return getOwnKeys(properties).reduce((function(shadowProperties, key) { + var _a; + var descriptor = getShadowedDescriptor(prototype, properties, key); + if (descriptor) { + Object.assign(shadowProperties, (_a = {}, _a[key] = descriptor, _a)); + } + return shadowProperties; + }), {}); + } + function getShadowedDescriptor(prototype, properties, key) { + var shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key); + var shadowedByValue = shadowingDescriptor && "value" in shadowingDescriptor; + if (!shadowedByValue) { + var descriptor = Object.getOwnPropertyDescriptor(properties, key).value; + if (shadowingDescriptor) { + descriptor.get = shadowingDescriptor.get || descriptor.get; + descriptor.set = shadowingDescriptor.set || descriptor.set; + } + return descriptor; + } + } + var getOwnKeys = function() { + if (typeof Object.getOwnPropertySymbols == "function") { + return function(object) { + return __spreadArrays(Object.getOwnPropertyNames(object), Object.getOwnPropertySymbols(object)); + }; + } else { + return Object.getOwnPropertyNames; + } + }(); + var extend = function() { + function extendWithReflect(constructor) { + function extended() { + var _newTarget = this && this instanceof extended ? this.constructor : void 0; + return Reflect.construct(constructor, arguments, _newTarget); + } + extended.prototype = Object.create(constructor.prototype, { + constructor: { + value: extended + } + }); + Reflect.setPrototypeOf(extended, constructor); + return extended; + } + function testReflectExtension() { + var a = function() { + this.a.call(this); + }; + var b = extendWithReflect(a); + b.prototype.a = function() {}; + return new b; + } + try { + testReflectExtension(); + return extendWithReflect; + } catch (error) { + return function(constructor) { + return function(_super) { + __extends$1(extended, _super); + function extended() { + return _super !== null && _super.apply(this, arguments) || this; + } + return extended; + }(constructor); + }; + } + }(); + function blessDefinition(definition) { + return { + identifier: definition.identifier, + controllerConstructor: bless(definition.controllerConstructor) + }; + } + var Module = function() { + function Module(application, definition) { + this.application = application; + this.definition = blessDefinition(definition); + this.contextsByScope = new WeakMap; + this.connectedContexts = new Set; + } + Object.defineProperty(Module.prototype, "identifier", { + get: function() { + return this.definition.identifier; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Module.prototype, "controllerConstructor", { + get: function() { + return this.definition.controllerConstructor; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Module.prototype, "contexts", { + get: function() { + return Array.from(this.connectedContexts); + }, + enumerable: false, + configurable: true + }); + Module.prototype.connectContextForScope = function(scope) { + var context = this.fetchContextForScope(scope); + this.connectedContexts.add(context); + context.connect(); + }; + Module.prototype.disconnectContextForScope = function(scope) { + var context = this.contextsByScope.get(scope); + if (context) { + this.connectedContexts.delete(context); + context.disconnect(); + } + }; + Module.prototype.fetchContextForScope = function(scope) { + var context = this.contextsByScope.get(scope); + if (!context) { + context = new Context(this, scope); + this.contextsByScope.set(scope, context); + } + return context; + }; + return Module; + }(); + var ClassMap = function() { + function ClassMap(scope) { + this.scope = scope; + } + ClassMap.prototype.has = function(name) { + return this.data.has(this.getDataKey(name)); + }; + ClassMap.prototype.get = function(name) { + return this.data.get(this.getDataKey(name)); + }; + ClassMap.prototype.getAttributeName = function(name) { + return this.data.getAttributeNameForKey(this.getDataKey(name)); + }; + ClassMap.prototype.getDataKey = function(name) { + return name + "-class"; + }; + Object.defineProperty(ClassMap.prototype, "data", { + get: function() { + return this.scope.data; + }, + enumerable: false, + configurable: true + }); + return ClassMap; + }(); + function camelize(value) { + return value.replace(/(?:[_-])([a-z0-9])/g, (function(_, char) { + return char.toUpperCase(); + })); + } + function capitalize(value) { + return value.charAt(0).toUpperCase() + value.slice(1); + } + function dasherize(value) { + return value.replace(/([A-Z])/g, (function(_, char) { + return "-" + char.toLowerCase(); + })); + } + var DataMap = function() { + function DataMap(scope) { + this.scope = scope; + } + Object.defineProperty(DataMap.prototype, "element", { + get: function() { + return this.scope.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(DataMap.prototype, "identifier", { + get: function() { + return this.scope.identifier; + }, + enumerable: false, + configurable: true + }); + DataMap.prototype.get = function(key) { + var name = this.getAttributeNameForKey(key); + return this.element.getAttribute(name); + }; + DataMap.prototype.set = function(key, value) { + var name = this.getAttributeNameForKey(key); + this.element.setAttribute(name, value); + return this.get(key); + }; + DataMap.prototype.has = function(key) { + var name = this.getAttributeNameForKey(key); + return this.element.hasAttribute(name); + }; + DataMap.prototype.delete = function(key) { + if (this.has(key)) { + var name_1 = this.getAttributeNameForKey(key); + this.element.removeAttribute(name_1); + return true; + } else { + return false; + } + }; + DataMap.prototype.getAttributeNameForKey = function(key) { + return "data-" + this.identifier + "-" + dasherize(key); + }; + return DataMap; + }(); + var Guide = function() { + function Guide(logger) { + this.warnedKeysByObject = new WeakMap; + this.logger = logger; + } + Guide.prototype.warn = function(object, key, message) { + var warnedKeys = this.warnedKeysByObject.get(object); + if (!warnedKeys) { + warnedKeys = new Set; + this.warnedKeysByObject.set(object, warnedKeys); + } + if (!warnedKeys.has(key)) { + warnedKeys.add(key); + this.logger.warn(message, object); + } + }; + return Guide; + }(); + function attributeValueContainsToken(attributeName, token) { + return "[" + attributeName + '~="' + token + '"]'; + } + var __spreadArrays$1 = window && window.__spreadArrays || function() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, + k++) r[k] = a[j]; + return r; + }; + var TargetSet = function() { + function TargetSet(scope) { + this.scope = scope; + } + Object.defineProperty(TargetSet.prototype, "element", { + get: function() { + return this.scope.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TargetSet.prototype, "identifier", { + get: function() { + return this.scope.identifier; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(TargetSet.prototype, "schema", { + get: function() { + return this.scope.schema; + }, + enumerable: false, + configurable: true + }); + TargetSet.prototype.has = function(targetName) { + return this.find(targetName) != null; + }; + TargetSet.prototype.find = function() { + var _this = this; + var targetNames = []; + for (var _i = 0; _i < arguments.length; _i++) { + targetNames[_i] = arguments[_i]; + } + return targetNames.reduce((function(target, targetName) { + return target || _this.findTarget(targetName) || _this.findLegacyTarget(targetName); + }), undefined); + }; + TargetSet.prototype.findAll = function() { + var _this = this; + var targetNames = []; + for (var _i = 0; _i < arguments.length; _i++) { + targetNames[_i] = arguments[_i]; + } + return targetNames.reduce((function(targets, targetName) { + return __spreadArrays$1(targets, _this.findAllTargets(targetName), _this.findAllLegacyTargets(targetName)); + }), []); + }; + TargetSet.prototype.findTarget = function(targetName) { + var selector = this.getSelectorForTargetName(targetName); + return this.scope.findElement(selector); + }; + TargetSet.prototype.findAllTargets = function(targetName) { + var selector = this.getSelectorForTargetName(targetName); + return this.scope.findAllElements(selector); + }; + TargetSet.prototype.getSelectorForTargetName = function(targetName) { + var attributeName = "data-" + this.identifier + "-target"; + return attributeValueContainsToken(attributeName, targetName); + }; + TargetSet.prototype.findLegacyTarget = function(targetName) { + var selector = this.getLegacySelectorForTargetName(targetName); + return this.deprecate(this.scope.findElement(selector), targetName); + }; + TargetSet.prototype.findAllLegacyTargets = function(targetName) { + var _this = this; + var selector = this.getLegacySelectorForTargetName(targetName); + return this.scope.findAllElements(selector).map((function(element) { + return _this.deprecate(element, targetName); + })); + }; + TargetSet.prototype.getLegacySelectorForTargetName = function(targetName) { + var targetDescriptor = this.identifier + "." + targetName; + return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor); + }; + TargetSet.prototype.deprecate = function(element, targetName) { + if (element) { + var identifier = this.identifier; + var attributeName = this.schema.targetAttribute; + this.guide.warn(element, "target:" + targetName, "Please replace " + attributeName + '="' + identifier + "." + targetName + '" with data-' + identifier + '-target="' + targetName + '". ' + ("The " + attributeName + " attribute is deprecated and will be removed in a future version of Stimulus.")); + } + return element; + }; + Object.defineProperty(TargetSet.prototype, "guide", { + get: function() { + return this.scope.guide; + }, + enumerable: false, + configurable: true + }); + return TargetSet; + }(); + var __spreadArrays$2 = window && window.__spreadArrays || function() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, + k++) r[k] = a[j]; + return r; + }; + var Scope = function() { + function Scope(schema, element, identifier, logger) { + var _this = this; + this.targets = new TargetSet(this); + this.classes = new ClassMap(this); + this.data = new DataMap(this); + this.containsElement = function(element) { + return element.closest(_this.controllerSelector) === _this.element; + }; + this.schema = schema; + this.element = element; + this.identifier = identifier; + this.guide = new Guide(logger); + } + Scope.prototype.findElement = function(selector) { + return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement); + }; + Scope.prototype.findAllElements = function(selector) { + return __spreadArrays$2(this.element.matches(selector) ? [ this.element ] : [], this.queryElements(selector).filter(this.containsElement)); + }; + Scope.prototype.queryElements = function(selector) { + return Array.from(this.element.querySelectorAll(selector)); + }; + Object.defineProperty(Scope.prototype, "controllerSelector", { + get: function() { + return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier); + }, + enumerable: false, + configurable: true + }); + return Scope; + }(); + var ScopeObserver = function() { + function ScopeObserver(element, schema, delegate) { + this.element = element; + this.schema = schema; + this.delegate = delegate; + this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this); + this.scopesByIdentifierByElement = new WeakMap; + this.scopeReferenceCounts = new WeakMap; + } + ScopeObserver.prototype.start = function() { + this.valueListObserver.start(); + }; + ScopeObserver.prototype.stop = function() { + this.valueListObserver.stop(); + }; + Object.defineProperty(ScopeObserver.prototype, "controllerAttribute", { + get: function() { + return this.schema.controllerAttribute; + }, + enumerable: false, + configurable: true + }); + ScopeObserver.prototype.parseValueForToken = function(token) { + var element = token.element, identifier = token.content; + var scopesByIdentifier = this.fetchScopesByIdentifierForElement(element); + var scope = scopesByIdentifier.get(identifier); + if (!scope) { + scope = this.delegate.createScopeForElementAndIdentifier(element, identifier); + scopesByIdentifier.set(identifier, scope); + } + return scope; + }; + ScopeObserver.prototype.elementMatchedValue = function(element, value) { + var referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1; + this.scopeReferenceCounts.set(value, referenceCount); + if (referenceCount == 1) { + this.delegate.scopeConnected(value); + } + }; + ScopeObserver.prototype.elementUnmatchedValue = function(element, value) { + var referenceCount = this.scopeReferenceCounts.get(value); + if (referenceCount) { + this.scopeReferenceCounts.set(value, referenceCount - 1); + if (referenceCount == 1) { + this.delegate.scopeDisconnected(value); + } + } + }; + ScopeObserver.prototype.fetchScopesByIdentifierForElement = function(element) { + var scopesByIdentifier = this.scopesByIdentifierByElement.get(element); + if (!scopesByIdentifier) { + scopesByIdentifier = new Map; + this.scopesByIdentifierByElement.set(element, scopesByIdentifier); + } + return scopesByIdentifier; + }; + return ScopeObserver; + }(); + var Router = function() { + function Router(application) { + this.application = application; + this.scopeObserver = new ScopeObserver(this.element, this.schema, this); + this.scopesByIdentifier = new Multimap; + this.modulesByIdentifier = new Map; + } + Object.defineProperty(Router.prototype, "element", { + get: function() { + return this.application.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Router.prototype, "schema", { + get: function() { + return this.application.schema; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Router.prototype, "logger", { + get: function() { + return this.application.logger; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Router.prototype, "controllerAttribute", { + get: function() { + return this.schema.controllerAttribute; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Router.prototype, "modules", { + get: function() { + return Array.from(this.modulesByIdentifier.values()); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Router.prototype, "contexts", { + get: function() { + return this.modules.reduce((function(contexts, module) { + return contexts.concat(module.contexts); + }), []); + }, + enumerable: false, + configurable: true + }); + Router.prototype.start = function() { + this.scopeObserver.start(); + }; + Router.prototype.stop = function() { + this.scopeObserver.stop(); + }; + Router.prototype.loadDefinition = function(definition) { + this.unloadIdentifier(definition.identifier); + var module = new Module(this.application, definition); + this.connectModule(module); + }; + Router.prototype.unloadIdentifier = function(identifier) { + var module = this.modulesByIdentifier.get(identifier); + if (module) { + this.disconnectModule(module); + } + }; + Router.prototype.getContextForElementAndIdentifier = function(element, identifier) { + var module = this.modulesByIdentifier.get(identifier); + if (module) { + return module.contexts.find((function(context) { + return context.element == element; + })); + } + }; + Router.prototype.handleError = function(error, message, detail) { + this.application.handleError(error, message, detail); + }; + Router.prototype.createScopeForElementAndIdentifier = function(element, identifier) { + return new Scope(this.schema, element, identifier, this.logger); + }; + Router.prototype.scopeConnected = function(scope) { + this.scopesByIdentifier.add(scope.identifier, scope); + var module = this.modulesByIdentifier.get(scope.identifier); + if (module) { + module.connectContextForScope(scope); + } + }; + Router.prototype.scopeDisconnected = function(scope) { + this.scopesByIdentifier.delete(scope.identifier, scope); + var module = this.modulesByIdentifier.get(scope.identifier); + if (module) { + module.disconnectContextForScope(scope); + } + }; + Router.prototype.connectModule = function(module) { + this.modulesByIdentifier.set(module.identifier, module); + var scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); + scopes.forEach((function(scope) { + return module.connectContextForScope(scope); + })); + }; + Router.prototype.disconnectModule = function(module) { + this.modulesByIdentifier.delete(module.identifier); + var scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); + scopes.forEach((function(scope) { + return module.disconnectContextForScope(scope); + })); + }; + return Router; + }(); + var defaultSchema = { + controllerAttribute: "data-controller", + actionAttribute: "data-action", + targetAttribute: "data-target" + }; + var __awaiter = window && window.__awaiter || function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P((function(resolve) { + resolve(value); + })); + } + return new (P || (P = Promise))((function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + })); + }; + var __generator = window && window.__generator || function(thisArg, body) { + var _ = { + label: 0, + sent: function() { + if (t[0] & 1) throw t[1]; + return t[1]; + }, + trys: [], + ops: [] + }, f, y, t, g; + return g = { + next: verb(0), + throw: verb(1), + return: verb(2) + }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { + return this; + }), g; + function verb(n) { + return function(v) { + return step([ n, v ]); + }; + } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), + 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [ op[0] & 2, t.value ]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + + case 4: + _.label++; + return { + value: op[1], + done: false + }; + + case 5: + _.label++; + y = op[1]; + op = [ 0 ]; + continue; + + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { + _ = 0; + continue; + } + if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } catch (e) { + op = [ 6, e ]; + y = 0; + } finally { + f = t = 0; + } + if (op[0] & 5) throw op[1]; + return { + value: op[0] ? op[1] : void 0, + done: true + }; + } + }; + var __spreadArrays$3 = window && window.__spreadArrays || function() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, + k++) r[k] = a[j]; + return r; + }; + var Application = function() { + function Application(element, schema) { + if (element === void 0) { + element = document.documentElement; + } + if (schema === void 0) { + schema = defaultSchema; + } + this.logger = console; + this.element = element; + this.schema = schema; + this.dispatcher = new Dispatcher(this); + this.router = new Router(this); + } + Application.start = function(element, schema) { + var application = new Application(element, schema); + application.start(); + return application; + }; + Application.prototype.start = function() { + return __awaiter(this, void 0, void 0, (function() { + return __generator(this, (function(_a) { + switch (_a.label) { + case 0: + return [ 4, domReady() ]; + + case 1: + _a.sent(); + this.dispatcher.start(); + this.router.start(); + return [ 2 ]; + } + })); + })); + }; + Application.prototype.stop = function() { + this.dispatcher.stop(); + this.router.stop(); + }; + Application.prototype.register = function(identifier, controllerConstructor) { + this.load({ + identifier: identifier, + controllerConstructor: controllerConstructor + }); + }; + Application.prototype.load = function(head) { + var _this = this; + var rest = []; + for (var _i = 1; _i < arguments.length; _i++) { + rest[_i - 1] = arguments[_i]; + } + var definitions = Array.isArray(head) ? head : __spreadArrays$3([ head ], rest); + definitions.forEach((function(definition) { + return _this.router.loadDefinition(definition); + })); + }; + Application.prototype.unload = function(head) { + var _this = this; + var rest = []; + for (var _i = 1; _i < arguments.length; _i++) { + rest[_i - 1] = arguments[_i]; + } + var identifiers = Array.isArray(head) ? head : __spreadArrays$3([ head ], rest); + identifiers.forEach((function(identifier) { + return _this.router.unloadIdentifier(identifier); + })); + }; + Object.defineProperty(Application.prototype, "controllers", { + get: function() { + return this.router.contexts.map((function(context) { + return context.controller; + })); + }, + enumerable: false, + configurable: true + }); + Application.prototype.getControllerForElementAndIdentifier = function(element, identifier) { + var context = this.router.getContextForElementAndIdentifier(element, identifier); + return context ? context.controller : null; + }; + Application.prototype.handleError = function(error, message, detail) { + this.logger.error("%s\n\n%o\n\n%o", message, error, detail); + }; + return Application; + }(); + function domReady() { + return new Promise((function(resolve) { + if (document.readyState == "loading") { + document.addEventListener("DOMContentLoaded", resolve); + } else { + resolve(); + } + })); + } + function ClassPropertiesBlessing(constructor) { + var classes = readInheritableStaticArrayValues(constructor, "classes"); + return classes.reduce((function(properties, classDefinition) { + return Object.assign(properties, propertiesForClassDefinition(classDefinition)); + }), {}); + } + function propertiesForClassDefinition(key) { + var _a; + var name = key + "Class"; + return _a = {}, _a[name] = { + get: function() { + var classes = this.classes; + if (classes.has(key)) { + return classes.get(key); + } else { + var attribute = classes.getAttributeName(key); + throw new Error('Missing attribute "' + attribute + '"'); + } + } + }, _a["has" + capitalize(name)] = { + get: function() { + return this.classes.has(key); + } + }, _a; + } + function TargetPropertiesBlessing(constructor) { + var targets = readInheritableStaticArrayValues(constructor, "targets"); + return targets.reduce((function(properties, targetDefinition) { + return Object.assign(properties, propertiesForTargetDefinition(targetDefinition)); + }), {}); + } + function propertiesForTargetDefinition(name) { + var _a; + return _a = {}, _a[name + "Target"] = { + get: function() { + var target = this.targets.find(name); + if (target) { + return target; + } else { + throw new Error('Missing target element "' + this.identifier + "." + name + '"'); + } + } + }, _a[name + "Targets"] = { + get: function() { + return this.targets.findAll(name); + } + }, _a["has" + capitalize(name) + "Target"] = { + get: function() { + return this.targets.has(name); + } + }, _a; + } + function ValuePropertiesBlessing(constructor) { + var valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values"); + var propertyDescriptorMap = { + valueDescriptorMap: { + get: function() { + var _this = this; + return valueDefinitionPairs.reduce((function(result, valueDefinitionPair) { + var _a; + var valueDescriptor = parseValueDefinitionPair(valueDefinitionPair); + var attributeName = _this.data.getAttributeNameForKey(valueDescriptor.key); + return Object.assign(result, (_a = {}, _a[attributeName] = valueDescriptor, _a)); + }), {}); + } + } + }; + return valueDefinitionPairs.reduce((function(properties, valueDefinitionPair) { + return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair)); + }), propertyDescriptorMap); + } + function propertiesForValueDefinitionPair(valueDefinitionPair) { + var _a; + var definition = parseValueDefinitionPair(valueDefinitionPair); + var type = definition.type, key = definition.key, name = definition.name; + var read = readers[type], write = writers[type] || writers.default; + return _a = {}, _a[name] = { + get: function() { + var value = this.data.get(key); + if (value !== null) { + return read(value); + } else { + return definition.defaultValue; + } + }, + set: function(value) { + if (value === undefined) { + this.data.delete(key); + } else { + this.data.set(key, write(value)); + } + } + }, _a["has" + capitalize(name)] = { + get: function() { + return this.data.has(key); + } + }, _a; + } + function parseValueDefinitionPair(_a) { + var token = _a[0], typeConstant = _a[1]; + var type = parseValueTypeConstant(typeConstant); + return valueDescriptorForTokenAndType(token, type); + } + function parseValueTypeConstant(typeConstant) { + switch (typeConstant) { + case Array: + return "array"; + + case Boolean: + return "boolean"; + + case Number: + return "number"; + + case Object: + return "object"; + + case String: + return "string"; + } + throw new Error('Unknown value type constant "' + typeConstant + '"'); + } + function valueDescriptorForTokenAndType(token, type) { + var key = dasherize(token) + "-value"; + return { + type: type, + key: key, + name: camelize(key), + get defaultValue() { + return defaultValuesByType[type]; + } + }; + } + var defaultValuesByType = { + get array() { + return []; + }, + boolean: false, + number: 0, + get object() { + return {}; + }, + string: "" + }; + var readers = { + array: function(value) { + var array = JSON.parse(value); + if (!Array.isArray(array)) { + throw new TypeError("Expected array"); + } + return array; + }, + boolean: function(value) { + return !(value == "0" || value == "false"); + }, + number: function(value) { + return parseFloat(value); + }, + object: function(value) { + var object = JSON.parse(value); + if (object === null || typeof object != "object" || Array.isArray(object)) { + throw new TypeError("Expected object"); + } + return object; + }, + string: function(value) { + return value; + } + }; + var writers = { + default: writeString, + array: writeJSON, + object: writeJSON + }; + function writeJSON(value) { + return JSON.stringify(value); + } + function writeString(value) { + return "" + value; + } + var Controller = function() { + function Controller(context) { + this.context = context; + } + Object.defineProperty(Controller.prototype, "application", { + get: function() { + return this.context.application; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "scope", { + get: function() { + return this.context.scope; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "element", { + get: function() { + return this.scope.element; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "identifier", { + get: function() { + return this.scope.identifier; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "targets", { + get: function() { + return this.scope.targets; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "classes", { + get: function() { + return this.scope.classes; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Controller.prototype, "data", { + get: function() { + return this.scope.data; + }, + enumerable: false, + configurable: true + }); + Controller.prototype.initialize = function() {}; + Controller.prototype.connect = function() {}; + Controller.prototype.disconnect = function() {}; + Controller.blessings = [ ClassPropertiesBlessing, TargetPropertiesBlessing, ValuePropertiesBlessing ]; + Controller.targets = []; + Controller.values = {}; + return Controller; + }(); + exports.Application = Application; + exports.Context = Context; + exports.Controller = Controller; + exports.defaultSchema = defaultSchema; + Object.defineProperty(exports, "__esModule", { + value: true + }); +})); + diff --git a/static/styles/main.css b/static/styles/main.css index 65ffeee..0dfadf6 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -5,6 +5,7 @@ --blue: #10638c; --light-blue: #74c0e6; --red: #8c1016; + --light-brown: #a69688; } html { @@ -62,7 +63,7 @@ a { blockquote { margin-left: 0; padding-left: 2rem; - border-left: 2px solid var(--blue); + border-left: 0.2rem solid var(--blue); } body > header { @@ -154,8 +155,14 @@ article { } .hidden_action { + visibility: hidden; margin-left: 1rem; - display: none; + border: none; + background-color: var(--light-brown); + color: white; + padding: 0.15rem 0.5rem; + border-radius: 1rem; + cursor: pointer; } .todo__item { @@ -164,19 +171,76 @@ article { align-content: flex-start; } .todo__item:hover .hidden_action { - display: inline-block; + visibility: visible; } +.todo_display { + display: grid; + grid-template-columns: 0.25fr 2fr 1fr 1fr; + align-items: center; + gap: 0 1rem; + width: 100%; +} +.todo__actions { + font-size: 0.889rem; +} +.todo__due_date { + color: var(--light-brown); +} .todo__checkbox { margin-right: 0.5rem; } -.todo_form { - display: flex; +.todo__checkbox_input { + opacity: 0; + position: absolute; + cursor: pointer; + appearance: none; + z-index: -1; } -.todo__details { - display: flex; - align-items: center; - flex-direction: row; +.todos__overdue { + background-color: var(--white); + padding: 1rem; +} +.todos__overdue h4 { + margin-top: 0; +} +.todo__checkbox_button { + display: inline-block; + width: 1.4em; + height: 1.4em; + border: 1px solid rgba(0,0,0,0.25); + background-color: #fff; + border-radius: 0.3em; + vertical-align: top; + cursor: pointer; +} +.todo__checkbox_button--completed { + position: relative; + border-color: rgba(0,0,0,0.1); + background-color: var(--blue); + box-shadow: none; +} +.todo__checkbox_button--completed::after { + content: ''; + position: absolute; + width: 100%; + height: 100%; + top: 0; + bottom: 0; + right: 0; + left: 0; + background: url(../images/checkmark.svg) no-repeat center center; + background-size: auto; + background-size: 65%; +} +.todo_form { + display: grid; + row-gap: 1rem; + margin: 1rem 0; + width: 100%; + border: 0.0625rem solid rgba(0, 0, 0, 0.25); + background-color: var(--white); + padding: 1rem; } @@ -207,10 +271,13 @@ article { .action-button--danger { background-color: var(--red); } +.--danger { + color: var(--red); +} /* FORMS */ -input[type=text]:not([name=description]), +input[type=text], input[type=number], input[type=date], input[type=time], @@ -226,14 +293,6 @@ textarea, select { box-sizing: border-box; } -input[name=description] { - border: 0.2rem solid var(--grey); - padding: 0.3rem; - font-family: inherit; - outline: none; - box-sizing: border-box; -} - input[type=radio], input[type=checkbox] { cursor: pointer; width: 1.5rem; @@ -267,6 +326,15 @@ input:focus, textarea:focus, select:focus { border-color: var(--blue) !important; } +button { + margin-left: 1rem; + border: none; + background-color: var(--light-brown); + color: white; + padding: 0.15rem 0.5rem; + border-radius: 1rem; + cursor: pointer; +} diff --git a/templates/base.html b/templates/base.html index 9ec42f9..8447248 100644 --- a/templates/base.html +++ b/templates/base.html @@ -30,11 +30,7 @@ Employees - {% if user.first_name or user.last_name %} - {{ user.first_name }} {{ user.last_name }} - {% else %} Profile - {% endif %} Logout {% else %}