');
+}
+
+function _Debug_addSlashes(str, isChar)
+{
+ var s = str
+ .replace(/\\/g, '\\\\')
+ .replace(/\n/g, '\\n')
+ .replace(/\t/g, '\\t')
+ .replace(/\r/g, '\\r')
+ .replace(/\v/g, '\\v')
+ .replace(/\0/g, '\\0');
+
+ if (isChar)
+ {
+ return s.replace(/\'/g, '\\\'');
+ }
+ else
+ {
+ return s.replace(/\"/g, '\\"');
+ }
+}
+
+function _Debug_ctorColor(ansi, string)
+{
+ return ansi ? '\x1b[96m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_numberColor(ansi, string)
+{
+ return ansi ? '\x1b[95m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_stringColor(ansi, string)
+{
+ return ansi ? '\x1b[93m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_charColor(ansi, string)
+{
+ return ansi ? '\x1b[92m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_fadeColor(ansi, string)
+{
+ return ansi ? '\x1b[37m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_internalColor(ansi, string)
+{
+ return ansi ? '\x1b[36m' + string + '\x1b[0m' : string;
+}
+
+function _Debug_toHexDigit(n)
+{
+ return String.fromCharCode(n < 10 ? 48 + n : 55 + n);
+}
+
+
+// CRASH
+
+
+function _Debug_crash(identifier)
+{
+ throw new Error('https://github.com/elm/core/blob/1.0.0/hints/' + identifier + '.md');
+}
+
+
+function _Debug_crash_UNUSED(identifier, fact1, fact2, fact3, fact4)
+{
+ switch(identifier)
+ {
+ case 0:
+ throw new Error('What node should I take over? In JavaScript I need something like:\n\n Elm.Main.init({\n node: document.getElementById("elm-node")\n })\n\nYou need to do this with any Browser.sandbox or Browser.element program.');
+
+ case 1:
+ throw new Error('Browser.application programs cannot handle URLs like this:\n\n ' + document.location.href + '\n\nWhat is the root? The root of your file system? Try looking at this program with `elm reactor` or some other server.');
+
+ case 2:
+ var jsonErrorString = fact1;
+ throw new Error('Problem with the flags given to your Elm program on initialization.\n\n' + jsonErrorString);
+
+ case 3:
+ var portName = fact1;
+ throw new Error('There can only be one port named `' + portName + '`, but your program has multiple.');
+
+ case 4:
+ var portName = fact1;
+ var problem = fact2;
+ throw new Error('Trying to send an unexpected type of value through port `' + portName + '`:\n' + problem);
+
+ case 5:
+ throw new Error('Trying to use `(==)` on functions.\nThere is no way to know if functions are "the same" in the Elm sense.\nRead more about this at https://package.elm-lang.org/packages/elm/core/latest/Basics#== which describes why it is this way and what the better version will look like.');
+
+ case 6:
+ var moduleName = fact1;
+ throw new Error('Your page is loading multiple Elm scripts with a module named ' + moduleName + '. Maybe a duplicate script is getting loaded accidentally? If not, rename one of them so I know which is which!');
+
+ case 8:
+ var moduleName = fact1;
+ var region = fact2;
+ var message = fact3;
+ throw new Error('TODO in module `' + moduleName + '` ' + _Debug_regionToString(region) + '\n\n' + message);
+
+ case 9:
+ var moduleName = fact1;
+ var region = fact2;
+ var value = fact3;
+ var message = fact4;
+ throw new Error(
+ 'TODO in module `' + moduleName + '` from the `case` expression '
+ + _Debug_regionToString(region) + '\n\nIt received the following value:\n\n '
+ + _Debug_toString(value).replace('\n', '\n ')
+ + '\n\nBut the branch that handles it says:\n\n ' + message.replace('\n', '\n ')
+ );
+
+ case 10:
+ throw new Error('Bug in https://github.com/elm/virtual-dom/issues');
+
+ case 11:
+ throw new Error('Cannot perform mod 0. Division by zero error.');
+ }
+}
+
+function _Debug_regionToString(region)
+{
+ if (region.K.z === region.R.z)
+ {
+ return 'on line ' + region.K.z;
+ }
+ return 'on lines ' + region.K.z + ' through ' + region.R.z;
+}
+
+
+
+// MATH
+
+var _Basics_add = F2(function(a, b) { return a + b; });
+var _Basics_sub = F2(function(a, b) { return a - b; });
+var _Basics_mul = F2(function(a, b) { return a * b; });
+var _Basics_fdiv = F2(function(a, b) { return a / b; });
+var _Basics_idiv = F2(function(a, b) { return (a / b) | 0; });
+var _Basics_pow = F2(Math.pow);
+
+var _Basics_remainderBy = F2(function(b, a) { return a % b; });
+
+// https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf
+var _Basics_modBy = F2(function(modulus, x)
+{
+ var answer = x % modulus;
+ return modulus === 0
+ ? _Debug_crash(11)
+ :
+ ((answer > 0 && modulus < 0) || (answer < 0 && modulus > 0))
+ ? answer + modulus
+ : answer;
+});
+
+
+// TRIGONOMETRY
+
+var _Basics_pi = Math.PI;
+var _Basics_e = Math.E;
+var _Basics_cos = Math.cos;
+var _Basics_sin = Math.sin;
+var _Basics_tan = Math.tan;
+var _Basics_acos = Math.acos;
+var _Basics_asin = Math.asin;
+var _Basics_atan = Math.atan;
+var _Basics_atan2 = F2(Math.atan2);
+
+
+// MORE MATH
+
+function _Basics_toFloat(x) { return x; }
+function _Basics_truncate(n) { return n | 0; }
+function _Basics_isInfinite(n) { return n === Infinity || n === -Infinity; }
+
+var _Basics_ceiling = Math.ceil;
+var _Basics_floor = Math.floor;
+var _Basics_round = Math.round;
+var _Basics_sqrt = Math.sqrt;
+var _Basics_log = Math.log;
+var _Basics_isNaN = isNaN;
+
+
+// BOOLEANS
+
+function _Basics_not(bool) { return !bool; }
+var _Basics_and = F2(function(a, b) { return a && b; });
+var _Basics_or = F2(function(a, b) { return a || b; });
+var _Basics_xor = F2(function(a, b) { return a !== b; });
+
+
+
+var _String_cons = F2(function(chr, str)
+{
+ return chr + str;
+});
+
+function _String_uncons(string)
+{
+ var word = string.charCodeAt(0);
+ return !isNaN(word)
+ ? $elm$core$Maybe$Just(
+ 0xD800 <= word && word <= 0xDBFF
+ ? _Utils_Tuple2(_Utils_chr(string[0] + string[1]), string.slice(2))
+ : _Utils_Tuple2(_Utils_chr(string[0]), string.slice(1))
+ )
+ : $elm$core$Maybe$Nothing;
+}
+
+var _String_append = F2(function(a, b)
+{
+ return a + b;
+});
+
+function _String_length(str)
+{
+ return str.length;
+}
+
+var _String_map = F2(function(func, string)
+{
+ var len = string.length;
+ var array = new Array(len);
+ var i = 0;
+ while (i < len)
+ {
+ var word = string.charCodeAt(i);
+ if (0xD800 <= word && word <= 0xDBFF)
+ {
+ array[i] = func(_Utils_chr(string[i] + string[i+1]));
+ i += 2;
+ continue;
+ }
+ array[i] = func(_Utils_chr(string[i]));
+ i++;
+ }
+ return array.join('');
+});
+
+var _String_filter = F2(function(isGood, str)
+{
+ var arr = [];
+ var len = str.length;
+ var i = 0;
+ while (i < len)
+ {
+ var char = str[i];
+ var word = str.charCodeAt(i);
+ i++;
+ if (0xD800 <= word && word <= 0xDBFF)
+ {
+ char += str[i];
+ i++;
+ }
+
+ if (isGood(_Utils_chr(char)))
+ {
+ arr.push(char);
+ }
+ }
+ return arr.join('');
+});
+
+function _String_reverse(str)
+{
+ var len = str.length;
+ var arr = new Array(len);
+ var i = 0;
+ while (i < len)
+ {
+ var word = str.charCodeAt(i);
+ if (0xD800 <= word && word <= 0xDBFF)
+ {
+ arr[len - i] = str[i + 1];
+ i++;
+ arr[len - i] = str[i - 1];
+ i++;
+ }
+ else
+ {
+ arr[len - i] = str[i];
+ i++;
+ }
+ }
+ return arr.join('');
+}
+
+var _String_foldl = F3(function(func, state, string)
+{
+ var len = string.length;
+ var i = 0;
+ while (i < len)
+ {
+ var char = string[i];
+ var word = string.charCodeAt(i);
+ i++;
+ if (0xD800 <= word && word <= 0xDBFF)
+ {
+ char += string[i];
+ i++;
+ }
+ state = A2(func, _Utils_chr(char), state);
+ }
+ return state;
+});
+
+var _String_foldr = F3(function(func, state, string)
+{
+ var i = string.length;
+ while (i--)
+ {
+ var char = string[i];
+ var word = string.charCodeAt(i);
+ if (0xDC00 <= word && word <= 0xDFFF)
+ {
+ i--;
+ char = string[i] + char;
+ }
+ state = A2(func, _Utils_chr(char), state);
+ }
+ return state;
+});
+
+var _String_split = F2(function(sep, str)
+{
+ return str.split(sep);
+});
+
+var _String_join = F2(function(sep, strs)
+{
+ return strs.join(sep);
+});
+
+var _String_slice = F3(function(start, end, str) {
+ return str.slice(start, end);
+});
+
+function _String_trim(str)
+{
+ return str.trim();
+}
+
+function _String_trimLeft(str)
+{
+ return str.replace(/^\s+/, '');
+}
+
+function _String_trimRight(str)
+{
+ return str.replace(/\s+$/, '');
+}
+
+function _String_words(str)
+{
+ return _List_fromArray(str.trim().split(/\s+/g));
+}
+
+function _String_lines(str)
+{
+ return _List_fromArray(str.split(/\r\n|\r|\n/g));
+}
+
+function _String_toUpper(str)
+{
+ return str.toUpperCase();
+}
+
+function _String_toLower(str)
+{
+ return str.toLowerCase();
+}
+
+var _String_any = F2(function(isGood, string)
+{
+ var i = string.length;
+ while (i--)
+ {
+ var char = string[i];
+ var word = string.charCodeAt(i);
+ if (0xDC00 <= word && word <= 0xDFFF)
+ {
+ i--;
+ char = string[i] + char;
+ }
+ if (isGood(_Utils_chr(char)))
+ {
+ return true;
+ }
+ }
+ return false;
+});
+
+var _String_all = F2(function(isGood, string)
+{
+ var i = string.length;
+ while (i--)
+ {
+ var char = string[i];
+ var word = string.charCodeAt(i);
+ if (0xDC00 <= word && word <= 0xDFFF)
+ {
+ i--;
+ char = string[i] + char;
+ }
+ if (!isGood(_Utils_chr(char)))
+ {
+ return false;
+ }
+ }
+ return true;
+});
+
+var _String_contains = F2(function(sub, str)
+{
+ return str.indexOf(sub) > -1;
+});
+
+var _String_startsWith = F2(function(sub, str)
+{
+ return str.indexOf(sub) === 0;
+});
+
+var _String_endsWith = F2(function(sub, str)
+{
+ return str.length >= sub.length &&
+ str.lastIndexOf(sub) === str.length - sub.length;
+});
+
+var _String_indexes = F2(function(sub, str)
+{
+ var subLen = sub.length;
+
+ if (subLen < 1)
+ {
+ return _List_Nil;
+ }
+
+ var i = 0;
+ var is = [];
+
+ while ((i = str.indexOf(sub, i)) > -1)
+ {
+ is.push(i);
+ i = i + subLen;
+ }
+
+ return _List_fromArray(is);
+});
+
+
+// TO STRING
+
+function _String_fromNumber(number)
+{
+ return number + '';
+}
+
+
+// INT CONVERSIONS
+
+function _String_toInt(str)
+{
+ var total = 0;
+ var code0 = str.charCodeAt(0);
+ var start = code0 == 0x2B /* + */ || code0 == 0x2D /* - */ ? 1 : 0;
+
+ for (var i = start; i < str.length; ++i)
+ {
+ var code = str.charCodeAt(i);
+ if (code < 0x30 || 0x39 < code)
+ {
+ return $elm$core$Maybe$Nothing;
+ }
+ total = 10 * total + code - 0x30;
+ }
+
+ return i == start
+ ? $elm$core$Maybe$Nothing
+ : $elm$core$Maybe$Just(code0 == 0x2D ? -total : total);
+}
+
+
+// FLOAT CONVERSIONS
+
+function _String_toFloat(s)
+{
+ // check if it is a hex, octal, or binary number
+ if (s.length === 0 || /[\sxbo]/.test(s))
+ {
+ return $elm$core$Maybe$Nothing;
+ }
+ var n = +s;
+ // faster isNaN check
+ return n === n ? $elm$core$Maybe$Just(n) : $elm$core$Maybe$Nothing;
+}
+
+function _String_fromList(chars)
+{
+ return _List_toArray(chars).join('');
+}
+
+
+
+
+function _Char_toCode(char)
+{
+ var code = char.charCodeAt(0);
+ if (0xD800 <= code && code <= 0xDBFF)
+ {
+ return (code - 0xD800) * 0x400 + char.charCodeAt(1) - 0xDC00 + 0x10000
+ }
+ return code;
+}
+
+function _Char_fromCode(code)
+{
+ return _Utils_chr(
+ (code < 0 || 0x10FFFF < code)
+ ? '\uFFFD'
+ :
+ (code <= 0xFFFF)
+ ? String.fromCharCode(code)
+ :
+ (code -= 0x10000,
+ String.fromCharCode(Math.floor(code / 0x400) + 0xD800, code % 0x400 + 0xDC00)
+ )
+ );
+}
+
+function _Char_toUpper(char)
+{
+ return _Utils_chr(char.toUpperCase());
+}
+
+function _Char_toLower(char)
+{
+ return _Utils_chr(char.toLowerCase());
+}
+
+function _Char_toLocaleUpper(char)
+{
+ return _Utils_chr(char.toLocaleUpperCase());
+}
+
+function _Char_toLocaleLower(char)
+{
+ return _Utils_chr(char.toLocaleLowerCase());
+}
+
+
+
+/**_UNUSED/
+function _Json_errorToString(error)
+{
+ return $elm$json$Json$Decode$errorToString(error);
+}
+//*/
+
+
+// CORE DECODERS
+
+function _Json_succeed(msg)
+{
+ return {
+ $: 0,
+ a: msg
+ };
+}
+
+function _Json_fail(msg)
+{
+ return {
+ $: 1,
+ a: msg
+ };
+}
+
+function _Json_decodePrim(decoder)
+{
+ return { $: 2, b: decoder };
+}
+
+var _Json_decodeInt = _Json_decodePrim(function(value) {
+ return (typeof value !== 'number')
+ ? _Json_expecting('an INT', value)
+ :
+ (-2147483647 < value && value < 2147483647 && (value | 0) === value)
+ ? $elm$core$Result$Ok(value)
+ :
+ (isFinite(value) && !(value % 1))
+ ? $elm$core$Result$Ok(value)
+ : _Json_expecting('an INT', value);
+});
+
+var _Json_decodeBool = _Json_decodePrim(function(value) {
+ return (typeof value === 'boolean')
+ ? $elm$core$Result$Ok(value)
+ : _Json_expecting('a BOOL', value);
+});
+
+var _Json_decodeFloat = _Json_decodePrim(function(value) {
+ return (typeof value === 'number')
+ ? $elm$core$Result$Ok(value)
+ : _Json_expecting('a FLOAT', value);
+});
+
+var _Json_decodeValue = _Json_decodePrim(function(value) {
+ return $elm$core$Result$Ok(_Json_wrap(value));
+});
+
+var _Json_decodeString = _Json_decodePrim(function(value) {
+ return (typeof value === 'string')
+ ? $elm$core$Result$Ok(value)
+ : (value instanceof String)
+ ? $elm$core$Result$Ok(value + '')
+ : _Json_expecting('a STRING', value);
+});
+
+function _Json_decodeList(decoder) { return { $: 3, b: decoder }; }
+function _Json_decodeArray(decoder) { return { $: 4, b: decoder }; }
+
+function _Json_decodeNull(value) { return { $: 5, c: value }; }
+
+var _Json_decodeField = F2(function(field, decoder)
+{
+ return {
+ $: 6,
+ d: field,
+ b: decoder
+ };
+});
+
+var _Json_decodeIndex = F2(function(index, decoder)
+{
+ return {
+ $: 7,
+ e: index,
+ b: decoder
+ };
+});
+
+function _Json_decodeKeyValuePairs(decoder)
+{
+ return {
+ $: 8,
+ b: decoder
+ };
+}
+
+function _Json_mapMany(f, decoders)
+{
+ return {
+ $: 9,
+ f: f,
+ g: decoders
+ };
+}
+
+var _Json_andThen = F2(function(callback, decoder)
+{
+ return {
+ $: 10,
+ b: decoder,
+ h: callback
+ };
+});
+
+function _Json_oneOf(decoders)
+{
+ return {
+ $: 11,
+ g: decoders
+ };
+}
+
+
+// DECODING OBJECTS
+
+var _Json_map1 = F2(function(f, d1)
+{
+ return _Json_mapMany(f, [d1]);
+});
+
+var _Json_map2 = F3(function(f, d1, d2)
+{
+ return _Json_mapMany(f, [d1, d2]);
+});
+
+var _Json_map3 = F4(function(f, d1, d2, d3)
+{
+ return _Json_mapMany(f, [d1, d2, d3]);
+});
+
+var _Json_map4 = F5(function(f, d1, d2, d3, d4)
+{
+ return _Json_mapMany(f, [d1, d2, d3, d4]);
+});
+
+var _Json_map5 = F6(function(f, d1, d2, d3, d4, d5)
+{
+ return _Json_mapMany(f, [d1, d2, d3, d4, d5]);
+});
+
+var _Json_map6 = F7(function(f, d1, d2, d3, d4, d5, d6)
+{
+ return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6]);
+});
+
+var _Json_map7 = F8(function(f, d1, d2, d3, d4, d5, d6, d7)
+{
+ return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7]);
+});
+
+var _Json_map8 = F9(function(f, d1, d2, d3, d4, d5, d6, d7, d8)
+{
+ return _Json_mapMany(f, [d1, d2, d3, d4, d5, d6, d7, d8]);
+});
+
+
+// DECODE
+
+var _Json_runOnString = F2(function(decoder, string)
+{
+ try
+ {
+ var value = JSON.parse(string);
+ return _Json_runHelp(decoder, value);
+ }
+ catch (e)
+ {
+ return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, 'This is not valid JSON! ' + e.message, _Json_wrap(string)));
+ }
+});
+
+var _Json_run = F2(function(decoder, value)
+{
+ return _Json_runHelp(decoder, _Json_unwrap(value));
+});
+
+function _Json_runHelp(decoder, value)
+{
+ switch (decoder.$)
+ {
+ case 2:
+ return decoder.b(value);
+
+ case 5:
+ return (value === null)
+ ? $elm$core$Result$Ok(decoder.c)
+ : _Json_expecting('null', value);
+
+ case 3:
+ if (!_Json_isArray(value))
+ {
+ return _Json_expecting('a LIST', value);
+ }
+ return _Json_runArrayDecoder(decoder.b, value, _List_fromArray);
+
+ case 4:
+ if (!_Json_isArray(value))
+ {
+ return _Json_expecting('an ARRAY', value);
+ }
+ return _Json_runArrayDecoder(decoder.b, value, _Json_toElmArray);
+
+ case 6:
+ var field = decoder.d;
+ if (typeof value !== 'object' || value === null || !(field in value))
+ {
+ return _Json_expecting('an OBJECT with a field named `' + field + '`', value);
+ }
+ var result = _Json_runHelp(decoder.b, value[field]);
+ return ($elm$core$Result$isOk(result)) ? result : $elm$core$Result$Err(A2($elm$json$Json$Decode$Field, field, result.a));
+
+ case 7:
+ var index = decoder.e;
+ if (!_Json_isArray(value))
+ {
+ return _Json_expecting('an ARRAY', value);
+ }
+ if (index >= value.length)
+ {
+ return _Json_expecting('a LONGER array. Need index ' + index + ' but only see ' + value.length + ' entries', value);
+ }
+ var result = _Json_runHelp(decoder.b, value[index]);
+ return ($elm$core$Result$isOk(result)) ? result : $elm$core$Result$Err(A2($elm$json$Json$Decode$Index, index, result.a));
+
+ case 8:
+ if (typeof value !== 'object' || value === null || _Json_isArray(value))
+ {
+ return _Json_expecting('an OBJECT', value);
+ }
+
+ var keyValuePairs = _List_Nil;
+ // TODO test perf of Object.keys and switch when support is good enough
+ for (var key in value)
+ {
+ if (value.hasOwnProperty(key))
+ {
+ var result = _Json_runHelp(decoder.b, value[key]);
+ if (!$elm$core$Result$isOk(result))
+ {
+ return $elm$core$Result$Err(A2($elm$json$Json$Decode$Field, key, result.a));
+ }
+ keyValuePairs = _List_Cons(_Utils_Tuple2(key, result.a), keyValuePairs);
+ }
+ }
+ return $elm$core$Result$Ok($elm$core$List$reverse(keyValuePairs));
+
+ case 9:
+ var answer = decoder.f;
+ var decoders = decoder.g;
+ for (var i = 0; i < decoders.length; i++)
+ {
+ var result = _Json_runHelp(decoders[i], value);
+ if (!$elm$core$Result$isOk(result))
+ {
+ return result;
+ }
+ answer = answer(result.a);
+ }
+ return $elm$core$Result$Ok(answer);
+
+ case 10:
+ var result = _Json_runHelp(decoder.b, value);
+ return (!$elm$core$Result$isOk(result))
+ ? result
+ : _Json_runHelp(decoder.h(result.a), value);
+
+ case 11:
+ var errors = _List_Nil;
+ for (var temp = decoder.g; temp.b; temp = temp.b) // WHILE_CONS
+ {
+ var result = _Json_runHelp(temp.a, value);
+ if ($elm$core$Result$isOk(result))
+ {
+ return result;
+ }
+ errors = _List_Cons(result.a, errors);
+ }
+ return $elm$core$Result$Err($elm$json$Json$Decode$OneOf($elm$core$List$reverse(errors)));
+
+ case 1:
+ return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, decoder.a, _Json_wrap(value)));
+
+ case 0:
+ return $elm$core$Result$Ok(decoder.a);
+ }
+}
+
+function _Json_runArrayDecoder(decoder, value, toElmValue)
+{
+ var len = value.length;
+ var array = new Array(len);
+ for (var i = 0; i < len; i++)
+ {
+ var result = _Json_runHelp(decoder, value[i]);
+ if (!$elm$core$Result$isOk(result))
+ {
+ return $elm$core$Result$Err(A2($elm$json$Json$Decode$Index, i, result.a));
+ }
+ array[i] = result.a;
+ }
+ return $elm$core$Result$Ok(toElmValue(array));
+}
+
+function _Json_isArray(value)
+{
+ return Array.isArray(value) || (typeof FileList !== 'undefined' && value instanceof FileList);
+}
+
+function _Json_toElmArray(array)
+{
+ return A2($elm$core$Array$initialize, array.length, function(i) { return array[i]; });
+}
+
+function _Json_expecting(type, value)
+{
+ return $elm$core$Result$Err(A2($elm$json$Json$Decode$Failure, 'Expecting ' + type, _Json_wrap(value)));
+}
+
+
+// EQUALITY
+
+function _Json_equality(x, y)
+{
+ if (x === y)
+ {
+ return true;
+ }
+
+ if (x.$ !== y.$)
+ {
+ return false;
+ }
+
+ switch (x.$)
+ {
+ case 0:
+ case 1:
+ return x.a === y.a;
+
+ case 2:
+ return x.b === y.b;
+
+ case 5:
+ return x.c === y.c;
+
+ case 3:
+ case 4:
+ case 8:
+ return _Json_equality(x.b, y.b);
+
+ case 6:
+ return x.d === y.d && _Json_equality(x.b, y.b);
+
+ case 7:
+ return x.e === y.e && _Json_equality(x.b, y.b);
+
+ case 9:
+ return x.f === y.f && _Json_listEquality(x.g, y.g);
+
+ case 10:
+ return x.h === y.h && _Json_equality(x.b, y.b);
+
+ case 11:
+ return _Json_listEquality(x.g, y.g);
+ }
+}
+
+function _Json_listEquality(aDecoders, bDecoders)
+{
+ var len = aDecoders.length;
+ if (len !== bDecoders.length)
+ {
+ return false;
+ }
+ for (var i = 0; i < len; i++)
+ {
+ if (!_Json_equality(aDecoders[i], bDecoders[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// ENCODE
+
+var _Json_encode = F2(function(indentLevel, value)
+{
+ return JSON.stringify(_Json_unwrap(value), null, indentLevel) + '';
+});
+
+function _Json_wrap_UNUSED(value) { return { $: 0, a: value }; }
+function _Json_unwrap_UNUSED(value) { return value.a; }
+
+function _Json_wrap(value) { return value; }
+function _Json_unwrap(value) { return value; }
+
+function _Json_emptyArray() { return []; }
+function _Json_emptyObject() { return {}; }
+
+var _Json_addField = F3(function(key, value, object)
+{
+ object[key] = _Json_unwrap(value);
+ return object;
+});
+
+function _Json_addEntry(func)
+{
+ return F2(function(entry, array)
+ {
+ array.push(_Json_unwrap(func(entry)));
+ return array;
+ });
+}
+
+var _Json_encodeNull = _Json_wrap(null);
+
+
+
+// TASKS
+
+function _Scheduler_succeed(value)
+{
+ return {
+ $: 0,
+ a: value
+ };
+}
+
+function _Scheduler_fail(error)
+{
+ return {
+ $: 1,
+ a: error
+ };
+}
+
+function _Scheduler_binding(callback)
+{
+ return {
+ $: 2,
+ b: callback,
+ c: null
+ };
+}
+
+var _Scheduler_andThen = F2(function(callback, task)
+{
+ return {
+ $: 3,
+ b: callback,
+ d: task
+ };
+});
+
+var _Scheduler_onError = F2(function(callback, task)
+{
+ return {
+ $: 4,
+ b: callback,
+ d: task
+ };
+});
+
+function _Scheduler_receive(callback)
+{
+ return {
+ $: 5,
+ b: callback
+ };
+}
+
+
+// PROCESSES
+
+var _Scheduler_guid = 0;
+
+function _Scheduler_rawSpawn(task)
+{
+ var proc = {
+ $: 0,
+ e: _Scheduler_guid++,
+ f: task,
+ g: null,
+ h: []
+ };
+
+ _Scheduler_enqueue(proc);
+
+ return proc;
+}
+
+function _Scheduler_spawn(task)
+{
+ return _Scheduler_binding(function(callback) {
+ callback(_Scheduler_succeed(_Scheduler_rawSpawn(task)));
+ });
+}
+
+function _Scheduler_rawSend(proc, msg)
+{
+ proc.h.push(msg);
+ _Scheduler_enqueue(proc);
+}
+
+var _Scheduler_send = F2(function(proc, msg)
+{
+ return _Scheduler_binding(function(callback) {
+ _Scheduler_rawSend(proc, msg);
+ callback(_Scheduler_succeed(_Utils_Tuple0));
+ });
+});
+
+function _Scheduler_kill(proc)
+{
+ return _Scheduler_binding(function(callback) {
+ var task = proc.f;
+ if (task.$ === 2 && task.c)
+ {
+ task.c();
+ }
+
+ proc.f = null;
+
+ callback(_Scheduler_succeed(_Utils_Tuple0));
+ });
+}
+
+
+/* STEP PROCESSES
+
+type alias Process =
+ { $ : tag
+ , id : unique_id
+ , root : Task
+ , stack : null | { $: SUCCEED | FAIL, a: callback, b: stack }
+ , mailbox : [msg]
+ }
+
+*/
+
+
+var _Scheduler_working = false;
+var _Scheduler_queue = [];
+
+
+function _Scheduler_enqueue(proc)
+{
+ _Scheduler_queue.push(proc);
+ if (_Scheduler_working)
+ {
+ return;
+ }
+ _Scheduler_working = true;
+ while (proc = _Scheduler_queue.shift())
+ {
+ _Scheduler_step(proc);
+ }
+ _Scheduler_working = false;
+}
+
+
+function _Scheduler_step(proc)
+{
+ while (proc.f)
+ {
+ var rootTag = proc.f.$;
+ if (rootTag === 0 || rootTag === 1)
+ {
+ while (proc.g && proc.g.$ !== rootTag)
+ {
+ proc.g = proc.g.i;
+ }
+ if (!proc.g)
+ {
+ return;
+ }
+ proc.f = proc.g.b(proc.f.a);
+ proc.g = proc.g.i;
+ }
+ else if (rootTag === 2)
+ {
+ proc.f.c = proc.f.b(function(newRoot) {
+ proc.f = newRoot;
+ _Scheduler_enqueue(proc);
+ });
+ return;
+ }
+ else if (rootTag === 5)
+ {
+ if (proc.h.length === 0)
+ {
+ return;
+ }
+ proc.f = proc.f.b(proc.h.shift());
+ }
+ else // if (rootTag === 3 || rootTag === 4)
+ {
+ proc.g = {
+ $: rootTag === 3 ? 0 : 1,
+ b: proc.f.b,
+ i: proc.g
+ };
+ proc.f = proc.f.d;
+ }
+ }
+}
+
+
+
+function _Process_sleep(time)
+{
+ return _Scheduler_binding(function(callback) {
+ var id = setTimeout(function() {
+ callback(_Scheduler_succeed(_Utils_Tuple0));
+ }, time);
+
+ return function() { clearTimeout(id); };
+ });
+}
+
+
+
+
+// PROGRAMS
+
+
+var _Platform_worker = F4(function(impl, flagDecoder, debugMetadata, args)
+{
+ return _Platform_initialize(
+ flagDecoder,
+ args,
+ impl.aD,
+ impl.aR,
+ impl.aO,
+ function() { return function() {} }
+ );
+});
+
+
+
+// INITIALIZE A PROGRAM
+
+
+function _Platform_initialize(flagDecoder, args, init, update, subscriptions, stepperBuilder)
+{
+ var result = A2(_Json_run, flagDecoder, _Json_wrap(args ? args['flags'] : undefined));
+ $elm$core$Result$isOk(result) || _Debug_crash(2 /**_UNUSED/, _Json_errorToString(result.a) /**/);
+ var managers = {};
+ result = init(result.a);
+ var model = result.a;
+ var stepper = stepperBuilder(sendToApp, model);
+ var ports = _Platform_setupEffects(managers, sendToApp);
+
+ function sendToApp(msg, viewMetadata)
+ {
+ result = A2(update, msg, model);
+ stepper(model = result.a, viewMetadata);
+ _Platform_enqueueEffects(managers, result.b, subscriptions(model));
+ }
+
+ _Platform_enqueueEffects(managers, result.b, subscriptions(model));
+
+ return ports ? { ports: ports } : {};
+}
+
+
+
+// TRACK PRELOADS
+//
+// This is used by code in elm/browser and elm/http
+// to register any HTTP requests that are triggered by init.
+//
+
+
+var _Platform_preload;
+
+
+function _Platform_registerPreload(url)
+{
+ _Platform_preload.add(url);
+}
+
+
+
+// EFFECT MANAGERS
+
+
+var _Platform_effectManagers = {};
+
+
+function _Platform_setupEffects(managers, sendToApp)
+{
+ var ports;
+
+ // setup all necessary effect managers
+ for (var key in _Platform_effectManagers)
+ {
+ var manager = _Platform_effectManagers[key];
+
+ if (manager.a)
+ {
+ ports = ports || {};
+ ports[key] = manager.a(key, sendToApp);
+ }
+
+ managers[key] = _Platform_instantiateManager(manager, sendToApp);
+ }
+
+ return ports;
+}
+
+
+function _Platform_createManager(init, onEffects, onSelfMsg, cmdMap, subMap)
+{
+ return {
+ b: init,
+ c: onEffects,
+ d: onSelfMsg,
+ e: cmdMap,
+ f: subMap
+ };
+}
+
+
+function _Platform_instantiateManager(info, sendToApp)
+{
+ var router = {
+ g: sendToApp,
+ h: undefined
+ };
+
+ var onEffects = info.c;
+ var onSelfMsg = info.d;
+ var cmdMap = info.e;
+ var subMap = info.f;
+
+ function loop(state)
+ {
+ return A2(_Scheduler_andThen, loop, _Scheduler_receive(function(msg)
+ {
+ var value = msg.a;
+
+ if (msg.$ === 0)
+ {
+ return A3(onSelfMsg, router, value, state);
+ }
+
+ return cmdMap && subMap
+ ? A4(onEffects, router, value.i, value.j, state)
+ : A3(onEffects, router, cmdMap ? value.i : value.j, state);
+ }));
+ }
+
+ return router.h = _Scheduler_rawSpawn(A2(_Scheduler_andThen, loop, info.b));
+}
+
+
+
+// ROUTING
+
+
+var _Platform_sendToApp = F2(function(router, msg)
+{
+ return _Scheduler_binding(function(callback)
+ {
+ router.g(msg);
+ callback(_Scheduler_succeed(_Utils_Tuple0));
+ });
+});
+
+
+var _Platform_sendToSelf = F2(function(router, msg)
+{
+ return A2(_Scheduler_send, router.h, {
+ $: 0,
+ a: msg
+ });
+});
+
+
+
+// BAGS
+
+
+function _Platform_leaf(home)
+{
+ return function(value)
+ {
+ return {
+ $: 1,
+ k: home,
+ l: value
+ };
+ };
+}
+
+
+function _Platform_batch(list)
+{
+ return {
+ $: 2,
+ m: list
+ };
+}
+
+
+var _Platform_map = F2(function(tagger, bag)
+{
+ return {
+ $: 3,
+ n: tagger,
+ o: bag
+ }
+});
+
+
+
+// PIPE BAGS INTO EFFECT MANAGERS
+//
+// Effects must be queued!
+//
+// Say your init contains a synchronous command, like Time.now or Time.here
+//
+// - This will produce a batch of effects (FX_1)
+// - The synchronous task triggers the subsequent `update` call
+// - This will produce a batch of effects (FX_2)
+//
+// If we just start dispatching FX_2, subscriptions from FX_2 can be processed
+// before subscriptions from FX_1. No good! Earlier versions of this code had
+// this problem, leading to these reports:
+//
+// https://github.com/elm/core/issues/980
+// https://github.com/elm/core/pull/981
+// https://github.com/elm/compiler/issues/1776
+//
+// The queue is necessary to avoid ordering issues for synchronous commands.
+
+
+// Why use true/false here? Why not just check the length of the queue?
+// The goal is to detect "are we currently dispatching effects?" If we
+// are, we need to bail and let the ongoing while loop handle things.
+//
+// Now say the queue has 1 element. When we dequeue the final element,
+// the queue will be empty, but we are still actively dispatching effects.
+// So you could get queue jumping in a really tricky category of cases.
+//
+var _Platform_effectsQueue = [];
+var _Platform_effectsActive = false;
+
+
+function _Platform_enqueueEffects(managers, cmdBag, subBag)
+{
+ _Platform_effectsQueue.push({ p: managers, q: cmdBag, r: subBag });
+
+ if (_Platform_effectsActive) return;
+
+ _Platform_effectsActive = true;
+ for (var fx; fx = _Platform_effectsQueue.shift(); )
+ {
+ _Platform_dispatchEffects(fx.p, fx.q, fx.r);
+ }
+ _Platform_effectsActive = false;
+}
+
+
+function _Platform_dispatchEffects(managers, cmdBag, subBag)
+{
+ var effectsDict = {};
+ _Platform_gatherEffects(true, cmdBag, effectsDict, null);
+ _Platform_gatherEffects(false, subBag, effectsDict, null);
+
+ for (var home in managers)
+ {
+ _Scheduler_rawSend(managers[home], {
+ $: 'fx',
+ a: effectsDict[home] || { i: _List_Nil, j: _List_Nil }
+ });
+ }
+}
+
+
+function _Platform_gatherEffects(isCmd, bag, effectsDict, taggers)
+{
+ switch (bag.$)
+ {
+ case 1:
+ var home = bag.k;
+ var effect = _Platform_toEffect(isCmd, home, taggers, bag.l);
+ effectsDict[home] = _Platform_insert(isCmd, effect, effectsDict[home]);
+ return;
+
+ case 2:
+ for (var list = bag.m; list.b; list = list.b) // WHILE_CONS
+ {
+ _Platform_gatherEffects(isCmd, list.a, effectsDict, taggers);
+ }
+ return;
+
+ case 3:
+ _Platform_gatherEffects(isCmd, bag.o, effectsDict, {
+ s: bag.n,
+ t: taggers
+ });
+ return;
+ }
+}
+
+
+function _Platform_toEffect(isCmd, home, taggers, value)
+{
+ function applyTaggers(x)
+ {
+ for (var temp = taggers; temp; temp = temp.t)
+ {
+ x = temp.s(x);
+ }
+ return x;
+ }
+
+ var map = isCmd
+ ? _Platform_effectManagers[home].e
+ : _Platform_effectManagers[home].f;
+
+ return A2(map, applyTaggers, value)
+}
+
+
+function _Platform_insert(isCmd, newEffect, effects)
+{
+ effects = effects || { i: _List_Nil, j: _List_Nil };
+
+ isCmd
+ ? (effects.i = _List_Cons(newEffect, effects.i))
+ : (effects.j = _List_Cons(newEffect, effects.j));
+
+ return effects;
+}
+
+
+
+// PORTS
+
+
+function _Platform_checkPortName(name)
+{
+ if (_Platform_effectManagers[name])
+ {
+ _Debug_crash(3, name)
+ }
+}
+
+
+
+// OUTGOING PORTS
+
+
+function _Platform_outgoingPort(name, converter)
+{
+ _Platform_checkPortName(name);
+ _Platform_effectManagers[name] = {
+ e: _Platform_outgoingPortMap,
+ u: converter,
+ a: _Platform_setupOutgoingPort
+ };
+ return _Platform_leaf(name);
+}
+
+
+var _Platform_outgoingPortMap = F2(function(tagger, value) { return value; });
+
+
+function _Platform_setupOutgoingPort(name)
+{
+ var subs = [];
+ var converter = _Platform_effectManagers[name].u;
+
+ // CREATE MANAGER
+
+ var init = _Process_sleep(0);
+
+ _Platform_effectManagers[name].b = init;
+ _Platform_effectManagers[name].c = F3(function(router, cmdList, state)
+ {
+ for ( ; cmdList.b; cmdList = cmdList.b) // WHILE_CONS
+ {
+ // grab a separate reference to subs in case unsubscribe is called
+ var currentSubs = subs;
+ var value = _Json_unwrap(converter(cmdList.a));
+ for (var i = 0; i < currentSubs.length; i++)
+ {
+ currentSubs[i](value);
+ }
+ }
+ return init;
+ });
+
+ // PUBLIC API
+
+ function subscribe(callback)
+ {
+ subs.push(callback);
+ }
+
+ function unsubscribe(callback)
+ {
+ // copy subs into a new array in case unsubscribe is called within a
+ // subscribed callback
+ subs = subs.slice();
+ var index = subs.indexOf(callback);
+ if (index >= 0)
+ {
+ subs.splice(index, 1);
+ }
+ }
+
+ return {
+ subscribe: subscribe,
+ unsubscribe: unsubscribe
+ };
+}
+
+
+
+// INCOMING PORTS
+
+
+function _Platform_incomingPort(name, converter)
+{
+ _Platform_checkPortName(name);
+ _Platform_effectManagers[name] = {
+ f: _Platform_incomingPortMap,
+ u: converter,
+ a: _Platform_setupIncomingPort
+ };
+ return _Platform_leaf(name);
+}
+
+
+var _Platform_incomingPortMap = F2(function(tagger, finalTagger)
+{
+ return function(value)
+ {
+ return tagger(finalTagger(value));
+ };
+});
+
+
+function _Platform_setupIncomingPort(name, sendToApp)
+{
+ var subs = _List_Nil;
+ var converter = _Platform_effectManagers[name].u;
+
+ // CREATE MANAGER
+
+ var init = _Scheduler_succeed(null);
+
+ _Platform_effectManagers[name].b = init;
+ _Platform_effectManagers[name].c = F3(function(router, subList, state)
+ {
+ subs = subList;
+ return init;
+ });
+
+ // PUBLIC API
+
+ function send(incomingValue)
+ {
+ var result = A2(_Json_run, converter, _Json_wrap(incomingValue));
+
+ $elm$core$Result$isOk(result) || _Debug_crash(4, name, result.a);
+
+ var value = result.a;
+ for (var temp = subs; temp.b; temp = temp.b) // WHILE_CONS
+ {
+ sendToApp(temp.a(value));
+ }
+ }
+
+ return { send: send };
+}
+
+
+
+// EXPORT ELM MODULES
+//
+// Have DEBUG and PROD versions so that we can (1) give nicer errors in
+// debug mode and (2) not pay for the bits needed for that in prod mode.
+//
+
+
+function _Platform_export(exports)
+{
+ scope['Elm']
+ ? _Platform_mergeExportsProd(scope['Elm'], exports)
+ : scope['Elm'] = exports;
+}
+
+
+function _Platform_mergeExportsProd(obj, exports)
+{
+ for (var name in exports)
+ {
+ (name in obj)
+ ? (name == 'init')
+ ? _Debug_crash(6)
+ : _Platform_mergeExportsProd(obj[name], exports[name])
+ : (obj[name] = exports[name]);
+ }
+}
+
+
+function _Platform_export_UNUSED(exports)
+{
+ scope['Elm']
+ ? _Platform_mergeExportsDebug('Elm', scope['Elm'], exports)
+ : scope['Elm'] = exports;
+}
+
+
+function _Platform_mergeExportsDebug(moduleName, obj, exports)
+{
+ for (var name in exports)
+ {
+ (name in obj)
+ ? (name == 'init')
+ ? _Debug_crash(6, moduleName)
+ : _Platform_mergeExportsDebug(moduleName + '.' + name, obj[name], exports[name])
+ : (obj[name] = exports[name]);
+ }
+}
+
+
+
+
+// HELPERS
+
+
+var _VirtualDom_divertHrefToApp;
+
+var _VirtualDom_doc = typeof document !== 'undefined' ? document : {};
+
+
+function _VirtualDom_appendChild(parent, child)
+{
+ parent.appendChild(child);
+}
+
+var _VirtualDom_init = F4(function(virtualNode, flagDecoder, debugMetadata, args)
+{
+ // NOTE: this function needs _Platform_export available to work
+
+ /**/
+ var node = args['node'];
+ //*/
+ /**_UNUSED/
+ var node = args && args['node'] ? args['node'] : _Debug_crash(0);
+ //*/
+
+ node.parentNode.replaceChild(
+ _VirtualDom_render(virtualNode, function() {}),
+ node
+ );
+
+ return {};
+});
+
+
+
+// TEXT
+
+
+function _VirtualDom_text(string)
+{
+ return {
+ $: 0,
+ a: string
+ };
+}
+
+
+
+// NODE
+
+
+var _VirtualDom_nodeNS = F2(function(namespace, tag)
+{
+ return F2(function(factList, kidList)
+ {
+ for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS
+ {
+ var kid = kidList.a;
+ descendantsCount += (kid.b || 0);
+ kids.push(kid);
+ }
+ descendantsCount += kids.length;
+
+ return {
+ $: 1,
+ c: tag,
+ d: _VirtualDom_organizeFacts(factList),
+ e: kids,
+ f: namespace,
+ b: descendantsCount
+ };
+ });
+});
+
+
+var _VirtualDom_node = _VirtualDom_nodeNS(undefined);
+
+
+
+// KEYED NODE
+
+
+var _VirtualDom_keyedNodeNS = F2(function(namespace, tag)
+{
+ return F2(function(factList, kidList)
+ {
+ for (var kids = [], descendantsCount = 0; kidList.b; kidList = kidList.b) // WHILE_CONS
+ {
+ var kid = kidList.a;
+ descendantsCount += (kid.b.b || 0);
+ kids.push(kid);
+ }
+ descendantsCount += kids.length;
+
+ return {
+ $: 2,
+ c: tag,
+ d: _VirtualDom_organizeFacts(factList),
+ e: kids,
+ f: namespace,
+ b: descendantsCount
+ };
+ });
+});
+
+
+var _VirtualDom_keyedNode = _VirtualDom_keyedNodeNS(undefined);
+
+
+
+// CUSTOM
+
+
+function _VirtualDom_custom(factList, model, render, diff)
+{
+ return {
+ $: 3,
+ d: _VirtualDom_organizeFacts(factList),
+ g: model,
+ h: render,
+ i: diff
+ };
+}
+
+
+
+// MAP
+
+
+var _VirtualDom_map = F2(function(tagger, node)
+{
+ return {
+ $: 4,
+ j: tagger,
+ k: node,
+ b: 1 + (node.b || 0)
+ };
+});
+
+
+
+// LAZY
+
+
+function _VirtualDom_thunk(refs, thunk)
+{
+ return {
+ $: 5,
+ l: refs,
+ m: thunk,
+ k: undefined
+ };
+}
+
+var _VirtualDom_lazy = F2(function(func, a)
+{
+ return _VirtualDom_thunk([func, a], function() {
+ return func(a);
+ });
+});
+
+var _VirtualDom_lazy2 = F3(function(func, a, b)
+{
+ return _VirtualDom_thunk([func, a, b], function() {
+ return A2(func, a, b);
+ });
+});
+
+var _VirtualDom_lazy3 = F4(function(func, a, b, c)
+{
+ return _VirtualDom_thunk([func, a, b, c], function() {
+ return A3(func, a, b, c);
+ });
+});
+
+var _VirtualDom_lazy4 = F5(function(func, a, b, c, d)
+{
+ return _VirtualDom_thunk([func, a, b, c, d], function() {
+ return A4(func, a, b, c, d);
+ });
+});
+
+var _VirtualDom_lazy5 = F6(function(func, a, b, c, d, e)
+{
+ return _VirtualDom_thunk([func, a, b, c, d, e], function() {
+ return A5(func, a, b, c, d, e);
+ });
+});
+
+var _VirtualDom_lazy6 = F7(function(func, a, b, c, d, e, f)
+{
+ return _VirtualDom_thunk([func, a, b, c, d, e, f], function() {
+ return A6(func, a, b, c, d, e, f);
+ });
+});
+
+var _VirtualDom_lazy7 = F8(function(func, a, b, c, d, e, f, g)
+{
+ return _VirtualDom_thunk([func, a, b, c, d, e, f, g], function() {
+ return A7(func, a, b, c, d, e, f, g);
+ });
+});
+
+var _VirtualDom_lazy8 = F9(function(func, a, b, c, d, e, f, g, h)
+{
+ return _VirtualDom_thunk([func, a, b, c, d, e, f, g, h], function() {
+ return A8(func, a, b, c, d, e, f, g, h);
+ });
+});
+
+
+
+// FACTS
+
+
+var _VirtualDom_on = F2(function(key, handler)
+{
+ return {
+ $: 'a0',
+ n: key,
+ o: handler
+ };
+});
+var _VirtualDom_style = F2(function(key, value)
+{
+ return {
+ $: 'a1',
+ n: key,
+ o: value
+ };
+});
+var _VirtualDom_property = F2(function(key, value)
+{
+ return {
+ $: 'a2',
+ n: key,
+ o: value
+ };
+});
+var _VirtualDom_attribute = F2(function(key, value)
+{
+ return {
+ $: 'a3',
+ n: key,
+ o: value
+ };
+});
+var _VirtualDom_attributeNS = F3(function(namespace, key, value)
+{
+ return {
+ $: 'a4',
+ n: key,
+ o: { f: namespace, o: value }
+ };
+});
+
+
+
+// XSS ATTACK VECTOR CHECKS
+
+
+function _VirtualDom_noScript(tag)
+{
+ return tag == 'script' ? 'p' : tag;
+}
+
+function _VirtualDom_noOnOrFormAction(key)
+{
+ return /^(on|formAction$)/i.test(key) ? 'data-' + key : key;
+}
+
+function _VirtualDom_noInnerHtmlOrFormAction(key)
+{
+ return key == 'innerHTML' || key == 'formAction' ? 'data-' + key : key;
+}
+
+function _VirtualDom_noJavaScriptUri(value)
+{
+ return /^javascript:/i.test(value.replace(/\s/g,'')) ? '' : value;
+}
+
+function _VirtualDom_noJavaScriptUri_UNUSED(value)
+{
+ return /^javascript:/i.test(value.replace(/\s/g,''))
+ ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")'
+ : value;
+}
+
+function _VirtualDom_noJavaScriptOrHtmlUri(value)
+{
+ return /^\s*(javascript:|data:text\/html)/i.test(value) ? '' : value;
+}
+
+function _VirtualDom_noJavaScriptOrHtmlUri_UNUSED(value)
+{
+ return /^\s*(javascript:|data:text\/html)/i.test(value)
+ ? 'javascript:alert("This is an XSS vector. Please use ports or web components instead.")'
+ : value;
+}
+
+
+
+// MAP FACTS
+
+
+var _VirtualDom_mapAttribute = F2(function(func, attr)
+{
+ return (attr.$ === 'a0')
+ ? A2(_VirtualDom_on, attr.n, _VirtualDom_mapHandler(func, attr.o))
+ : attr;
+});
+
+function _VirtualDom_mapHandler(func, handler)
+{
+ var tag = $elm$virtual_dom$VirtualDom$toHandlerInt(handler);
+
+ // 0 = Normal
+ // 1 = MayStopPropagation
+ // 2 = MayPreventDefault
+ // 3 = Custom
+
+ return {
+ $: handler.$,
+ a:
+ !tag
+ ? A2($elm$json$Json$Decode$map, func, handler.a)
+ :
+ A3($elm$json$Json$Decode$map2,
+ tag < 3
+ ? _VirtualDom_mapEventTuple
+ : _VirtualDom_mapEventRecord,
+ $elm$json$Json$Decode$succeed(func),
+ handler.a
+ )
+ };
+}
+
+var _VirtualDom_mapEventTuple = F2(function(func, tuple)
+{
+ return _Utils_Tuple2(func(tuple.a), tuple.b);
+});
+
+var _VirtualDom_mapEventRecord = F2(function(func, record)
+{
+ return {
+ E: func(record.E),
+ L: record.L,
+ I: record.I
+ }
+});
+
+
+
+// ORGANIZE FACTS
+
+
+function _VirtualDom_organizeFacts(factList)
+{
+ for (var facts = {}; factList.b; factList = factList.b) // WHILE_CONS
+ {
+ var entry = factList.a;
+
+ var tag = entry.$;
+ var key = entry.n;
+ var value = entry.o;
+
+ if (tag === 'a2')
+ {
+ (key === 'className')
+ ? _VirtualDom_addClass(facts, key, _Json_unwrap(value))
+ : facts[key] = _Json_unwrap(value);
+
+ continue;
+ }
+
+ var subFacts = facts[tag] || (facts[tag] = {});
+ (tag === 'a3' && key === 'class')
+ ? _VirtualDom_addClass(subFacts, key, value)
+ : subFacts[key] = value;
+ }
+
+ return facts;
+}
+
+function _VirtualDom_addClass(object, key, newClass)
+{
+ var classes = object[key];
+ object[key] = classes ? classes + ' ' + newClass : newClass;
+}
+
+
+
+// RENDER
+
+
+function _VirtualDom_render(vNode, eventNode)
+{
+ var tag = vNode.$;
+
+ if (tag === 5)
+ {
+ return _VirtualDom_render(vNode.k || (vNode.k = vNode.m()), eventNode);
+ }
+
+ if (tag === 0)
+ {
+ return _VirtualDom_doc.createTextNode(vNode.a);
+ }
+
+ if (tag === 4)
+ {
+ var subNode = vNode.k;
+ var tagger = vNode.j;
+
+ while (subNode.$ === 4)
+ {
+ typeof tagger !== 'object'
+ ? tagger = [tagger, subNode.j]
+ : tagger.push(subNode.j);
+
+ subNode = subNode.k;
+ }
+
+ var subEventRoot = { j: tagger, p: eventNode };
+ var domNode = _VirtualDom_render(subNode, subEventRoot);
+ domNode.elm_event_node_ref = subEventRoot;
+ return domNode;
+ }
+
+ if (tag === 3)
+ {
+ var domNode = vNode.h(vNode.g);
+ _VirtualDom_applyFacts(domNode, eventNode, vNode.d);
+ return domNode;
+ }
+
+ // at this point `tag` must be 1 or 2
+
+ var domNode = vNode.f
+ ? _VirtualDom_doc.createElementNS(vNode.f, vNode.c)
+ : _VirtualDom_doc.createElement(vNode.c);
+
+ if (_VirtualDom_divertHrefToApp && vNode.c == 'a')
+ {
+ domNode.addEventListener('click', _VirtualDom_divertHrefToApp(domNode));
+ }
+
+ _VirtualDom_applyFacts(domNode, eventNode, vNode.d);
+
+ for (var kids = vNode.e, i = 0; i < kids.length; i++)
+ {
+ _VirtualDom_appendChild(domNode, _VirtualDom_render(tag === 1 ? kids[i] : kids[i].b, eventNode));
+ }
+
+ return domNode;
+}
+
+
+
+// APPLY FACTS
+
+
+function _VirtualDom_applyFacts(domNode, eventNode, facts)
+{
+ for (var key in facts)
+ {
+ var value = facts[key];
+
+ key === 'a1'
+ ? _VirtualDom_applyStyles(domNode, value)
+ :
+ key === 'a0'
+ ? _VirtualDom_applyEvents(domNode, eventNode, value)
+ :
+ key === 'a3'
+ ? _VirtualDom_applyAttrs(domNode, value)
+ :
+ key === 'a4'
+ ? _VirtualDom_applyAttrsNS(domNode, value)
+ :
+ ((key !== 'value' && key !== 'checked') || domNode[key] !== value) && (domNode[key] = value);
+ }
+}
+
+
+
+// APPLY STYLES
+
+
+function _VirtualDom_applyStyles(domNode, styles)
+{
+ var domNodeStyle = domNode.style;
+
+ for (var key in styles)
+ {
+ domNodeStyle[key] = styles[key];
+ }
+}
+
+
+
+// APPLY ATTRS
+
+
+function _VirtualDom_applyAttrs(domNode, attrs)
+{
+ for (var key in attrs)
+ {
+ var value = attrs[key];
+ typeof value !== 'undefined'
+ ? domNode.setAttribute(key, value)
+ : domNode.removeAttribute(key);
+ }
+}
+
+
+
+// APPLY NAMESPACED ATTRS
+
+
+function _VirtualDom_applyAttrsNS(domNode, nsAttrs)
+{
+ for (var key in nsAttrs)
+ {
+ var pair = nsAttrs[key];
+ var namespace = pair.f;
+ var value = pair.o;
+
+ typeof value !== 'undefined'
+ ? domNode.setAttributeNS(namespace, key, value)
+ : domNode.removeAttributeNS(namespace, key);
+ }
+}
+
+
+
+// APPLY EVENTS
+
+
+function _VirtualDom_applyEvents(domNode, eventNode, events)
+{
+ var allCallbacks = domNode.elmFs || (domNode.elmFs = {});
+
+ for (var key in events)
+ {
+ var newHandler = events[key];
+ var oldCallback = allCallbacks[key];
+
+ if (!newHandler)
+ {
+ domNode.removeEventListener(key, oldCallback);
+ allCallbacks[key] = undefined;
+ continue;
+ }
+
+ if (oldCallback)
+ {
+ var oldHandler = oldCallback.q;
+ if (oldHandler.$ === newHandler.$)
+ {
+ oldCallback.q = newHandler;
+ continue;
+ }
+ domNode.removeEventListener(key, oldCallback);
+ }
+
+ oldCallback = _VirtualDom_makeCallback(eventNode, newHandler);
+ domNode.addEventListener(key, oldCallback,
+ _VirtualDom_passiveSupported
+ && { passive: $elm$virtual_dom$VirtualDom$toHandlerInt(newHandler) < 2 }
+ );
+ allCallbacks[key] = oldCallback;
+ }
+}
+
+
+
+// PASSIVE EVENTS
+
+
+var _VirtualDom_passiveSupported;
+
+try
+{
+ window.addEventListener('t', null, Object.defineProperty({}, 'passive', {
+ get: function() { _VirtualDom_passiveSupported = true; }
+ }));
+}
+catch(e) {}
+
+
+
+// EVENT HANDLERS
+
+
+function _VirtualDom_makeCallback(eventNode, initialHandler)
+{
+ function callback(event)
+ {
+ var handler = callback.q;
+ var result = _Json_runHelp(handler.a, event);
+
+ if (!$elm$core$Result$isOk(result))
+ {
+ return;
+ }
+
+ var tag = $elm$virtual_dom$VirtualDom$toHandlerInt(handler);
+
+ // 0 = Normal
+ // 1 = MayStopPropagation
+ // 2 = MayPreventDefault
+ // 3 = Custom
+
+ var value = result.a;
+ var message = !tag ? value : tag < 3 ? value.a : value.E;
+ var stopPropagation = tag == 1 ? value.b : tag == 3 && value.L;
+ var currentEventNode = (
+ stopPropagation && event.stopPropagation(),
+ (tag == 2 ? value.b : tag == 3 && value.I) && event.preventDefault(),
+ eventNode
+ );
+ var tagger;
+ var i;
+ while (tagger = currentEventNode.j)
+ {
+ if (typeof tagger == 'function')
+ {
+ message = tagger(message);
+ }
+ else
+ {
+ for (var i = tagger.length; i--; )
+ {
+ message = tagger[i](message);
+ }
+ }
+ currentEventNode = currentEventNode.p;
+ }
+ currentEventNode(message, stopPropagation); // stopPropagation implies isSync
+ }
+
+ callback.q = initialHandler;
+
+ return callback;
+}
+
+function _VirtualDom_equalEvents(x, y)
+{
+ return x.$ == y.$ && _Json_equality(x.a, y.a);
+}
+
+
+
+// DIFF
+
+
+// TODO: Should we do patches like in iOS?
+//
+// type Patch
+// = At Int Patch
+// | Batch (List Patch)
+// | Change ...
+//
+// How could it not be better?
+//
+function _VirtualDom_diff(x, y)
+{
+ var patches = [];
+ _VirtualDom_diffHelp(x, y, patches, 0);
+ return patches;
+}
+
+
+function _VirtualDom_pushPatch(patches, type, index, data)
+{
+ var patch = {
+ $: type,
+ r: index,
+ s: data,
+ t: undefined,
+ u: undefined
+ };
+ patches.push(patch);
+ return patch;
+}
+
+
+function _VirtualDom_diffHelp(x, y, patches, index)
+{
+ if (x === y)
+ {
+ return;
+ }
+
+ var xType = x.$;
+ var yType = y.$;
+
+ // Bail if you run into different types of nodes. Implies that the
+ // structure has changed significantly and it's not worth a diff.
+ if (xType !== yType)
+ {
+ if (xType === 1 && yType === 2)
+ {
+ y = _VirtualDom_dekey(y);
+ yType = 1;
+ }
+ else
+ {
+ _VirtualDom_pushPatch(patches, 0, index, y);
+ return;
+ }
+ }
+
+ // Now we know that both nodes are the same $.
+ switch (yType)
+ {
+ case 5:
+ var xRefs = x.l;
+ var yRefs = y.l;
+ var i = xRefs.length;
+ var same = i === yRefs.length;
+ while (same && i--)
+ {
+ same = xRefs[i] === yRefs[i];
+ }
+ if (same)
+ {
+ y.k = x.k;
+ return;
+ }
+ y.k = y.m();
+ var subPatches = [];
+ _VirtualDom_diffHelp(x.k, y.k, subPatches, 0);
+ subPatches.length > 0 && _VirtualDom_pushPatch(patches, 1, index, subPatches);
+ return;
+
+ case 4:
+ // gather nested taggers
+ var xTaggers = x.j;
+ var yTaggers = y.j;
+ var nesting = false;
+
+ var xSubNode = x.k;
+ while (xSubNode.$ === 4)
+ {
+ nesting = true;
+
+ typeof xTaggers !== 'object'
+ ? xTaggers = [xTaggers, xSubNode.j]
+ : xTaggers.push(xSubNode.j);
+
+ xSubNode = xSubNode.k;
+ }
+
+ var ySubNode = y.k;
+ while (ySubNode.$ === 4)
+ {
+ nesting = true;
+
+ typeof yTaggers !== 'object'
+ ? yTaggers = [yTaggers, ySubNode.j]
+ : yTaggers.push(ySubNode.j);
+
+ ySubNode = ySubNode.k;
+ }
+
+ // Just bail if different numbers of taggers. This implies the
+ // structure of the virtual DOM has changed.
+ if (nesting && xTaggers.length !== yTaggers.length)
+ {
+ _VirtualDom_pushPatch(patches, 0, index, y);
+ return;
+ }
+
+ // check if taggers are "the same"
+ if (nesting ? !_VirtualDom_pairwiseRefEqual(xTaggers, yTaggers) : xTaggers !== yTaggers)
+ {
+ _VirtualDom_pushPatch(patches, 2, index, yTaggers);
+ }
+
+ // diff everything below the taggers
+ _VirtualDom_diffHelp(xSubNode, ySubNode, patches, index + 1);
+ return;
+
+ case 0:
+ if (x.a !== y.a)
+ {
+ _VirtualDom_pushPatch(patches, 3, index, y.a);
+ }
+ return;
+
+ case 1:
+ _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKids);
+ return;
+
+ case 2:
+ _VirtualDom_diffNodes(x, y, patches, index, _VirtualDom_diffKeyedKids);
+ return;
+
+ case 3:
+ if (x.h !== y.h)
+ {
+ _VirtualDom_pushPatch(patches, 0, index, y);
+ return;
+ }
+
+ var factsDiff = _VirtualDom_diffFacts(x.d, y.d);
+ factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff);
+
+ var patch = y.i(x.g, y.g);
+ patch && _VirtualDom_pushPatch(patches, 5, index, patch);
+
+ return;
+ }
+}
+
+// assumes the incoming arrays are the same length
+function _VirtualDom_pairwiseRefEqual(as, bs)
+{
+ for (var i = 0; i < as.length; i++)
+ {
+ if (as[i] !== bs[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function _VirtualDom_diffNodes(x, y, patches, index, diffKids)
+{
+ // Bail if obvious indicators have changed. Implies more serious
+ // structural changes such that it's not worth it to diff.
+ if (x.c !== y.c || x.f !== y.f)
+ {
+ _VirtualDom_pushPatch(patches, 0, index, y);
+ return;
+ }
+
+ var factsDiff = _VirtualDom_diffFacts(x.d, y.d);
+ factsDiff && _VirtualDom_pushPatch(patches, 4, index, factsDiff);
+
+ diffKids(x, y, patches, index);
+}
+
+
+
+// DIFF FACTS
+
+
+// TODO Instead of creating a new diff object, it's possible to just test if
+// there *is* a diff. During the actual patch, do the diff again and make the
+// modifications directly. This way, there's no new allocations. Worth it?
+function _VirtualDom_diffFacts(x, y, category)
+{
+ var diff;
+
+ // look for changes and removals
+ for (var xKey in x)
+ {
+ if (xKey === 'a1' || xKey === 'a0' || xKey === 'a3' || xKey === 'a4')
+ {
+ var subDiff = _VirtualDom_diffFacts(x[xKey], y[xKey] || {}, xKey);
+ if (subDiff)
+ {
+ diff = diff || {};
+ diff[xKey] = subDiff;
+ }
+ continue;
+ }
+
+ // remove if not in the new facts
+ if (!(xKey in y))
+ {
+ diff = diff || {};
+ diff[xKey] =
+ !category
+ ? (typeof x[xKey] === 'string' ? '' : null)
+ :
+ (category === 'a1')
+ ? ''
+ :
+ (category === 'a0' || category === 'a3')
+ ? undefined
+ :
+ { f: x[xKey].f, o: undefined };
+
+ continue;
+ }
+
+ var xValue = x[xKey];
+ var yValue = y[xKey];
+
+ // reference equal, so don't worry about it
+ if (xValue === yValue && xKey !== 'value' && xKey !== 'checked'
+ || category === 'a0' && _VirtualDom_equalEvents(xValue, yValue))
+ {
+ continue;
+ }
+
+ diff = diff || {};
+ diff[xKey] = yValue;
+ }
+
+ // add new stuff
+ for (var yKey in y)
+ {
+ if (!(yKey in x))
+ {
+ diff = diff || {};
+ diff[yKey] = y[yKey];
+ }
+ }
+
+ return diff;
+}
+
+
+
+// DIFF KIDS
+
+
+function _VirtualDom_diffKids(xParent, yParent, patches, index)
+{
+ var xKids = xParent.e;
+ var yKids = yParent.e;
+
+ var xLen = xKids.length;
+ var yLen = yKids.length;
+
+ // FIGURE OUT IF THERE ARE INSERTS OR REMOVALS
+
+ if (xLen > yLen)
+ {
+ _VirtualDom_pushPatch(patches, 6, index, {
+ v: yLen,
+ i: xLen - yLen
+ });
+ }
+ else if (xLen < yLen)
+ {
+ _VirtualDom_pushPatch(patches, 7, index, {
+ v: xLen,
+ e: yKids
+ });
+ }
+
+ // PAIRWISE DIFF EVERYTHING ELSE
+
+ for (var minLen = xLen < yLen ? xLen : yLen, i = 0; i < minLen; i++)
+ {
+ var xKid = xKids[i];
+ _VirtualDom_diffHelp(xKid, yKids[i], patches, ++index);
+ index += xKid.b || 0;
+ }
+}
+
+
+
+// KEYED DIFF
+
+
+function _VirtualDom_diffKeyedKids(xParent, yParent, patches, rootIndex)
+{
+ var localPatches = [];
+
+ var changes = {}; // Dict String Entry
+ var inserts = []; // Array { index : Int, entry : Entry }
+ // type Entry = { tag : String, vnode : VNode, index : Int, data : _ }
+
+ var xKids = xParent.e;
+ var yKids = yParent.e;
+ var xLen = xKids.length;
+ var yLen = yKids.length;
+ var xIndex = 0;
+ var yIndex = 0;
+
+ var index = rootIndex;
+
+ while (xIndex < xLen && yIndex < yLen)
+ {
+ var x = xKids[xIndex];
+ var y = yKids[yIndex];
+
+ var xKey = x.a;
+ var yKey = y.a;
+ var xNode = x.b;
+ var yNode = y.b;
+
+ var newMatch = undefined;
+ var oldMatch = undefined;
+
+ // check if keys match
+
+ if (xKey === yKey)
+ {
+ index++;
+ _VirtualDom_diffHelp(xNode, yNode, localPatches, index);
+ index += xNode.b || 0;
+
+ xIndex++;
+ yIndex++;
+ continue;
+ }
+
+ // look ahead 1 to detect insertions and removals.
+
+ var xNext = xKids[xIndex + 1];
+ var yNext = yKids[yIndex + 1];
+
+ if (xNext)
+ {
+ var xNextKey = xNext.a;
+ var xNextNode = xNext.b;
+ oldMatch = yKey === xNextKey;
+ }
+
+ if (yNext)
+ {
+ var yNextKey = yNext.a;
+ var yNextNode = yNext.b;
+ newMatch = xKey === yNextKey;
+ }
+
+
+ // swap x and y
+ if (newMatch && oldMatch)
+ {
+ index++;
+ _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index);
+ _VirtualDom_insertNode(changes, localPatches, xKey, yNode, yIndex, inserts);
+ index += xNode.b || 0;
+
+ index++;
+ _VirtualDom_removeNode(changes, localPatches, xKey, xNextNode, index);
+ index += xNextNode.b || 0;
+
+ xIndex += 2;
+ yIndex += 2;
+ continue;
+ }
+
+ // insert y
+ if (newMatch)
+ {
+ index++;
+ _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts);
+ _VirtualDom_diffHelp(xNode, yNextNode, localPatches, index);
+ index += xNode.b || 0;
+
+ xIndex += 1;
+ yIndex += 2;
+ continue;
+ }
+
+ // remove x
+ if (oldMatch)
+ {
+ index++;
+ _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index);
+ index += xNode.b || 0;
+
+ index++;
+ _VirtualDom_diffHelp(xNextNode, yNode, localPatches, index);
+ index += xNextNode.b || 0;
+
+ xIndex += 2;
+ yIndex += 1;
+ continue;
+ }
+
+ // remove x, insert y
+ if (xNext && xNextKey === yNextKey)
+ {
+ index++;
+ _VirtualDom_removeNode(changes, localPatches, xKey, xNode, index);
+ _VirtualDom_insertNode(changes, localPatches, yKey, yNode, yIndex, inserts);
+ index += xNode.b || 0;
+
+ index++;
+ _VirtualDom_diffHelp(xNextNode, yNextNode, localPatches, index);
+ index += xNextNode.b || 0;
+
+ xIndex += 2;
+ yIndex += 2;
+ continue;
+ }
+
+ break;
+ }
+
+ // eat up any remaining nodes with removeNode and insertNode
+
+ while (xIndex < xLen)
+ {
+ index++;
+ var x = xKids[xIndex];
+ var xNode = x.b;
+ _VirtualDom_removeNode(changes, localPatches, x.a, xNode, index);
+ index += xNode.b || 0;
+ xIndex++;
+ }
+
+ while (yIndex < yLen)
+ {
+ var endInserts = endInserts || [];
+ var y = yKids[yIndex];
+ _VirtualDom_insertNode(changes, localPatches, y.a, y.b, undefined, endInserts);
+ yIndex++;
+ }
+
+ if (localPatches.length > 0 || inserts.length > 0 || endInserts)
+ {
+ _VirtualDom_pushPatch(patches, 8, rootIndex, {
+ w: localPatches,
+ x: inserts,
+ y: endInserts
+ });
+ }
+}
+
+
+
+// CHANGES FROM KEYED DIFF
+
+
+var _VirtualDom_POSTFIX = '_elmW6BL';
+
+
+function _VirtualDom_insertNode(changes, localPatches, key, vnode, yIndex, inserts)
+{
+ var entry = changes[key];
+
+ // never seen this key before
+ if (!entry)
+ {
+ entry = {
+ c: 0,
+ z: vnode,
+ r: yIndex,
+ s: undefined
+ };
+
+ inserts.push({ r: yIndex, A: entry });
+ changes[key] = entry;
+
+ return;
+ }
+
+ // this key was removed earlier, a match!
+ if (entry.c === 1)
+ {
+ inserts.push({ r: yIndex, A: entry });
+
+ entry.c = 2;
+ var subPatches = [];
+ _VirtualDom_diffHelp(entry.z, vnode, subPatches, entry.r);
+ entry.r = yIndex;
+ entry.s.s = {
+ w: subPatches,
+ A: entry
+ };
+
+ return;
+ }
+
+ // this key has already been inserted or moved, a duplicate!
+ _VirtualDom_insertNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, yIndex, inserts);
+}
+
+
+function _VirtualDom_removeNode(changes, localPatches, key, vnode, index)
+{
+ var entry = changes[key];
+
+ // never seen this key before
+ if (!entry)
+ {
+ var patch = _VirtualDom_pushPatch(localPatches, 9, index, undefined);
+
+ changes[key] = {
+ c: 1,
+ z: vnode,
+ r: index,
+ s: patch
+ };
+
+ return;
+ }
+
+ // this key was inserted earlier, a match!
+ if (entry.c === 0)
+ {
+ entry.c = 2;
+ var subPatches = [];
+ _VirtualDom_diffHelp(vnode, entry.z, subPatches, index);
+
+ _VirtualDom_pushPatch(localPatches, 9, index, {
+ w: subPatches,
+ A: entry
+ });
+
+ return;
+ }
+
+ // this key has already been removed or moved, a duplicate!
+ _VirtualDom_removeNode(changes, localPatches, key + _VirtualDom_POSTFIX, vnode, index);
+}
+
+
+
+// ADD DOM NODES
+//
+// Each DOM node has an "index" assigned in order of traversal. It is important
+// to minimize our crawl over the actual DOM, so these indexes (along with the
+// descendantsCount of virtual nodes) let us skip touching entire subtrees of
+// the DOM if we know there are no patches there.
+
+
+function _VirtualDom_addDomNodes(domNode, vNode, patches, eventNode)
+{
+ _VirtualDom_addDomNodesHelp(domNode, vNode, patches, 0, 0, vNode.b, eventNode);
+}
+
+
+// assumes `patches` is non-empty and indexes increase monotonically.
+function _VirtualDom_addDomNodesHelp(domNode, vNode, patches, i, low, high, eventNode)
+{
+ var patch = patches[i];
+ var index = patch.r;
+
+ while (index === low)
+ {
+ var patchType = patch.$;
+
+ if (patchType === 1)
+ {
+ _VirtualDom_addDomNodes(domNode, vNode.k, patch.s, eventNode);
+ }
+ else if (patchType === 8)
+ {
+ patch.t = domNode;
+ patch.u = eventNode;
+
+ var subPatches = patch.s.w;
+ if (subPatches.length > 0)
+ {
+ _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode);
+ }
+ }
+ else if (patchType === 9)
+ {
+ patch.t = domNode;
+ patch.u = eventNode;
+
+ var data = patch.s;
+ if (data)
+ {
+ data.A.s = domNode;
+ var subPatches = data.w;
+ if (subPatches.length > 0)
+ {
+ _VirtualDom_addDomNodesHelp(domNode, vNode, subPatches, 0, low, high, eventNode);
+ }
+ }
+ }
+ else
+ {
+ patch.t = domNode;
+ patch.u = eventNode;
+ }
+
+ i++;
+
+ if (!(patch = patches[i]) || (index = patch.r) > high)
+ {
+ return i;
+ }
+ }
+
+ var tag = vNode.$;
+
+ if (tag === 4)
+ {
+ var subNode = vNode.k;
+
+ while (subNode.$ === 4)
+ {
+ subNode = subNode.k;
+ }
+
+ return _VirtualDom_addDomNodesHelp(domNode, subNode, patches, i, low + 1, high, domNode.elm_event_node_ref);
+ }
+
+ // tag must be 1 or 2 at this point
+
+ var vKids = vNode.e;
+ var childNodes = domNode.childNodes;
+ for (var j = 0; j < vKids.length; j++)
+ {
+ low++;
+ var vKid = tag === 1 ? vKids[j] : vKids[j].b;
+ var nextLow = low + (vKid.b || 0);
+ if (low <= index && index <= nextLow)
+ {
+ i = _VirtualDom_addDomNodesHelp(childNodes[j], vKid, patches, i, low, nextLow, eventNode);
+ if (!(patch = patches[i]) || (index = patch.r) > high)
+ {
+ return i;
+ }
+ }
+ low = nextLow;
+ }
+ return i;
+}
+
+
+
+// APPLY PATCHES
+
+
+function _VirtualDom_applyPatches(rootDomNode, oldVirtualNode, patches, eventNode)
+{
+ if (patches.length === 0)
+ {
+ return rootDomNode;
+ }
+
+ _VirtualDom_addDomNodes(rootDomNode, oldVirtualNode, patches, eventNode);
+ return _VirtualDom_applyPatchesHelp(rootDomNode, patches);
+}
+
+function _VirtualDom_applyPatchesHelp(rootDomNode, patches)
+{
+ for (var i = 0; i < patches.length; i++)
+ {
+ var patch = patches[i];
+ var localDomNode = patch.t
+ var newNode = _VirtualDom_applyPatch(localDomNode, patch);
+ if (localDomNode === rootDomNode)
+ {
+ rootDomNode = newNode;
+ }
+ }
+ return rootDomNode;
+}
+
+function _VirtualDom_applyPatch(domNode, patch)
+{
+ switch (patch.$)
+ {
+ case 0:
+ return _VirtualDom_applyPatchRedraw(domNode, patch.s, patch.u);
+
+ case 4:
+ _VirtualDom_applyFacts(domNode, patch.u, patch.s);
+ return domNode;
+
+ case 3:
+ domNode.replaceData(0, domNode.length, patch.s);
+ return domNode;
+
+ case 1:
+ return _VirtualDom_applyPatchesHelp(domNode, patch.s);
+
+ case 2:
+ if (domNode.elm_event_node_ref)
+ {
+ domNode.elm_event_node_ref.j = patch.s;
+ }
+ else
+ {
+ domNode.elm_event_node_ref = { j: patch.s, p: patch.u };
+ }
+ return domNode;
+
+ case 6:
+ var data = patch.s;
+ for (var i = 0; i < data.i; i++)
+ {
+ domNode.removeChild(domNode.childNodes[data.v]);
+ }
+ return domNode;
+
+ case 7:
+ var data = patch.s;
+ var kids = data.e;
+ var i = data.v;
+ var theEnd = domNode.childNodes[i];
+ for (; i < kids.length; i++)
+ {
+ domNode.insertBefore(_VirtualDom_render(kids[i], patch.u), theEnd);
+ }
+ return domNode;
+
+ case 9:
+ var data = patch.s;
+ if (!data)
+ {
+ domNode.parentNode.removeChild(domNode);
+ return domNode;
+ }
+ var entry = data.A;
+ if (typeof entry.r !== 'undefined')
+ {
+ domNode.parentNode.removeChild(domNode);
+ }
+ entry.s = _VirtualDom_applyPatchesHelp(domNode, data.w);
+ return domNode;
+
+ case 8:
+ return _VirtualDom_applyPatchReorder(domNode, patch);
+
+ case 5:
+ return patch.s(domNode);
+
+ default:
+ _Debug_crash(10); // 'Ran into an unknown patch!'
+ }
+}
+
+
+function _VirtualDom_applyPatchRedraw(domNode, vNode, eventNode)
+{
+ var parentNode = domNode.parentNode;
+ var newNode = _VirtualDom_render(vNode, eventNode);
+
+ if (!newNode.elm_event_node_ref)
+ {
+ newNode.elm_event_node_ref = domNode.elm_event_node_ref;
+ }
+
+ if (parentNode && newNode !== domNode)
+ {
+ parentNode.replaceChild(newNode, domNode);
+ }
+ return newNode;
+}
+
+
+function _VirtualDom_applyPatchReorder(domNode, patch)
+{
+ var data = patch.s;
+
+ // remove end inserts
+ var frag = _VirtualDom_applyPatchReorderEndInsertsHelp(data.y, patch);
+
+ // removals
+ domNode = _VirtualDom_applyPatchesHelp(domNode, data.w);
+
+ // inserts
+ var inserts = data.x;
+ for (var i = 0; i < inserts.length; i++)
+ {
+ var insert = inserts[i];
+ var entry = insert.A;
+ var node = entry.c === 2
+ ? entry.s
+ : _VirtualDom_render(entry.z, patch.u);
+ domNode.insertBefore(node, domNode.childNodes[insert.r]);
+ }
+
+ // add end inserts
+ if (frag)
+ {
+ _VirtualDom_appendChild(domNode, frag);
+ }
+
+ return domNode;
+}
+
+
+function _VirtualDom_applyPatchReorderEndInsertsHelp(endInserts, patch)
+{
+ if (!endInserts)
+ {
+ return;
+ }
+
+ var frag = _VirtualDom_doc.createDocumentFragment();
+ for (var i = 0; i < endInserts.length; i++)
+ {
+ var insert = endInserts[i];
+ var entry = insert.A;
+ _VirtualDom_appendChild(frag, entry.c === 2
+ ? entry.s
+ : _VirtualDom_render(entry.z, patch.u)
+ );
+ }
+ return frag;
+}
+
+
+function _VirtualDom_virtualize(node)
+{
+ // TEXT NODES
+
+ if (node.nodeType === 3)
+ {
+ return _VirtualDom_text(node.textContent);
+ }
+
+
+ // WEIRD NODES
+
+ if (node.nodeType !== 1)
+ {
+ return _VirtualDom_text('');
+ }
+
+
+ // ELEMENT NODES
+
+ var attrList = _List_Nil;
+ var attrs = node.attributes;
+ for (var i = attrs.length; i--; )
+ {
+ var attr = attrs[i];
+ var name = attr.name;
+ var value = attr.value;
+ attrList = _List_Cons( A2(_VirtualDom_attribute, name, value), attrList );
+ }
+
+ var tag = node.tagName.toLowerCase();
+ var kidList = _List_Nil;
+ var kids = node.childNodes;
+
+ for (var i = kids.length; i--; )
+ {
+ kidList = _List_Cons(_VirtualDom_virtualize(kids[i]), kidList);
+ }
+ return A3(_VirtualDom_node, tag, attrList, kidList);
+}
+
+function _VirtualDom_dekey(keyedNode)
+{
+ var keyedKids = keyedNode.e;
+ var len = keyedKids.length;
+ var kids = new Array(len);
+ for (var i = 0; i < len; i++)
+ {
+ kids[i] = keyedKids[i].b;
+ }
+
+ return {
+ $: 1,
+ c: keyedNode.c,
+ d: keyedNode.d,
+ e: kids,
+ f: keyedNode.f,
+ b: keyedNode.b
+ };
+}
+
+
+
+
+// ELEMENT
+
+
+var _Debugger_element;
+
+var _Browser_element = _Debugger_element || F4(function(impl, flagDecoder, debugMetadata, args)
+{
+ return _Platform_initialize(
+ flagDecoder,
+ args,
+ impl.aD,
+ impl.aR,
+ impl.aO,
+ function(sendToApp, initialModel) {
+ var view = impl.aS;
+ /**/
+ var domNode = args['node'];
+ //*/
+ /**_UNUSED/
+ var domNode = args && args['node'] ? args['node'] : _Debug_crash(0);
+ //*/
+ var currNode = _VirtualDom_virtualize(domNode);
+
+ return _Browser_makeAnimator(initialModel, function(model)
+ {
+ var nextNode = view(model);
+ var patches = _VirtualDom_diff(currNode, nextNode);
+ domNode = _VirtualDom_applyPatches(domNode, currNode, patches, sendToApp);
+ currNode = nextNode;
+ });
+ }
+ );
+});
+
+
+
+// DOCUMENT
+
+
+var _Debugger_document;
+
+var _Browser_document = _Debugger_document || F4(function(impl, flagDecoder, debugMetadata, args)
+{
+ return _Platform_initialize(
+ flagDecoder,
+ args,
+ impl.aD,
+ impl.aR,
+ impl.aO,
+ function(sendToApp, initialModel) {
+ var divertHrefToApp = impl.J && impl.J(sendToApp)
+ var view = impl.aS;
+ var title = _VirtualDom_doc.title;
+ var bodyNode = _VirtualDom_doc.body;
+ var currNode = _VirtualDom_virtualize(bodyNode);
+ return _Browser_makeAnimator(initialModel, function(model)
+ {
+ _VirtualDom_divertHrefToApp = divertHrefToApp;
+ var doc = view(model);
+ var nextNode = _VirtualDom_node('body')(_List_Nil)(doc.O);
+ var patches = _VirtualDom_diff(currNode, nextNode);
+ bodyNode = _VirtualDom_applyPatches(bodyNode, currNode, patches, sendToApp);
+ currNode = nextNode;
+ _VirtualDom_divertHrefToApp = 0;
+ (title !== doc.aQ) && (_VirtualDom_doc.title = title = doc.aQ);
+ });
+ }
+ );
+});
+
+
+
+// ANIMATION
+
+
+var _Browser_cancelAnimationFrame =
+ typeof cancelAnimationFrame !== 'undefined'
+ ? cancelAnimationFrame
+ : function(id) { clearTimeout(id); };
+
+var _Browser_requestAnimationFrame =
+ typeof requestAnimationFrame !== 'undefined'
+ ? requestAnimationFrame
+ : function(callback) { return setTimeout(callback, 1000 / 60); };
+
+
+function _Browser_makeAnimator(model, draw)
+{
+ draw(model);
+
+ var state = 0;
+
+ function updateIfNeeded()
+ {
+ state = state === 1
+ ? 0
+ : ( _Browser_requestAnimationFrame(updateIfNeeded), draw(model), 1 );
+ }
+
+ return function(nextModel, isSync)
+ {
+ model = nextModel;
+
+ isSync
+ ? ( draw(model),
+ state === 2 && (state = 1)
+ )
+ : ( state === 0 && _Browser_requestAnimationFrame(updateIfNeeded),
+ state = 2
+ );
+ };
+}
+
+
+
+// APPLICATION
+
+
+function _Browser_application(impl)
+{
+ var onUrlChange = impl.aG;
+ var onUrlRequest = impl.aH;
+ var key = function() { key.a(onUrlChange(_Browser_getUrl())); };
+
+ return _Browser_document({
+ J: function(sendToApp)
+ {
+ key.a = sendToApp;
+ _Browser_window.addEventListener('popstate', key);
+ _Browser_window.navigator.userAgent.indexOf('Trident') < 0 || _Browser_window.addEventListener('hashchange', key);
+
+ return F2(function(domNode, event)
+ {
+ if (!event.ctrlKey && !event.metaKey && !event.shiftKey && event.button < 1 && !domNode.target && !domNode.hasAttribute('download'))
+ {
+ event.preventDefault();
+ var href = domNode.href;
+ var curr = _Browser_getUrl();
+ var next = $elm$url$Url$fromString(href).a;
+ sendToApp(onUrlRequest(
+ (next
+ && curr.ae === next.ae
+ && curr.W === next.W
+ && curr.ab.a === next.ab.a
+ )
+ ? $elm$browser$Browser$Internal(next)
+ : $elm$browser$Browser$External(href)
+ ));
+ }
+ });
+ },
+ aD: function(flags)
+ {
+ return A3(impl.aD, flags, _Browser_getUrl(), key);
+ },
+ aS: impl.aS,
+ aR: impl.aR,
+ aO: impl.aO
+ });
+}
+
+function _Browser_getUrl()
+{
+ return $elm$url$Url$fromString(_VirtualDom_doc.location.href).a || _Debug_crash(1);
+}
+
+var _Browser_go = F2(function(key, n)
+{
+ return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() {
+ n && history.go(n);
+ key();
+ }));
+});
+
+var _Browser_pushUrl = F2(function(key, url)
+{
+ return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() {
+ history.pushState({}, '', url);
+ key();
+ }));
+});
+
+var _Browser_replaceUrl = F2(function(key, url)
+{
+ return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function() {
+ history.replaceState({}, '', url);
+ key();
+ }));
+});
+
+
+
+// GLOBAL EVENTS
+
+
+var _Browser_fakeNode = { addEventListener: function() {}, removeEventListener: function() {} };
+var _Browser_doc = typeof document !== 'undefined' ? document : _Browser_fakeNode;
+var _Browser_window = typeof window !== 'undefined' ? window : _Browser_fakeNode;
+
+var _Browser_on = F3(function(node, eventName, sendToSelf)
+{
+ return _Scheduler_spawn(_Scheduler_binding(function(callback)
+ {
+ function handler(event) { _Scheduler_rawSpawn(sendToSelf(event)); }
+ node.addEventListener(eventName, handler, _VirtualDom_passiveSupported && { passive: true });
+ return function() { node.removeEventListener(eventName, handler); };
+ }));
+});
+
+var _Browser_decodeEvent = F2(function(decoder, event)
+{
+ var result = _Json_runHelp(decoder, event);
+ return $elm$core$Result$isOk(result) ? $elm$core$Maybe$Just(result.a) : $elm$core$Maybe$Nothing;
+});
+
+
+
+// PAGE VISIBILITY
+
+
+function _Browser_visibilityInfo()
+{
+ return (typeof _VirtualDom_doc.hidden !== 'undefined')
+ ? { aB: 'hidden', aw: 'visibilitychange' }
+ :
+ (typeof _VirtualDom_doc.mozHidden !== 'undefined')
+ ? { aB: 'mozHidden', aw: 'mozvisibilitychange' }
+ :
+ (typeof _VirtualDom_doc.msHidden !== 'undefined')
+ ? { aB: 'msHidden', aw: 'msvisibilitychange' }
+ :
+ (typeof _VirtualDom_doc.webkitHidden !== 'undefined')
+ ? { aB: 'webkitHidden', aw: 'webkitvisibilitychange' }
+ : { aB: 'hidden', aw: 'visibilitychange' };
+}
+
+
+
+// ANIMATION FRAMES
+
+
+function _Browser_rAF()
+{
+ return _Scheduler_binding(function(callback)
+ {
+ var id = _Browser_requestAnimationFrame(function() {
+ callback(_Scheduler_succeed(Date.now()));
+ });
+
+ return function() {
+ _Browser_cancelAnimationFrame(id);
+ };
+ });
+}
+
+
+function _Browser_now()
+{
+ return _Scheduler_binding(function(callback)
+ {
+ callback(_Scheduler_succeed(Date.now()));
+ });
+}
+
+
+
+// DOM STUFF
+
+
+function _Browser_withNode(id, doStuff)
+{
+ return _Scheduler_binding(function(callback)
+ {
+ _Browser_requestAnimationFrame(function() {
+ var node = document.getElementById(id);
+ callback(node
+ ? _Scheduler_succeed(doStuff(node))
+ : _Scheduler_fail($elm$browser$Browser$Dom$NotFound(id))
+ );
+ });
+ });
+}
+
+
+function _Browser_withWindow(doStuff)
+{
+ return _Scheduler_binding(function(callback)
+ {
+ _Browser_requestAnimationFrame(function() {
+ callback(_Scheduler_succeed(doStuff()));
+ });
+ });
+}
+
+
+// FOCUS and BLUR
+
+
+var _Browser_call = F2(function(functionName, id)
+{
+ return _Browser_withNode(id, function(node) {
+ node[functionName]();
+ return _Utils_Tuple0;
+ });
+});
+
+
+
+// WINDOW VIEWPORT
+
+
+function _Browser_getViewport()
+{
+ return {
+ ak: _Browser_getScene(),
+ ap: {
+ ar: _Browser_window.pageXOffset,
+ as: _Browser_window.pageYOffset,
+ aq: _Browser_doc.documentElement.clientWidth,
+ V: _Browser_doc.documentElement.clientHeight
+ }
+ };
+}
+
+function _Browser_getScene()
+{
+ var body = _Browser_doc.body;
+ var elem = _Browser_doc.documentElement;
+ return {
+ aq: Math.max(body.scrollWidth, body.offsetWidth, elem.scrollWidth, elem.offsetWidth, elem.clientWidth),
+ V: Math.max(body.scrollHeight, body.offsetHeight, elem.scrollHeight, elem.offsetHeight, elem.clientHeight)
+ };
+}
+
+var _Browser_setViewport = F2(function(x, y)
+{
+ return _Browser_withWindow(function()
+ {
+ _Browser_window.scroll(x, y);
+ return _Utils_Tuple0;
+ });
+});
+
+
+
+// ELEMENT VIEWPORT
+
+
+function _Browser_getViewportOf(id)
+{
+ return _Browser_withNode(id, function(node)
+ {
+ return {
+ ak: {
+ aq: node.scrollWidth,
+ V: node.scrollHeight
+ },
+ ap: {
+ ar: node.scrollLeft,
+ as: node.scrollTop,
+ aq: node.clientWidth,
+ V: node.clientHeight
+ }
+ };
+ });
+}
+
+
+var _Browser_setViewportOf = F3(function(id, x, y)
+{
+ return _Browser_withNode(id, function(node)
+ {
+ node.scrollLeft = x;
+ node.scrollTop = y;
+ return _Utils_Tuple0;
+ });
+});
+
+
+
+// ELEMENT
+
+
+function _Browser_getElement(id)
+{
+ return _Browser_withNode(id, function(node)
+ {
+ var rect = node.getBoundingClientRect();
+ var x = _Browser_window.pageXOffset;
+ var y = _Browser_window.pageYOffset;
+ return {
+ ak: _Browser_getScene(),
+ ap: {
+ ar: x,
+ as: y,
+ aq: _Browser_doc.documentElement.clientWidth,
+ V: _Browser_doc.documentElement.clientHeight
+ },
+ ay: {
+ ar: x + rect.left,
+ as: y + rect.top,
+ aq: rect.width,
+ V: rect.height
+ }
+ };
+ });
+}
+
+
+
+// LOAD and RELOAD
+
+
+function _Browser_reload(skipCache)
+{
+ return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function(callback)
+ {
+ _VirtualDom_doc.location.reload(skipCache);
+ }));
+}
+
+function _Browser_load(url)
+{
+ return A2($elm$core$Task$perform, $elm$core$Basics$never, _Scheduler_binding(function(callback)
+ {
+ try
+ {
+ _Browser_window.location = url;
+ }
+ catch(err)
+ {
+ // Only Firefox can throw a NS_ERROR_MALFORMED_URI exception here.
+ // Other browsers reload the page, so let's be consistent about that.
+ _VirtualDom_doc.location.reload(false);
+ }
+ }));
+}
+
+
+
+// SEND REQUEST
+
+var _Http_toTask = F3(function(router, toTask, request)
+{
+ return _Scheduler_binding(function(callback)
+ {
+ function done(response) {
+ callback(toTask(request.az.a(response)));
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.addEventListener('error', function() { done($elm$http$Http$NetworkError_); });
+ xhr.addEventListener('timeout', function() { done($elm$http$Http$Timeout_); });
+ xhr.addEventListener('load', function() { done(_Http_toResponse(request.az.b, xhr)); });
+ $elm$core$Maybe$isJust(request.ao) && _Http_track(router, xhr, request.ao.a);
+
+ try {
+ xhr.open(request.aE, request.M, true);
+ } catch (e) {
+ return done($elm$http$Http$BadUrl_(request.M));
+ }
+
+ _Http_configureRequest(xhr, request);
+
+ request.O.a && xhr.setRequestHeader('Content-Type', request.O.a);
+ xhr.send(request.O.b);
+
+ return function() { xhr.c = true; xhr.abort(); };
+ });
+});
+
+
+// CONFIGURE
+
+function _Http_configureRequest(xhr, request)
+{
+ for (var headers = request.U; headers.b; headers = headers.b) // WHILE_CONS
+ {
+ xhr.setRequestHeader(headers.a.a, headers.a.b);
+ }
+ xhr.timeout = request.aP.a || 0;
+ xhr.responseType = request.az.d;
+ xhr.withCredentials = request.au;
+}
+
+
+// RESPONSES
+
+function _Http_toResponse(toBody, xhr)
+{
+ return A2(
+ 200 <= xhr.status && xhr.status < 300 ? $elm$http$Http$GoodStatus_ : $elm$http$Http$BadStatus_,
+ _Http_toMetadata(xhr),
+ toBody(xhr.response)
+ );
+}
+
+
+// METADATA
+
+function _Http_toMetadata(xhr)
+{
+ return {
+ M: xhr.responseURL,
+ aM: xhr.status,
+ aN: xhr.statusText,
+ U: _Http_parseHeaders(xhr.getAllResponseHeaders())
+ };
+}
+
+
+// HEADERS
+
+function _Http_parseHeaders(rawHeaders)
+{
+ if (!rawHeaders)
+ {
+ return $elm$core$Dict$empty;
+ }
+
+ var headers = $elm$core$Dict$empty;
+ var headerPairs = rawHeaders.split('\r\n');
+ for (var i = headerPairs.length; i--; )
+ {
+ var headerPair = headerPairs[i];
+ var index = headerPair.indexOf(': ');
+ if (index > 0)
+ {
+ var key = headerPair.substring(0, index);
+ var value = headerPair.substring(index + 2);
+
+ headers = A3($elm$core$Dict$update, key, function(oldValue) {
+ return $elm$core$Maybe$Just($elm$core$Maybe$isJust(oldValue)
+ ? value + ', ' + oldValue.a
+ : value
+ );
+ }, headers);
+ }
+ }
+ return headers;
+}
+
+
+// EXPECT
+
+var _Http_expect = F3(function(type, toBody, toValue)
+{
+ return {
+ $: 0,
+ d: type,
+ b: toBody,
+ a: toValue
+ };
+});
+
+var _Http_mapExpect = F2(function(func, expect)
+{
+ return {
+ $: 0,
+ d: expect.d,
+ b: expect.b,
+ a: function(x) { return func(expect.a(x)); }
+ };
+});
+
+function _Http_toDataView(arrayBuffer)
+{
+ return new DataView(arrayBuffer);
+}
+
+
+// BODY and PARTS
+
+var _Http_emptyBody = { $: 0 };
+var _Http_pair = F2(function(a, b) { return { $: 0, a: a, b: b }; });
+
+function _Http_toFormData(parts)
+{
+ for (var formData = new FormData(); parts.b; parts = parts.b) // WHILE_CONS
+ {
+ var part = parts.a;
+ formData.append(part.a, part.b);
+ }
+ return formData;
+}
+
+var _Http_bytesToBlob = F2(function(mime, bytes)
+{
+ return new Blob([bytes], { type: mime });
+});
+
+
+// PROGRESS
+
+function _Http_track(router, xhr, tracker)
+{
+ // TODO check out lengthComputable on loadstart event
+
+ xhr.upload.addEventListener('progress', function(event) {
+ if (xhr.c) { return; }
+ _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Sending({
+ aL: event.loaded,
+ al: event.total
+ }))));
+ });
+ xhr.addEventListener('progress', function(event) {
+ if (xhr.c) { return; }
+ _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Receiving({
+ aJ: event.loaded,
+ al: event.lengthComputable ? $elm$core$Maybe$Just(event.total) : $elm$core$Maybe$Nothing
+ }))));
+ });
+}var $author$project$Main$LinkClicked = function (a) {
+ return {$: 0, a: a};
+};
+var $author$project$Main$UrlChanged = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$core$Basics$EQ = 1;
+var $elm$core$Basics$GT = 2;
+var $elm$core$Basics$LT = 0;
+var $elm$core$List$cons = _List_cons;
+var $elm$core$Dict$foldr = F3(
+ function (func, acc, t) {
+ foldr:
+ while (true) {
+ if (t.$ === -2) {
+ return acc;
+ } else {
+ var key = t.b;
+ var value = t.c;
+ var left = t.d;
+ var right = t.e;
+ var $temp$func = func,
+ $temp$acc = A3(
+ func,
+ key,
+ value,
+ A3($elm$core$Dict$foldr, func, acc, right)),
+ $temp$t = left;
+ func = $temp$func;
+ acc = $temp$acc;
+ t = $temp$t;
+ continue foldr;
+ }
+ }
+ });
+var $elm$core$Dict$toList = function (dict) {
+ return A3(
+ $elm$core$Dict$foldr,
+ F3(
+ function (key, value, list) {
+ return A2(
+ $elm$core$List$cons,
+ _Utils_Tuple2(key, value),
+ list);
+ }),
+ _List_Nil,
+ dict);
+};
+var $elm$core$Dict$keys = function (dict) {
+ return A3(
+ $elm$core$Dict$foldr,
+ F3(
+ function (key, value, keyList) {
+ return A2($elm$core$List$cons, key, keyList);
+ }),
+ _List_Nil,
+ dict);
+};
+var $elm$core$Set$toList = function (_v0) {
+ var dict = _v0;
+ return $elm$core$Dict$keys(dict);
+};
+var $elm$core$Elm$JsArray$foldr = _JsArray_foldr;
+var $elm$core$Array$foldr = F3(
+ function (func, baseCase, _v0) {
+ var tree = _v0.c;
+ var tail = _v0.d;
+ var helper = F2(
+ function (node, acc) {
+ if (!node.$) {
+ var subTree = node.a;
+ return A3($elm$core$Elm$JsArray$foldr, helper, acc, subTree);
+ } else {
+ var values = node.a;
+ return A3($elm$core$Elm$JsArray$foldr, func, acc, values);
+ }
+ });
+ return A3(
+ $elm$core$Elm$JsArray$foldr,
+ helper,
+ A3($elm$core$Elm$JsArray$foldr, func, baseCase, tail),
+ tree);
+ });
+var $elm$core$Array$toList = function (array) {
+ return A3($elm$core$Array$foldr, $elm$core$List$cons, _List_Nil, array);
+};
+var $elm$core$Result$Err = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$json$Json$Decode$Failure = F2(
+ function (a, b) {
+ return {$: 3, a: a, b: b};
+ });
+var $elm$json$Json$Decode$Field = F2(
+ function (a, b) {
+ return {$: 0, a: a, b: b};
+ });
+var $elm$json$Json$Decode$Index = F2(
+ function (a, b) {
+ return {$: 1, a: a, b: b};
+ });
+var $elm$core$Result$Ok = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$json$Json$Decode$OneOf = function (a) {
+ return {$: 2, a: a};
+};
+var $elm$core$Basics$False = 1;
+var $elm$core$Basics$add = _Basics_add;
+var $elm$core$Maybe$Just = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$core$Maybe$Nothing = {$: 1};
+var $elm$core$String$all = _String_all;
+var $elm$core$Basics$and = _Basics_and;
+var $elm$core$Basics$append = _Utils_append;
+var $elm$json$Json$Encode$encode = _Json_encode;
+var $elm$core$String$fromInt = _String_fromNumber;
+var $elm$core$String$join = F2(
+ function (sep, chunks) {
+ return A2(
+ _String_join,
+ sep,
+ _List_toArray(chunks));
+ });
+var $elm$core$String$split = F2(
+ function (sep, string) {
+ return _List_fromArray(
+ A2(_String_split, sep, string));
+ });
+var $elm$json$Json$Decode$indent = function (str) {
+ return A2(
+ $elm$core$String$join,
+ '\n ',
+ A2($elm$core$String$split, '\n', str));
+};
+var $elm$core$List$foldl = F3(
+ function (func, acc, list) {
+ foldl:
+ while (true) {
+ if (!list.b) {
+ return acc;
+ } else {
+ var x = list.a;
+ var xs = list.b;
+ var $temp$func = func,
+ $temp$acc = A2(func, x, acc),
+ $temp$list = xs;
+ func = $temp$func;
+ acc = $temp$acc;
+ list = $temp$list;
+ continue foldl;
+ }
+ }
+ });
+var $elm$core$List$length = function (xs) {
+ return A3(
+ $elm$core$List$foldl,
+ F2(
+ function (_v0, i) {
+ return i + 1;
+ }),
+ 0,
+ xs);
+};
+var $elm$core$List$map2 = _List_map2;
+var $elm$core$Basics$le = _Utils_le;
+var $elm$core$Basics$sub = _Basics_sub;
+var $elm$core$List$rangeHelp = F3(
+ function (lo, hi, list) {
+ rangeHelp:
+ while (true) {
+ if (_Utils_cmp(lo, hi) < 1) {
+ var $temp$lo = lo,
+ $temp$hi = hi - 1,
+ $temp$list = A2($elm$core$List$cons, hi, list);
+ lo = $temp$lo;
+ hi = $temp$hi;
+ list = $temp$list;
+ continue rangeHelp;
+ } else {
+ return list;
+ }
+ }
+ });
+var $elm$core$List$range = F2(
+ function (lo, hi) {
+ return A3($elm$core$List$rangeHelp, lo, hi, _List_Nil);
+ });
+var $elm$core$List$indexedMap = F2(
+ function (f, xs) {
+ return A3(
+ $elm$core$List$map2,
+ f,
+ A2(
+ $elm$core$List$range,
+ 0,
+ $elm$core$List$length(xs) - 1),
+ xs);
+ });
+var $elm$core$Char$toCode = _Char_toCode;
+var $elm$core$Char$isLower = function (_char) {
+ var code = $elm$core$Char$toCode(_char);
+ return (97 <= code) && (code <= 122);
+};
+var $elm$core$Char$isUpper = function (_char) {
+ var code = $elm$core$Char$toCode(_char);
+ return (code <= 90) && (65 <= code);
+};
+var $elm$core$Basics$or = _Basics_or;
+var $elm$core$Char$isAlpha = function (_char) {
+ return $elm$core$Char$isLower(_char) || $elm$core$Char$isUpper(_char);
+};
+var $elm$core$Char$isDigit = function (_char) {
+ var code = $elm$core$Char$toCode(_char);
+ return (code <= 57) && (48 <= code);
+};
+var $elm$core$Char$isAlphaNum = function (_char) {
+ return $elm$core$Char$isLower(_char) || ($elm$core$Char$isUpper(_char) || $elm$core$Char$isDigit(_char));
+};
+var $elm$core$List$reverse = function (list) {
+ return A3($elm$core$List$foldl, $elm$core$List$cons, _List_Nil, list);
+};
+var $elm$core$String$uncons = _String_uncons;
+var $elm$json$Json$Decode$errorOneOf = F2(
+ function (i, error) {
+ return '\n\n(' + ($elm$core$String$fromInt(i + 1) + (') ' + $elm$json$Json$Decode$indent(
+ $elm$json$Json$Decode$errorToString(error))));
+ });
+var $elm$json$Json$Decode$errorToString = function (error) {
+ return A2($elm$json$Json$Decode$errorToStringHelp, error, _List_Nil);
+};
+var $elm$json$Json$Decode$errorToStringHelp = F2(
+ function (error, context) {
+ errorToStringHelp:
+ while (true) {
+ switch (error.$) {
+ case 0:
+ var f = error.a;
+ var err = error.b;
+ var isSimple = function () {
+ var _v1 = $elm$core$String$uncons(f);
+ if (_v1.$ === 1) {
+ return false;
+ } else {
+ var _v2 = _v1.a;
+ var _char = _v2.a;
+ var rest = _v2.b;
+ return $elm$core$Char$isAlpha(_char) && A2($elm$core$String$all, $elm$core$Char$isAlphaNum, rest);
+ }
+ }();
+ var fieldName = isSimple ? ('.' + f) : ('[\'' + (f + '\']'));
+ var $temp$error = err,
+ $temp$context = A2($elm$core$List$cons, fieldName, context);
+ error = $temp$error;
+ context = $temp$context;
+ continue errorToStringHelp;
+ case 1:
+ var i = error.a;
+ var err = error.b;
+ var indexName = '[' + ($elm$core$String$fromInt(i) + ']');
+ var $temp$error = err,
+ $temp$context = A2($elm$core$List$cons, indexName, context);
+ error = $temp$error;
+ context = $temp$context;
+ continue errorToStringHelp;
+ case 2:
+ var errors = error.a;
+ if (!errors.b) {
+ return 'Ran into a Json.Decode.oneOf with no possibilities' + function () {
+ if (!context.b) {
+ return '!';
+ } else {
+ return ' at json' + A2(
+ $elm$core$String$join,
+ '',
+ $elm$core$List$reverse(context));
+ }
+ }();
+ } else {
+ if (!errors.b.b) {
+ var err = errors.a;
+ var $temp$error = err,
+ $temp$context = context;
+ error = $temp$error;
+ context = $temp$context;
+ continue errorToStringHelp;
+ } else {
+ var starter = function () {
+ if (!context.b) {
+ return 'Json.Decode.oneOf';
+ } else {
+ return 'The Json.Decode.oneOf at json' + A2(
+ $elm$core$String$join,
+ '',
+ $elm$core$List$reverse(context));
+ }
+ }();
+ var introduction = starter + (' failed in the following ' + ($elm$core$String$fromInt(
+ $elm$core$List$length(errors)) + ' ways:'));
+ return A2(
+ $elm$core$String$join,
+ '\n\n',
+ A2(
+ $elm$core$List$cons,
+ introduction,
+ A2($elm$core$List$indexedMap, $elm$json$Json$Decode$errorOneOf, errors)));
+ }
+ }
+ default:
+ var msg = error.a;
+ var json = error.b;
+ var introduction = function () {
+ if (!context.b) {
+ return 'Problem with the given value:\n\n';
+ } else {
+ return 'Problem with the value at json' + (A2(
+ $elm$core$String$join,
+ '',
+ $elm$core$List$reverse(context)) + ':\n\n ');
+ }
+ }();
+ return introduction + ($elm$json$Json$Decode$indent(
+ A2($elm$json$Json$Encode$encode, 4, json)) + ('\n\n' + msg));
+ }
+ }
+ });
+var $elm$core$Array$branchFactor = 32;
+var $elm$core$Array$Array_elm_builtin = F4(
+ function (a, b, c, d) {
+ return {$: 0, a: a, b: b, c: c, d: d};
+ });
+var $elm$core$Elm$JsArray$empty = _JsArray_empty;
+var $elm$core$Basics$ceiling = _Basics_ceiling;
+var $elm$core$Basics$fdiv = _Basics_fdiv;
+var $elm$core$Basics$logBase = F2(
+ function (base, number) {
+ return _Basics_log(number) / _Basics_log(base);
+ });
+var $elm$core$Basics$toFloat = _Basics_toFloat;
+var $elm$core$Array$shiftStep = $elm$core$Basics$ceiling(
+ A2($elm$core$Basics$logBase, 2, $elm$core$Array$branchFactor));
+var $elm$core$Array$empty = A4($elm$core$Array$Array_elm_builtin, 0, $elm$core$Array$shiftStep, $elm$core$Elm$JsArray$empty, $elm$core$Elm$JsArray$empty);
+var $elm$core$Elm$JsArray$initialize = _JsArray_initialize;
+var $elm$core$Array$Leaf = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$core$Basics$apL = F2(
+ function (f, x) {
+ return f(x);
+ });
+var $elm$core$Basics$apR = F2(
+ function (x, f) {
+ return f(x);
+ });
+var $elm$core$Basics$eq = _Utils_equal;
+var $elm$core$Basics$floor = _Basics_floor;
+var $elm$core$Elm$JsArray$length = _JsArray_length;
+var $elm$core$Basics$gt = _Utils_gt;
+var $elm$core$Basics$max = F2(
+ function (x, y) {
+ return (_Utils_cmp(x, y) > 0) ? x : y;
+ });
+var $elm$core$Basics$mul = _Basics_mul;
+var $elm$core$Array$SubTree = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$core$Elm$JsArray$initializeFromList = _JsArray_initializeFromList;
+var $elm$core$Array$compressNodes = F2(
+ function (nodes, acc) {
+ compressNodes:
+ while (true) {
+ var _v0 = A2($elm$core$Elm$JsArray$initializeFromList, $elm$core$Array$branchFactor, nodes);
+ var node = _v0.a;
+ var remainingNodes = _v0.b;
+ var newAcc = A2(
+ $elm$core$List$cons,
+ $elm$core$Array$SubTree(node),
+ acc);
+ if (!remainingNodes.b) {
+ return $elm$core$List$reverse(newAcc);
+ } else {
+ var $temp$nodes = remainingNodes,
+ $temp$acc = newAcc;
+ nodes = $temp$nodes;
+ acc = $temp$acc;
+ continue compressNodes;
+ }
+ }
+ });
+var $elm$core$Tuple$first = function (_v0) {
+ var x = _v0.a;
+ return x;
+};
+var $elm$core$Array$treeFromBuilder = F2(
+ function (nodeList, nodeListSize) {
+ treeFromBuilder:
+ while (true) {
+ var newNodeSize = $elm$core$Basics$ceiling(nodeListSize / $elm$core$Array$branchFactor);
+ if (newNodeSize === 1) {
+ return A2($elm$core$Elm$JsArray$initializeFromList, $elm$core$Array$branchFactor, nodeList).a;
+ } else {
+ var $temp$nodeList = A2($elm$core$Array$compressNodes, nodeList, _List_Nil),
+ $temp$nodeListSize = newNodeSize;
+ nodeList = $temp$nodeList;
+ nodeListSize = $temp$nodeListSize;
+ continue treeFromBuilder;
+ }
+ }
+ });
+var $elm$core$Array$builderToArray = F2(
+ function (reverseNodeList, builder) {
+ if (!builder.a) {
+ return A4(
+ $elm$core$Array$Array_elm_builtin,
+ $elm$core$Elm$JsArray$length(builder.c),
+ $elm$core$Array$shiftStep,
+ $elm$core$Elm$JsArray$empty,
+ builder.c);
+ } else {
+ var treeLen = builder.a * $elm$core$Array$branchFactor;
+ var depth = $elm$core$Basics$floor(
+ A2($elm$core$Basics$logBase, $elm$core$Array$branchFactor, treeLen - 1));
+ var correctNodeList = reverseNodeList ? $elm$core$List$reverse(builder.d) : builder.d;
+ var tree = A2($elm$core$Array$treeFromBuilder, correctNodeList, builder.a);
+ return A4(
+ $elm$core$Array$Array_elm_builtin,
+ $elm$core$Elm$JsArray$length(builder.c) + treeLen,
+ A2($elm$core$Basics$max, 5, depth * $elm$core$Array$shiftStep),
+ tree,
+ builder.c);
+ }
+ });
+var $elm$core$Basics$idiv = _Basics_idiv;
+var $elm$core$Basics$lt = _Utils_lt;
+var $elm$core$Array$initializeHelp = F5(
+ function (fn, fromIndex, len, nodeList, tail) {
+ initializeHelp:
+ while (true) {
+ if (fromIndex < 0) {
+ return A2(
+ $elm$core$Array$builderToArray,
+ false,
+ {d: nodeList, a: (len / $elm$core$Array$branchFactor) | 0, c: tail});
+ } else {
+ var leaf = $elm$core$Array$Leaf(
+ A3($elm$core$Elm$JsArray$initialize, $elm$core$Array$branchFactor, fromIndex, fn));
+ var $temp$fn = fn,
+ $temp$fromIndex = fromIndex - $elm$core$Array$branchFactor,
+ $temp$len = len,
+ $temp$nodeList = A2($elm$core$List$cons, leaf, nodeList),
+ $temp$tail = tail;
+ fn = $temp$fn;
+ fromIndex = $temp$fromIndex;
+ len = $temp$len;
+ nodeList = $temp$nodeList;
+ tail = $temp$tail;
+ continue initializeHelp;
+ }
+ }
+ });
+var $elm$core$Basics$remainderBy = _Basics_remainderBy;
+var $elm$core$Array$initialize = F2(
+ function (len, fn) {
+ if (len <= 0) {
+ return $elm$core$Array$empty;
+ } else {
+ var tailLen = len % $elm$core$Array$branchFactor;
+ var tail = A3($elm$core$Elm$JsArray$initialize, tailLen, len - tailLen, fn);
+ var initialFromIndex = (len - tailLen) - $elm$core$Array$branchFactor;
+ return A5($elm$core$Array$initializeHelp, fn, initialFromIndex, len, _List_Nil, tail);
+ }
+ });
+var $elm$core$Basics$True = 0;
+var $elm$core$Result$isOk = function (result) {
+ if (!result.$) {
+ return true;
+ } else {
+ return false;
+ }
+};
+var $elm$json$Json$Decode$map = _Json_map1;
+var $elm$json$Json$Decode$map2 = _Json_map2;
+var $elm$json$Json$Decode$succeed = _Json_succeed;
+var $elm$virtual_dom$VirtualDom$toHandlerInt = function (handler) {
+ switch (handler.$) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return 2;
+ default:
+ return 3;
+ }
+};
+var $elm$browser$Browser$External = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$browser$Browser$Internal = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$core$Basics$identity = function (x) {
+ return x;
+};
+var $elm$browser$Browser$Dom$NotFound = $elm$core$Basics$identity;
+var $elm$url$Url$Http = 0;
+var $elm$url$Url$Https = 1;
+var $elm$url$Url$Url = F6(
+ function (protocol, host, port_, path, query, fragment) {
+ return {T: fragment, W: host, _: path, ab: port_, ae: protocol, af: query};
+ });
+var $elm$core$String$contains = _String_contains;
+var $elm$core$String$length = _String_length;
+var $elm$core$String$slice = _String_slice;
+var $elm$core$String$dropLeft = F2(
+ function (n, string) {
+ return (n < 1) ? string : A3(
+ $elm$core$String$slice,
+ n,
+ $elm$core$String$length(string),
+ string);
+ });
+var $elm$core$String$indexes = _String_indexes;
+var $elm$core$String$isEmpty = function (string) {
+ return string === '';
+};
+var $elm$core$String$left = F2(
+ function (n, string) {
+ return (n < 1) ? '' : A3($elm$core$String$slice, 0, n, string);
+ });
+var $elm$core$String$toInt = _String_toInt;
+var $elm$url$Url$chompBeforePath = F5(
+ function (protocol, path, params, frag, str) {
+ if ($elm$core$String$isEmpty(str) || A2($elm$core$String$contains, '@', str)) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var _v0 = A2($elm$core$String$indexes, ':', str);
+ if (!_v0.b) {
+ return $elm$core$Maybe$Just(
+ A6($elm$url$Url$Url, protocol, str, $elm$core$Maybe$Nothing, path, params, frag));
+ } else {
+ if (!_v0.b.b) {
+ var i = _v0.a;
+ var _v1 = $elm$core$String$toInt(
+ A2($elm$core$String$dropLeft, i + 1, str));
+ if (_v1.$ === 1) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var port_ = _v1;
+ return $elm$core$Maybe$Just(
+ A6(
+ $elm$url$Url$Url,
+ protocol,
+ A2($elm$core$String$left, i, str),
+ port_,
+ path,
+ params,
+ frag));
+ }
+ } else {
+ return $elm$core$Maybe$Nothing;
+ }
+ }
+ }
+ });
+var $elm$url$Url$chompBeforeQuery = F4(
+ function (protocol, params, frag, str) {
+ if ($elm$core$String$isEmpty(str)) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var _v0 = A2($elm$core$String$indexes, '/', str);
+ if (!_v0.b) {
+ return A5($elm$url$Url$chompBeforePath, protocol, '/', params, frag, str);
+ } else {
+ var i = _v0.a;
+ return A5(
+ $elm$url$Url$chompBeforePath,
+ protocol,
+ A2($elm$core$String$dropLeft, i, str),
+ params,
+ frag,
+ A2($elm$core$String$left, i, str));
+ }
+ }
+ });
+var $elm$url$Url$chompBeforeFragment = F3(
+ function (protocol, frag, str) {
+ if ($elm$core$String$isEmpty(str)) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var _v0 = A2($elm$core$String$indexes, '?', str);
+ if (!_v0.b) {
+ return A4($elm$url$Url$chompBeforeQuery, protocol, $elm$core$Maybe$Nothing, frag, str);
+ } else {
+ var i = _v0.a;
+ return A4(
+ $elm$url$Url$chompBeforeQuery,
+ protocol,
+ $elm$core$Maybe$Just(
+ A2($elm$core$String$dropLeft, i + 1, str)),
+ frag,
+ A2($elm$core$String$left, i, str));
+ }
+ }
+ });
+var $elm$url$Url$chompAfterProtocol = F2(
+ function (protocol, str) {
+ if ($elm$core$String$isEmpty(str)) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var _v0 = A2($elm$core$String$indexes, '#', str);
+ if (!_v0.b) {
+ return A3($elm$url$Url$chompBeforeFragment, protocol, $elm$core$Maybe$Nothing, str);
+ } else {
+ var i = _v0.a;
+ return A3(
+ $elm$url$Url$chompBeforeFragment,
+ protocol,
+ $elm$core$Maybe$Just(
+ A2($elm$core$String$dropLeft, i + 1, str)),
+ A2($elm$core$String$left, i, str));
+ }
+ }
+ });
+var $elm$core$String$startsWith = _String_startsWith;
+var $elm$url$Url$fromString = function (str) {
+ return A2($elm$core$String$startsWith, 'http://', str) ? A2(
+ $elm$url$Url$chompAfterProtocol,
+ 0,
+ A2($elm$core$String$dropLeft, 7, str)) : (A2($elm$core$String$startsWith, 'https://', str) ? A2(
+ $elm$url$Url$chompAfterProtocol,
+ 1,
+ A2($elm$core$String$dropLeft, 8, str)) : $elm$core$Maybe$Nothing);
+};
+var $elm$core$Basics$never = function (_v0) {
+ never:
+ while (true) {
+ var nvr = _v0;
+ var $temp$_v0 = nvr;
+ _v0 = $temp$_v0;
+ continue never;
+ }
+};
+var $elm$core$Task$Perform = $elm$core$Basics$identity;
+var $elm$core$Task$succeed = _Scheduler_succeed;
+var $elm$core$Task$init = $elm$core$Task$succeed(0);
+var $elm$core$List$foldrHelper = F4(
+ function (fn, acc, ctr, ls) {
+ if (!ls.b) {
+ return acc;
+ } else {
+ var a = ls.a;
+ var r1 = ls.b;
+ if (!r1.b) {
+ return A2(fn, a, acc);
+ } else {
+ var b = r1.a;
+ var r2 = r1.b;
+ if (!r2.b) {
+ return A2(
+ fn,
+ a,
+ A2(fn, b, acc));
+ } else {
+ var c = r2.a;
+ var r3 = r2.b;
+ if (!r3.b) {
+ return A2(
+ fn,
+ a,
+ A2(
+ fn,
+ b,
+ A2(fn, c, acc)));
+ } else {
+ var d = r3.a;
+ var r4 = r3.b;
+ var res = (ctr > 500) ? A3(
+ $elm$core$List$foldl,
+ fn,
+ acc,
+ $elm$core$List$reverse(r4)) : A4($elm$core$List$foldrHelper, fn, acc, ctr + 1, r4);
+ return A2(
+ fn,
+ a,
+ A2(
+ fn,
+ b,
+ A2(
+ fn,
+ c,
+ A2(fn, d, res))));
+ }
+ }
+ }
+ }
+ });
+var $elm$core$List$foldr = F3(
+ function (fn, acc, ls) {
+ return A4($elm$core$List$foldrHelper, fn, acc, 0, ls);
+ });
+var $elm$core$List$map = F2(
+ function (f, xs) {
+ return A3(
+ $elm$core$List$foldr,
+ F2(
+ function (x, acc) {
+ return A2(
+ $elm$core$List$cons,
+ f(x),
+ acc);
+ }),
+ _List_Nil,
+ xs);
+ });
+var $elm$core$Task$andThen = _Scheduler_andThen;
+var $elm$core$Task$map = F2(
+ function (func, taskA) {
+ return A2(
+ $elm$core$Task$andThen,
+ function (a) {
+ return $elm$core$Task$succeed(
+ func(a));
+ },
+ taskA);
+ });
+var $elm$core$Task$map2 = F3(
+ function (func, taskA, taskB) {
+ return A2(
+ $elm$core$Task$andThen,
+ function (a) {
+ return A2(
+ $elm$core$Task$andThen,
+ function (b) {
+ return $elm$core$Task$succeed(
+ A2(func, a, b));
+ },
+ taskB);
+ },
+ taskA);
+ });
+var $elm$core$Task$sequence = function (tasks) {
+ return A3(
+ $elm$core$List$foldr,
+ $elm$core$Task$map2($elm$core$List$cons),
+ $elm$core$Task$succeed(_List_Nil),
+ tasks);
+};
+var $elm$core$Platform$sendToApp = _Platform_sendToApp;
+var $elm$core$Task$spawnCmd = F2(
+ function (router, _v0) {
+ var task = _v0;
+ return _Scheduler_spawn(
+ A2(
+ $elm$core$Task$andThen,
+ $elm$core$Platform$sendToApp(router),
+ task));
+ });
+var $elm$core$Task$onEffects = F3(
+ function (router, commands, state) {
+ return A2(
+ $elm$core$Task$map,
+ function (_v0) {
+ return 0;
+ },
+ $elm$core$Task$sequence(
+ A2(
+ $elm$core$List$map,
+ $elm$core$Task$spawnCmd(router),
+ commands)));
+ });
+var $elm$core$Task$onSelfMsg = F3(
+ function (_v0, _v1, _v2) {
+ return $elm$core$Task$succeed(0);
+ });
+var $elm$core$Task$cmdMap = F2(
+ function (tagger, _v0) {
+ var task = _v0;
+ return A2($elm$core$Task$map, tagger, task);
+ });
+_Platform_effectManagers['Task'] = _Platform_createManager($elm$core$Task$init, $elm$core$Task$onEffects, $elm$core$Task$onSelfMsg, $elm$core$Task$cmdMap);
+var $elm$core$Task$command = _Platform_leaf('Task');
+var $elm$core$Task$perform = F2(
+ function (toMessage, task) {
+ return $elm$core$Task$command(
+ A2($elm$core$Task$map, toMessage, task));
+ });
+var $elm$browser$Browser$application = _Browser_application;
+var $author$project$Main$Model = F5(
+ function (key, url, capture, message, online) {
+ return {y: capture, X: key, E: message, H: online, M: url};
+ });
+var $elm$core$Platform$Cmd$batch = _Platform_batch;
+var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil);
+var $author$project$Main$init = F3(
+ function (flags, url, key) {
+ return _Utils_Tuple2(
+ A5($author$project$Main$Model, key, url, '', '', true),
+ $elm$core$Platform$Cmd$none);
+ });
+var $author$project$Main$Online = function (a) {
+ return {$: 5, a: a};
+};
+var $elm$core$Platform$Sub$batch = _Platform_batch;
+var $elm$json$Json$Decode$bool = _Json_decodeBool;
+var $author$project$Main$online = _Platform_incomingPort('online', $elm$json$Json$Decode$bool);
+var $author$project$Main$subscriptions = function (_v0) {
+ return $elm$core$Platform$Sub$batch(
+ _List_fromArray(
+ [
+ $author$project$Main$online($author$project$Main$Online)
+ ]));
+};
+var $elm$browser$Browser$Navigation$load = _Browser_load;
+var $elm$browser$Browser$Navigation$pushUrl = _Browser_pushUrl;
+var $author$project$Main$SaveCaptureResult = function (a) {
+ return {$: 4, a: a};
+};
+var $elm$json$Json$Decode$field = _Json_decodeField;
+var $elm$json$Json$Decode$string = _Json_decodeString;
+var $author$project$Main$captureDecoder = A2($elm$json$Json$Decode$field, 'text', $elm$json$Json$Decode$string);
+var $elm$json$Json$Encode$object = function (pairs) {
+ return _Json_wrap(
+ A3(
+ $elm$core$List$foldl,
+ F2(
+ function (_v0, obj) {
+ var k = _v0.a;
+ var v = _v0.b;
+ return A3(_Json_addField, k, v, obj);
+ }),
+ _Json_emptyObject(0),
+ pairs));
+};
+var $elm$json$Json$Encode$string = _Json_wrap;
+var $author$project$Main$captureEncode = function (capture) {
+ return $elm$json$Json$Encode$object(
+ _List_fromArray(
+ [
+ _Utils_Tuple2(
+ 'text',
+ $elm$json$Json$Encode$string(capture))
+ ]));
+};
+var $elm$json$Json$Decode$decodeString = _Json_runOnString;
+var $elm$http$Http$BadStatus_ = F2(
+ function (a, b) {
+ return {$: 3, a: a, b: b};
+ });
+var $elm$http$Http$BadUrl_ = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$http$Http$GoodStatus_ = F2(
+ function (a, b) {
+ return {$: 4, a: a, b: b};
+ });
+var $elm$http$Http$NetworkError_ = {$: 2};
+var $elm$http$Http$Receiving = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$http$Http$Sending = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$http$Http$Timeout_ = {$: 1};
+var $elm$core$Dict$RBEmpty_elm_builtin = {$: -2};
+var $elm$core$Dict$empty = $elm$core$Dict$RBEmpty_elm_builtin;
+var $elm$core$Maybe$isJust = function (maybe) {
+ if (!maybe.$) {
+ return true;
+ } else {
+ return false;
+ }
+};
+var $elm$core$Platform$sendToSelf = _Platform_sendToSelf;
+var $elm$core$Basics$compare = _Utils_compare;
+var $elm$core$Dict$get = F2(
+ function (targetKey, dict) {
+ get:
+ while (true) {
+ if (dict.$ === -2) {
+ return $elm$core$Maybe$Nothing;
+ } else {
+ var key = dict.b;
+ var value = dict.c;
+ var left = dict.d;
+ var right = dict.e;
+ var _v1 = A2($elm$core$Basics$compare, targetKey, key);
+ switch (_v1) {
+ case 0:
+ var $temp$targetKey = targetKey,
+ $temp$dict = left;
+ targetKey = $temp$targetKey;
+ dict = $temp$dict;
+ continue get;
+ case 1:
+ return $elm$core$Maybe$Just(value);
+ default:
+ var $temp$targetKey = targetKey,
+ $temp$dict = right;
+ targetKey = $temp$targetKey;
+ dict = $temp$dict;
+ continue get;
+ }
+ }
+ }
+ });
+var $elm$core$Dict$Black = 1;
+var $elm$core$Dict$RBNode_elm_builtin = F5(
+ function (a, b, c, d, e) {
+ return {$: -1, a: a, b: b, c: c, d: d, e: e};
+ });
+var $elm$core$Dict$Red = 0;
+var $elm$core$Dict$balance = F5(
+ function (color, key, value, left, right) {
+ if ((right.$ === -1) && (!right.a)) {
+ var _v1 = right.a;
+ var rK = right.b;
+ var rV = right.c;
+ var rLeft = right.d;
+ var rRight = right.e;
+ if ((left.$ === -1) && (!left.a)) {
+ var _v3 = left.a;
+ var lK = left.b;
+ var lV = left.c;
+ var lLeft = left.d;
+ var lRight = left.e;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 0,
+ key,
+ value,
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, lK, lV, lLeft, lRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, rK, rV, rLeft, rRight));
+ } else {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ rK,
+ rV,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, key, value, left, rLeft),
+ rRight);
+ }
+ } else {
+ if ((((left.$ === -1) && (!left.a)) && (left.d.$ === -1)) && (!left.d.a)) {
+ var _v5 = left.a;
+ var lK = left.b;
+ var lV = left.c;
+ var _v6 = left.d;
+ var _v7 = _v6.a;
+ var llK = _v6.b;
+ var llV = _v6.c;
+ var llLeft = _v6.d;
+ var llRight = _v6.e;
+ var lRight = left.e;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 0,
+ lK,
+ lV,
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, llK, llV, llLeft, llRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, key, value, lRight, right));
+ } else {
+ return A5($elm$core$Dict$RBNode_elm_builtin, color, key, value, left, right);
+ }
+ }
+ });
+var $elm$core$Dict$insertHelp = F3(
+ function (key, value, dict) {
+ if (dict.$ === -2) {
+ return A5($elm$core$Dict$RBNode_elm_builtin, 0, key, value, $elm$core$Dict$RBEmpty_elm_builtin, $elm$core$Dict$RBEmpty_elm_builtin);
+ } else {
+ var nColor = dict.a;
+ var nKey = dict.b;
+ var nValue = dict.c;
+ var nLeft = dict.d;
+ var nRight = dict.e;
+ var _v1 = A2($elm$core$Basics$compare, key, nKey);
+ switch (_v1) {
+ case 0:
+ return A5(
+ $elm$core$Dict$balance,
+ nColor,
+ nKey,
+ nValue,
+ A3($elm$core$Dict$insertHelp, key, value, nLeft),
+ nRight);
+ case 1:
+ return A5($elm$core$Dict$RBNode_elm_builtin, nColor, nKey, value, nLeft, nRight);
+ default:
+ return A5(
+ $elm$core$Dict$balance,
+ nColor,
+ nKey,
+ nValue,
+ nLeft,
+ A3($elm$core$Dict$insertHelp, key, value, nRight));
+ }
+ }
+ });
+var $elm$core$Dict$insert = F3(
+ function (key, value, dict) {
+ var _v0 = A3($elm$core$Dict$insertHelp, key, value, dict);
+ if ((_v0.$ === -1) && (!_v0.a)) {
+ var _v1 = _v0.a;
+ var k = _v0.b;
+ var v = _v0.c;
+ var l = _v0.d;
+ var r = _v0.e;
+ return A5($elm$core$Dict$RBNode_elm_builtin, 1, k, v, l, r);
+ } else {
+ var x = _v0;
+ return x;
+ }
+ });
+var $elm$core$Dict$getMin = function (dict) {
+ getMin:
+ while (true) {
+ if ((dict.$ === -1) && (dict.d.$ === -1)) {
+ var left = dict.d;
+ var $temp$dict = left;
+ dict = $temp$dict;
+ continue getMin;
+ } else {
+ return dict;
+ }
+ }
+};
+var $elm$core$Dict$moveRedLeft = function (dict) {
+ if (((dict.$ === -1) && (dict.d.$ === -1)) && (dict.e.$ === -1)) {
+ if ((dict.e.d.$ === -1) && (!dict.e.d.a)) {
+ var clr = dict.a;
+ var k = dict.b;
+ var v = dict.c;
+ var _v1 = dict.d;
+ var lClr = _v1.a;
+ var lK = _v1.b;
+ var lV = _v1.c;
+ var lLeft = _v1.d;
+ var lRight = _v1.e;
+ var _v2 = dict.e;
+ var rClr = _v2.a;
+ var rK = _v2.b;
+ var rV = _v2.c;
+ var rLeft = _v2.d;
+ var _v3 = rLeft.a;
+ var rlK = rLeft.b;
+ var rlV = rLeft.c;
+ var rlL = rLeft.d;
+ var rlR = rLeft.e;
+ var rRight = _v2.e;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 0,
+ rlK,
+ rlV,
+ A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, lK, lV, lLeft, lRight),
+ rlL),
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, rK, rV, rlR, rRight));
+ } else {
+ var clr = dict.a;
+ var k = dict.b;
+ var v = dict.c;
+ var _v4 = dict.d;
+ var lClr = _v4.a;
+ var lK = _v4.b;
+ var lV = _v4.c;
+ var lLeft = _v4.d;
+ var lRight = _v4.e;
+ var _v5 = dict.e;
+ var rClr = _v5.a;
+ var rK = _v5.b;
+ var rV = _v5.c;
+ var rLeft = _v5.d;
+ var rRight = _v5.e;
+ if (clr === 1) {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, lK, lV, lLeft, lRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, rK, rV, rLeft, rRight));
+ } else {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, lK, lV, lLeft, lRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, rK, rV, rLeft, rRight));
+ }
+ }
+ } else {
+ return dict;
+ }
+};
+var $elm$core$Dict$moveRedRight = function (dict) {
+ if (((dict.$ === -1) && (dict.d.$ === -1)) && (dict.e.$ === -1)) {
+ if ((dict.d.d.$ === -1) && (!dict.d.d.a)) {
+ var clr = dict.a;
+ var k = dict.b;
+ var v = dict.c;
+ var _v1 = dict.d;
+ var lClr = _v1.a;
+ var lK = _v1.b;
+ var lV = _v1.c;
+ var _v2 = _v1.d;
+ var _v3 = _v2.a;
+ var llK = _v2.b;
+ var llV = _v2.c;
+ var llLeft = _v2.d;
+ var llRight = _v2.e;
+ var lRight = _v1.e;
+ var _v4 = dict.e;
+ var rClr = _v4.a;
+ var rK = _v4.b;
+ var rV = _v4.c;
+ var rLeft = _v4.d;
+ var rRight = _v4.e;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 0,
+ lK,
+ lV,
+ A5($elm$core$Dict$RBNode_elm_builtin, 1, llK, llV, llLeft, llRight),
+ A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ lRight,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, rK, rV, rLeft, rRight)));
+ } else {
+ var clr = dict.a;
+ var k = dict.b;
+ var v = dict.c;
+ var _v5 = dict.d;
+ var lClr = _v5.a;
+ var lK = _v5.b;
+ var lV = _v5.c;
+ var lLeft = _v5.d;
+ var lRight = _v5.e;
+ var _v6 = dict.e;
+ var rClr = _v6.a;
+ var rK = _v6.b;
+ var rV = _v6.c;
+ var rLeft = _v6.d;
+ var rRight = _v6.e;
+ if (clr === 1) {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, lK, lV, lLeft, lRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, rK, rV, rLeft, rRight));
+ } else {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ 1,
+ k,
+ v,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, lK, lV, lLeft, lRight),
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, rK, rV, rLeft, rRight));
+ }
+ }
+ } else {
+ return dict;
+ }
+};
+var $elm$core$Dict$removeHelpPrepEQGT = F7(
+ function (targetKey, dict, color, key, value, left, right) {
+ if ((left.$ === -1) && (!left.a)) {
+ var _v1 = left.a;
+ var lK = left.b;
+ var lV = left.c;
+ var lLeft = left.d;
+ var lRight = left.e;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ lK,
+ lV,
+ lLeft,
+ A5($elm$core$Dict$RBNode_elm_builtin, 0, key, value, lRight, right));
+ } else {
+ _v2$2:
+ while (true) {
+ if ((right.$ === -1) && (right.a === 1)) {
+ if (right.d.$ === -1) {
+ if (right.d.a === 1) {
+ var _v3 = right.a;
+ var _v4 = right.d;
+ var _v5 = _v4.a;
+ return $elm$core$Dict$moveRedRight(dict);
+ } else {
+ break _v2$2;
+ }
+ } else {
+ var _v6 = right.a;
+ var _v7 = right.d;
+ return $elm$core$Dict$moveRedRight(dict);
+ }
+ } else {
+ break _v2$2;
+ }
+ }
+ return dict;
+ }
+ });
+var $elm$core$Dict$removeMin = function (dict) {
+ if ((dict.$ === -1) && (dict.d.$ === -1)) {
+ var color = dict.a;
+ var key = dict.b;
+ var value = dict.c;
+ var left = dict.d;
+ var lColor = left.a;
+ var lLeft = left.d;
+ var right = dict.e;
+ if (lColor === 1) {
+ if ((lLeft.$ === -1) && (!lLeft.a)) {
+ var _v3 = lLeft.a;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ key,
+ value,
+ $elm$core$Dict$removeMin(left),
+ right);
+ } else {
+ var _v4 = $elm$core$Dict$moveRedLeft(dict);
+ if (_v4.$ === -1) {
+ var nColor = _v4.a;
+ var nKey = _v4.b;
+ var nValue = _v4.c;
+ var nLeft = _v4.d;
+ var nRight = _v4.e;
+ return A5(
+ $elm$core$Dict$balance,
+ nColor,
+ nKey,
+ nValue,
+ $elm$core$Dict$removeMin(nLeft),
+ nRight);
+ } else {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ }
+ }
+ } else {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ key,
+ value,
+ $elm$core$Dict$removeMin(left),
+ right);
+ }
+ } else {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ }
+};
+var $elm$core$Dict$removeHelp = F2(
+ function (targetKey, dict) {
+ if (dict.$ === -2) {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ } else {
+ var color = dict.a;
+ var key = dict.b;
+ var value = dict.c;
+ var left = dict.d;
+ var right = dict.e;
+ if (_Utils_cmp(targetKey, key) < 0) {
+ if ((left.$ === -1) && (left.a === 1)) {
+ var _v4 = left.a;
+ var lLeft = left.d;
+ if ((lLeft.$ === -1) && (!lLeft.a)) {
+ var _v6 = lLeft.a;
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ key,
+ value,
+ A2($elm$core$Dict$removeHelp, targetKey, left),
+ right);
+ } else {
+ var _v7 = $elm$core$Dict$moveRedLeft(dict);
+ if (_v7.$ === -1) {
+ var nColor = _v7.a;
+ var nKey = _v7.b;
+ var nValue = _v7.c;
+ var nLeft = _v7.d;
+ var nRight = _v7.e;
+ return A5(
+ $elm$core$Dict$balance,
+ nColor,
+ nKey,
+ nValue,
+ A2($elm$core$Dict$removeHelp, targetKey, nLeft),
+ nRight);
+ } else {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ }
+ }
+ } else {
+ return A5(
+ $elm$core$Dict$RBNode_elm_builtin,
+ color,
+ key,
+ value,
+ A2($elm$core$Dict$removeHelp, targetKey, left),
+ right);
+ }
+ } else {
+ return A2(
+ $elm$core$Dict$removeHelpEQGT,
+ targetKey,
+ A7($elm$core$Dict$removeHelpPrepEQGT, targetKey, dict, color, key, value, left, right));
+ }
+ }
+ });
+var $elm$core$Dict$removeHelpEQGT = F2(
+ function (targetKey, dict) {
+ if (dict.$ === -1) {
+ var color = dict.a;
+ var key = dict.b;
+ var value = dict.c;
+ var left = dict.d;
+ var right = dict.e;
+ if (_Utils_eq(targetKey, key)) {
+ var _v1 = $elm$core$Dict$getMin(right);
+ if (_v1.$ === -1) {
+ var minKey = _v1.b;
+ var minValue = _v1.c;
+ return A5(
+ $elm$core$Dict$balance,
+ color,
+ minKey,
+ minValue,
+ left,
+ $elm$core$Dict$removeMin(right));
+ } else {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ }
+ } else {
+ return A5(
+ $elm$core$Dict$balance,
+ color,
+ key,
+ value,
+ left,
+ A2($elm$core$Dict$removeHelp, targetKey, right));
+ }
+ } else {
+ return $elm$core$Dict$RBEmpty_elm_builtin;
+ }
+ });
+var $elm$core$Dict$remove = F2(
+ function (key, dict) {
+ var _v0 = A2($elm$core$Dict$removeHelp, key, dict);
+ if ((_v0.$ === -1) && (!_v0.a)) {
+ var _v1 = _v0.a;
+ var k = _v0.b;
+ var v = _v0.c;
+ var l = _v0.d;
+ var r = _v0.e;
+ return A5($elm$core$Dict$RBNode_elm_builtin, 1, k, v, l, r);
+ } else {
+ var x = _v0;
+ return x;
+ }
+ });
+var $elm$core$Dict$update = F3(
+ function (targetKey, alter, dictionary) {
+ var _v0 = alter(
+ A2($elm$core$Dict$get, targetKey, dictionary));
+ if (!_v0.$) {
+ var value = _v0.a;
+ return A3($elm$core$Dict$insert, targetKey, value, dictionary);
+ } else {
+ return A2($elm$core$Dict$remove, targetKey, dictionary);
+ }
+ });
+var $elm$core$Basics$composeR = F3(
+ function (f, g, x) {
+ return g(
+ f(x));
+ });
+var $elm$http$Http$expectStringResponse = F2(
+ function (toMsg, toResult) {
+ return A3(
+ _Http_expect,
+ '',
+ $elm$core$Basics$identity,
+ A2($elm$core$Basics$composeR, toResult, toMsg));
+ });
+var $elm$core$Result$mapError = F2(
+ function (f, result) {
+ if (!result.$) {
+ var v = result.a;
+ return $elm$core$Result$Ok(v);
+ } else {
+ var e = result.a;
+ return $elm$core$Result$Err(
+ f(e));
+ }
+ });
+var $elm$http$Http$BadBody = function (a) {
+ return {$: 4, a: a};
+};
+var $elm$http$Http$BadStatus = function (a) {
+ return {$: 3, a: a};
+};
+var $elm$http$Http$BadUrl = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$http$Http$NetworkError = {$: 2};
+var $elm$http$Http$Timeout = {$: 1};
+var $elm$http$Http$resolve = F2(
+ function (toResult, response) {
+ switch (response.$) {
+ case 0:
+ var url = response.a;
+ return $elm$core$Result$Err(
+ $elm$http$Http$BadUrl(url));
+ case 1:
+ return $elm$core$Result$Err($elm$http$Http$Timeout);
+ case 2:
+ return $elm$core$Result$Err($elm$http$Http$NetworkError);
+ case 3:
+ var metadata = response.a;
+ return $elm$core$Result$Err(
+ $elm$http$Http$BadStatus(metadata.aM));
+ default:
+ var body = response.b;
+ return A2(
+ $elm$core$Result$mapError,
+ $elm$http$Http$BadBody,
+ toResult(body));
+ }
+ });
+var $elm$http$Http$expectJson = F2(
+ function (toMsg, decoder) {
+ return A2(
+ $elm$http$Http$expectStringResponse,
+ toMsg,
+ $elm$http$Http$resolve(
+ function (string) {
+ return A2(
+ $elm$core$Result$mapError,
+ $elm$json$Json$Decode$errorToString,
+ A2($elm$json$Json$Decode$decodeString, decoder, string));
+ }));
+ });
+var $elm$http$Http$jsonBody = function (value) {
+ return A2(
+ _Http_pair,
+ 'application/json',
+ A2($elm$json$Json$Encode$encode, 0, value));
+};
+var $elm$http$Http$Request = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$http$Http$State = F2(
+ function (reqs, subs) {
+ return {ah: reqs, am: subs};
+ });
+var $elm$http$Http$init = $elm$core$Task$succeed(
+ A2($elm$http$Http$State, $elm$core$Dict$empty, _List_Nil));
+var $elm$core$Process$kill = _Scheduler_kill;
+var $elm$core$Process$spawn = _Scheduler_spawn;
+var $elm$http$Http$updateReqs = F3(
+ function (router, cmds, reqs) {
+ updateReqs:
+ while (true) {
+ if (!cmds.b) {
+ return $elm$core$Task$succeed(reqs);
+ } else {
+ var cmd = cmds.a;
+ var otherCmds = cmds.b;
+ if (!cmd.$) {
+ var tracker = cmd.a;
+ var _v2 = A2($elm$core$Dict$get, tracker, reqs);
+ if (_v2.$ === 1) {
+ var $temp$router = router,
+ $temp$cmds = otherCmds,
+ $temp$reqs = reqs;
+ router = $temp$router;
+ cmds = $temp$cmds;
+ reqs = $temp$reqs;
+ continue updateReqs;
+ } else {
+ var pid = _v2.a;
+ return A2(
+ $elm$core$Task$andThen,
+ function (_v3) {
+ return A3(
+ $elm$http$Http$updateReqs,
+ router,
+ otherCmds,
+ A2($elm$core$Dict$remove, tracker, reqs));
+ },
+ $elm$core$Process$kill(pid));
+ }
+ } else {
+ var req = cmd.a;
+ return A2(
+ $elm$core$Task$andThen,
+ function (pid) {
+ var _v4 = req.ao;
+ if (_v4.$ === 1) {
+ return A3($elm$http$Http$updateReqs, router, otherCmds, reqs);
+ } else {
+ var tracker = _v4.a;
+ return A3(
+ $elm$http$Http$updateReqs,
+ router,
+ otherCmds,
+ A3($elm$core$Dict$insert, tracker, pid, reqs));
+ }
+ },
+ $elm$core$Process$spawn(
+ A3(
+ _Http_toTask,
+ router,
+ $elm$core$Platform$sendToApp(router),
+ req)));
+ }
+ }
+ }
+ });
+var $elm$http$Http$onEffects = F4(
+ function (router, cmds, subs, state) {
+ return A2(
+ $elm$core$Task$andThen,
+ function (reqs) {
+ return $elm$core$Task$succeed(
+ A2($elm$http$Http$State, reqs, subs));
+ },
+ A3($elm$http$Http$updateReqs, router, cmds, state.ah));
+ });
+var $elm$core$List$maybeCons = F3(
+ function (f, mx, xs) {
+ var _v0 = f(mx);
+ if (!_v0.$) {
+ var x = _v0.a;
+ return A2($elm$core$List$cons, x, xs);
+ } else {
+ return xs;
+ }
+ });
+var $elm$core$List$filterMap = F2(
+ function (f, xs) {
+ return A3(
+ $elm$core$List$foldr,
+ $elm$core$List$maybeCons(f),
+ _List_Nil,
+ xs);
+ });
+var $elm$http$Http$maybeSend = F4(
+ function (router, desiredTracker, progress, _v0) {
+ var actualTracker = _v0.a;
+ var toMsg = _v0.b;
+ return _Utils_eq(desiredTracker, actualTracker) ? $elm$core$Maybe$Just(
+ A2(
+ $elm$core$Platform$sendToApp,
+ router,
+ toMsg(progress))) : $elm$core$Maybe$Nothing;
+ });
+var $elm$http$Http$onSelfMsg = F3(
+ function (router, _v0, state) {
+ var tracker = _v0.a;
+ var progress = _v0.b;
+ return A2(
+ $elm$core$Task$andThen,
+ function (_v1) {
+ return $elm$core$Task$succeed(state);
+ },
+ $elm$core$Task$sequence(
+ A2(
+ $elm$core$List$filterMap,
+ A3($elm$http$Http$maybeSend, router, tracker, progress),
+ state.am)));
+ });
+var $elm$http$Http$Cancel = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$http$Http$cmdMap = F2(
+ function (func, cmd) {
+ if (!cmd.$) {
+ var tracker = cmd.a;
+ return $elm$http$Http$Cancel(tracker);
+ } else {
+ var r = cmd.a;
+ return $elm$http$Http$Request(
+ {
+ au: r.au,
+ O: r.O,
+ az: A2(_Http_mapExpect, func, r.az),
+ U: r.U,
+ aE: r.aE,
+ aP: r.aP,
+ ao: r.ao,
+ M: r.M
+ });
+ }
+ });
+var $elm$http$Http$MySub = F2(
+ function (a, b) {
+ return {$: 0, a: a, b: b};
+ });
+var $elm$http$Http$subMap = F2(
+ function (func, _v0) {
+ var tracker = _v0.a;
+ var toMsg = _v0.b;
+ return A2(
+ $elm$http$Http$MySub,
+ tracker,
+ A2($elm$core$Basics$composeR, toMsg, func));
+ });
+_Platform_effectManagers['Http'] = _Platform_createManager($elm$http$Http$init, $elm$http$Http$onEffects, $elm$http$Http$onSelfMsg, $elm$http$Http$cmdMap, $elm$http$Http$subMap);
+var $elm$http$Http$command = _Platform_leaf('Http');
+var $elm$http$Http$subscription = _Platform_leaf('Http');
+var $elm$http$Http$request = function (r) {
+ return $elm$http$Http$command(
+ $elm$http$Http$Request(
+ {au: false, O: r.O, az: r.az, U: r.U, aE: r.aE, aP: r.aP, ao: r.ao, M: r.M}));
+};
+var $elm$http$Http$post = function (r) {
+ return $elm$http$Http$request(
+ {O: r.O, az: r.az, U: _List_Nil, aE: 'POST', aP: $elm$core$Maybe$Nothing, ao: $elm$core$Maybe$Nothing, M: r.M});
+};
+var $author$project$Main$saveCapture = function (capture) {
+ return $elm$http$Http$post(
+ {
+ O: $elm$http$Http$jsonBody(
+ $author$project$Main$captureEncode(capture)),
+ az: A2($elm$http$Http$expectJson, $author$project$Main$SaveCaptureResult, $author$project$Main$captureDecoder),
+ M: 'https://dwylapp.herokuapp.com/api/captures/create'
+ });
+};
+var $elm$url$Url$addPort = F2(
+ function (maybePort, starter) {
+ if (maybePort.$ === 1) {
+ return starter;
+ } else {
+ var port_ = maybePort.a;
+ return starter + (':' + $elm$core$String$fromInt(port_));
+ }
+ });
+var $elm$url$Url$addPrefixed = F3(
+ function (prefix, maybeSegment, starter) {
+ if (maybeSegment.$ === 1) {
+ return starter;
+ } else {
+ var segment = maybeSegment.a;
+ return _Utils_ap(
+ starter,
+ _Utils_ap(prefix, segment));
+ }
+ });
+var $elm$url$Url$toString = function (url) {
+ var http = function () {
+ var _v0 = url.ae;
+ if (!_v0) {
+ return 'http://';
+ } else {
+ return 'https://';
+ }
+ }();
+ return A3(
+ $elm$url$Url$addPrefixed,
+ '#',
+ url.T,
+ A3(
+ $elm$url$Url$addPrefixed,
+ '?',
+ url.af,
+ _Utils_ap(
+ A2(
+ $elm$url$Url$addPort,
+ url.ab,
+ _Utils_ap(http, url.W)),
+ url._)));
+};
+var $author$project$Main$update = F2(
+ function (msg, model) {
+ switch (msg.$) {
+ case 0:
+ var urlRequest = msg.a;
+ if (!urlRequest.$) {
+ var url = urlRequest.a;
+ return _Utils_Tuple2(
+ model,
+ A2(
+ $elm$browser$Browser$Navigation$pushUrl,
+ model.X,
+ $elm$url$Url$toString(url)));
+ } else {
+ var href = urlRequest.a;
+ return _Utils_Tuple2(
+ model,
+ $elm$browser$Browser$Navigation$load(href));
+ }
+ case 1:
+ var url = msg.a;
+ return _Utils_Tuple2(
+ _Utils_update(
+ model,
+ {M: url}),
+ $elm$core$Platform$Cmd$none);
+ case 2:
+ var text = msg.a;
+ return _Utils_Tuple2(
+ _Utils_update(
+ model,
+ {y: text}),
+ $elm$core$Platform$Cmd$none);
+ case 3:
+ return _Utils_Tuple2(
+ model,
+ $author$project$Main$saveCapture(model.y));
+ case 4:
+ if (!msg.a.$) {
+ var response = msg.a.a;
+ return _Utils_Tuple2(
+ _Utils_update(
+ model,
+ {y: '', E: 'Capture saved'}),
+ $elm$core$Platform$Cmd$none);
+ } else {
+ var e = msg.a.a;
+ return _Utils_Tuple2(
+ _Utils_update(
+ model,
+ {E: 'The capture couldn\'t be saved'}),
+ $elm$core$Platform$Cmd$none);
+ }
+ default:
+ var status = msg.a;
+ return _Utils_Tuple2(
+ _Utils_update(
+ model,
+ {H: status}),
+ $elm$core$Platform$Cmd$none);
+ }
+ });
+var $author$project$Main$Capture = function (a) {
+ return {$: 2, a: a};
+};
+var $author$project$Main$CreateCapture = {$: 3};
+var $elm$html$Html$Attributes$stringProperty = F2(
+ function (key, string) {
+ return A2(
+ _VirtualDom_property,
+ key,
+ $elm$json$Json$Encode$string(string));
+ });
+var $elm$html$Html$Attributes$alt = $elm$html$Html$Attributes$stringProperty('alt');
+var $elm$html$Html$button = _VirtualDom_node('button');
+var $elm$html$Html$Attributes$class = $elm$html$Html$Attributes$stringProperty('className');
+var $elm$html$Html$div = _VirtualDom_node('div');
+var $elm$html$Html$h1 = _VirtualDom_node('h1');
+var $elm$html$Html$img = _VirtualDom_node('img');
+var $elm$html$Html$main_ = _VirtualDom_node('main');
+var $elm$virtual_dom$VirtualDom$Normal = function (a) {
+ return {$: 0, a: a};
+};
+var $elm$virtual_dom$VirtualDom$on = _VirtualDom_on;
+var $elm$html$Html$Events$on = F2(
+ function (event, decoder) {
+ return A2(
+ $elm$virtual_dom$VirtualDom$on,
+ event,
+ $elm$virtual_dom$VirtualDom$Normal(decoder));
+ });
+var $elm$html$Html$Events$onClick = function (msg) {
+ return A2(
+ $elm$html$Html$Events$on,
+ 'click',
+ $elm$json$Json$Decode$succeed(msg));
+};
+var $elm$html$Html$Events$alwaysStop = function (x) {
+ return _Utils_Tuple2(x, true);
+};
+var $elm$virtual_dom$VirtualDom$MayStopPropagation = function (a) {
+ return {$: 1, a: a};
+};
+var $elm$html$Html$Events$stopPropagationOn = F2(
+ function (event, decoder) {
+ return A2(
+ $elm$virtual_dom$VirtualDom$on,
+ event,
+ $elm$virtual_dom$VirtualDom$MayStopPropagation(decoder));
+ });
+var $elm$json$Json$Decode$at = F2(
+ function (fields, decoder) {
+ return A3($elm$core$List$foldr, $elm$json$Json$Decode$field, decoder, fields);
+ });
+var $elm$html$Html$Events$targetValue = A2(
+ $elm$json$Json$Decode$at,
+ _List_fromArray(
+ ['target', 'value']),
+ $elm$json$Json$Decode$string);
+var $elm$html$Html$Events$onInput = function (tagger) {
+ return A2(
+ $elm$html$Html$Events$stopPropagationOn,
+ 'input',
+ A2(
+ $elm$json$Json$Decode$map,
+ $elm$html$Html$Events$alwaysStop,
+ A2($elm$json$Json$Decode$map, tagger, $elm$html$Html$Events$targetValue)));
+};
+var $elm$core$List$filter = F2(
+ function (isGood, list) {
+ return A3(
+ $elm$core$List$foldr,
+ F2(
+ function (x, xs) {
+ return isGood(x) ? A2($elm$core$List$cons, x, xs) : xs;
+ }),
+ _List_Nil,
+ list);
+ });
+var $elm$core$Tuple$second = function (_v0) {
+ var y = _v0.b;
+ return y;
+};
+var $elm$html$Html$Attributes$classList = function (classes) {
+ return $elm$html$Html$Attributes$class(
+ A2(
+ $elm$core$String$join,
+ ' ',
+ A2(
+ $elm$core$List$map,
+ $elm$core$Tuple$first,
+ A2($elm$core$List$filter, $elm$core$Tuple$second, classes))));
+};
+var $elm$html$Html$Attributes$src = function (url) {
+ return A2(
+ $elm$html$Html$Attributes$stringProperty,
+ 'src',
+ _VirtualDom_noJavaScriptOrHtmlUri(url));
+};
+var $author$project$Main$onlineView = function (onlineStatus) {
+ return A2(
+ $elm$html$Html$div,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$classList(
+ _List_fromArray(
+ [
+ _Utils_Tuple2('dn', onlineStatus)
+ ]))
+ ]),
+ _List_fromArray(
+ [
+ A2(
+ $elm$html$Html$img,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$src('/elm-pwa-example/assets/images/signal_wifi_off.svg'),
+ $elm$html$Html$Attributes$alt('offline icon')
+ ]),
+ _List_Nil)
+ ]));
+};
+var $elm$html$Html$Attributes$placeholder = $elm$html$Html$Attributes$stringProperty('placeholder');
+var $elm$virtual_dom$VirtualDom$text = _VirtualDom_text;
+var $elm$html$Html$text = $elm$virtual_dom$VirtualDom$text;
+var $elm$html$Html$textarea = _VirtualDom_node('textarea');
+var $elm$html$Html$Attributes$value = $elm$html$Html$Attributes$stringProperty('value');
+var $author$project$Main$view = function (model) {
+ return {
+ O: _List_fromArray(
+ [
+ A2(
+ $elm$html$Html$main_,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('pa2')
+ ]),
+ _List_fromArray(
+ [
+ $elm$html$Html$text(model.E),
+ $author$project$Main$onlineView(model.H),
+ A2(
+ $elm$html$Html$h1,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('tc ')
+ ]),
+ _List_fromArray(
+ [
+ $elm$html$Html$text('Capture')
+ ])),
+ A2(
+ $elm$html$Html$div,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('h-75')
+ ]),
+ _List_fromArray(
+ [
+ A2(
+ $elm$html$Html$textarea,
+ _List_fromArray(
+ [
+ $elm$html$Html$Events$onInput($author$project$Main$Capture),
+ $elm$html$Html$Attributes$value(model.y),
+ $elm$html$Html$Attributes$class('db mb2 center w-100 w-60-l h-100 resize-none'),
+ $elm$html$Html$Attributes$placeholder('write down everything that is on your mind')
+ ]),
+ _List_Nil),
+ A2(
+ $elm$html$Html$div,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('tc')
+ ]),
+ _List_fromArray(
+ [
+ A2(
+ $elm$html$Html$button,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('bg-near-white bn'),
+ $elm$html$Html$Events$onClick($author$project$Main$CreateCapture)
+ ]),
+ _List_fromArray(
+ [
+ A2(
+ $elm$html$Html$img,
+ _List_fromArray(
+ [
+ $elm$html$Html$Attributes$class('pointer tc center'),
+ $elm$html$Html$Attributes$src('/elm-pwa-example/assets/images/submit.png'),
+ $elm$html$Html$Attributes$alt('capture')
+ ]),
+ _List_Nil)
+ ]))
+ ]))
+ ]))
+ ]))
+ ]),
+ aQ: 'DWYL App'
+ };
+};
+var $author$project$Main$main = $elm$browser$Browser$application(
+ {aD: $author$project$Main$init, aG: $author$project$Main$UrlChanged, aH: $author$project$Main$LinkClicked, aO: $author$project$Main$subscriptions, aR: $author$project$Main$update, aS: $author$project$Main$view});
+_Platform_export({'Main':{'init':$author$project$Main$main(
+ $elm$json$Json$Decode$succeed(0))(0)}});}(this));
\ No newline at end of file
diff --git a/elm.json b/elm.json
new file mode 100644
index 0000000..7e5229d
--- /dev/null
+++ b/elm.json
@@ -0,0 +1,27 @@
+{
+ "type": "application",
+ "source-directories": [
+ "src"
+ ],
+ "elm-version": "0.19.1",
+ "dependencies": {
+ "direct": {
+ "elm/browser": "1.0.2",
+ "elm/core": "1.0.4",
+ "elm/html": "1.0.0",
+ "elm/http": "2.0.0",
+ "elm/json": "1.1.3",
+ "elm/url": "1.0.0"
+ },
+ "indirect": {
+ "elm/bytes": "1.0.8",
+ "elm/file": "1.0.5",
+ "elm/time": "1.0.0",
+ "elm/virtual-dom": "1.0.2"
+ }
+ },
+ "test-dependencies": {
+ "direct": {},
+ "indirect": {}
+ }
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..68502f8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,40 @@
+
+
+
+ Dwyl App
+
+
+
+
+
+
+
+
+
+
+
+ This website is using Elm, so it needs js enabled
+
+
+
+
\ No newline at end of file
diff --git a/lib/app.ex b/lib/app.ex
deleted file mode 100644
index a10dc06..0000000
--- a/lib/app.ex
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule App do
- @moduledoc """
- App keeps the contexts that define your domain
- and business logic.
-
- Contexts are also responsible for managing your data, regardless
- if it comes from the database, an external API or others.
- """
-end
diff --git a/lib/app/application.ex b/lib/app/application.ex
deleted file mode 100644
index 04f8a68..0000000
--- a/lib/app/application.ex
+++ /dev/null
@@ -1,31 +0,0 @@
-defmodule App.Application do
- # See https://hexdocs.pm/elixir/Application.html
- # for more information on OTP Applications
- @moduledoc false
-
- use Application
-
- def start(_type, _args) do
- # List all child processes to be supervised
- children = [
- # Start the Ecto repository
- App.Repo,
- # Start the endpoint when the application starts
- AppWeb.Endpoint
- # Starts a worker by calling: App.Worker.start_link(arg)
- # {App.Worker, arg},
- ]
-
- # See https://hexdocs.pm/elixir/Supervisor.html
- # for other strategies and supported options
- opts = [strategy: :one_for_one, name: App.Supervisor]
- Supervisor.start_link(children, opts)
- end
-
- # Tell Phoenix to update the endpoint configuration
- # whenever the application is updated.
- def config_change(changed, _new, removed) do
- AppWeb.Endpoint.config_change(changed, removed)
- :ok
- end
-end
diff --git a/lib/app/ctx.ex b/lib/app/ctx.ex
deleted file mode 100644
index 4c6dac5..0000000
--- a/lib/app/ctx.ex
+++ /dev/null
@@ -1,639 +0,0 @@
-defmodule App.Ctx do
- @moduledoc """
- The Ctx context.
- """
-
- import Ecto.Query, warn: false
- alias App.Repo
-
- alias App.Ctx.Tag
-
- @doc """
- Returns the list of tags.
-
- ## Examples
-
- iex> list_tags()
- [%Tag{}, ...]
-
- """
- def list_tags do
- Repo.all(Tag)
- end
-
- @doc """
- Gets a single tag.
-
- Raises `Ecto.NoResultsError` if the Tag does not exist.
-
- ## Examples
-
- iex> get_tag!(123)
- %Tag{}
-
- iex> get_tag!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_tag!(id), do: Repo.get!(Tag, id)
-
- @doc """
- Creates a tag.
-
- ## Examples
-
- iex> create_tag(%{field: value})
- {:ok, %Tag{}}
-
- iex> create_tag(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_tag(attrs \\ %{}) do
- %Tag{}
- |> Tag.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a tag.
-
- ## Examples
-
- iex> update_tag(tag, %{field: new_value})
- {:ok, %Tag{}}
-
- iex> update_tag(tag, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_tag(%Tag{} = tag, attrs) do
- tag
- |> Tag.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a Tag.
-
- ## Examples
-
- iex> delete_tag(tag)
- {:ok, %Tag{}}
-
- iex> delete_tag(tag)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_tag(%Tag{} = tag) do
- Repo.delete(tag)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking tag changes.
-
- ## Examples
-
- iex> change_tag(tag)
- %Ecto.Changeset{source: %Tag{}}
-
- """
- def change_tag(%Tag{} = tag) do
- Tag.changeset(tag, %{})
- end
-
- alias App.Ctx.Status
-
- @doc """
- Returns the list of status.
-
- ## Examples
-
- iex> list_status()
- [%Status{}, ...]
-
- """
- def list_status do
- Repo.all(Status)
- end
-
- @doc """
- Gets a single status.
-
- Raises `Ecto.NoResultsError` if the Status does not exist.
-
- ## Examples
-
- iex> get_status!(123)
- %Status{}
-
- iex> get_status!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_status!(id), do: Repo.get!(Status, id)
-
- @doc """
- Creates a status.
-
- ## Examples
-
- iex> create_status(%{field: value})
- {:ok, %Status{}}
-
- iex> create_status(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_status(attrs \\ %{}) do
- %Status{}
- |> Status.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a status.
-
- ## Examples
-
- iex> update_status(status, %{field: new_value})
- {:ok, %Status{}}
-
- iex> update_status(status, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_status(%Status{} = status, attrs) do
- status
- |> Status.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a Status.
-
- ## Examples
-
- iex> delete_status(status)
- {:ok, %Status{}}
-
- iex> delete_status(status)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_status(%Status{} = status) do
- Repo.delete(status)
- end
-
- def get_status_verified() do
- Repo.get_by(Status, text: "verified")
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking status changes.
-
- ## Examples
-
- iex> change_status(status)
- %Ecto.Changeset{source: %Status{}}
-
- """
- def change_status(%Status{} = status) do
- Status.changeset(status, %{})
- end
-
- alias App.Ctx.Person
-
- @doc """
- Returns the list of people.
-
- ## Examples
-
- iex> list_people()
- [%Person{}, ...]
-
- """
- def list_people do
- Repo.all(Person)
- end
-
- @doc """
- Gets a single person.
-
- Raises `Ecto.NoResultsError` if the Person does not exist.
-
- ## Examples
-
- iex> get_person!(123)
- %Person{}
-
- iex> get_person!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_person!(id), do: Repo.get!(Person, id)
-
- @doc """
- Gets a single person.
- Returs `%Person{...}` or `nil` if not found
- """
- def get_person(id), do: Repo.get(Person, id)
-
- @doc """
- Get a person by email
- """
- def get_person_by_email(email) do
- Repo.get_by(Person, email_hash: email)
- end
-
- @doc """
- Creates a person.
-
- ## Examples
-
- iex> create_person(%{field: value})
- {:ok, %Person{}}
-
- iex> create_person(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_person(attrs \\ %{}) do
- %Person{}
- |> Person.changeset(attrs)
- |> Repo.insert()
- end
-
-
- @doc """
- Create a person from Google profile
- """
- def create_google_person(attrs \\ %{}) do
- %Person{}
- |> Person.google_changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Register a person with email/password
- """
- def register_person(attrs \\ %{}) do
- %Person{}
- |> Person.changeset_registration(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a person.
-
- ## Examples
-
- iex> update_person(person, %{field: new_value})
- {:ok, %Person{}}
-
- iex> update_person(person, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_person(%Person{} = person, attrs) do
- person
- |> Person.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a Person.
-
- ## Examples
-
- iex> delete_person(person)
- {:ok, %Person{}}
-
- iex> delete_person(person)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_person(%Person{} = person) do
- Repo.delete(person)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking person changes.
-
- ## Examples
-
- iex> change_person(person)
- %Ecto.Changeset{source: %Person{}}
-
- """
- def change_person(%Person{} = person) do
- Person.changeset(person, %{})
- end
-
- alias App.Ctx.Item
-
- @doc """
- Returns the list of items.
-
- ## Examples
-
- iex> list_items()
- [%Item{}, ...]
-
- """
- def list_items do
- Repo.all(Item)
- end
-
- @doc """
- Gets a single item.
-
- Raises `Ecto.NoResultsError` if the Item does not exist.
-
- ## Examples
-
- iex> get_item!(123)
- %Item{}
-
- iex> get_item!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_item!(id), do: Repo.get!(Item, id)
-
- @doc """
- Creates a item.
-
- ## Examples
-
- iex> create_item(%{field: value})
- {:ok, %Item{}}
-
- iex> create_item(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_item(attrs \\ %{}) do
- %Item{}
- |> Item.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a item.
-
- ## Examples
-
- iex> update_item(item, %{field: new_value})
- {:ok, %Item{}}
-
- iex> update_item(item, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_item(%Item{} = item, attrs) do
- item
- |> Item.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a Item.
-
- ## Examples
-
- iex> delete_item(item)
- {:ok, %Item{}}
-
- iex> delete_item(item)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_item(%Item{} = item) do
- Repo.delete(item)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking item changes.
-
- ## Examples
-
- iex> change_item(item)
- %Ecto.Changeset{source: %Item{}}
-
- """
- def change_item(%Item{} = item) do
- Item.changeset(item, %{})
- end
-
- alias App.Ctx.List
-
- @doc """
- Returns the list of lists.
-
- ## Examples
-
- iex> list_lists()
- [%List{}, ...]
-
- """
- def list_lists do
- Repo.all(List)
- end
-
- @doc """
- Gets a single list.
-
- Raises `Ecto.NoResultsError` if the List does not exist.
-
- ## Examples
-
- iex> get_list!(123)
- %List{}
-
- iex> get_list!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_list!(id), do: Repo.get!(List, id)
-
- @doc """
- Creates a list.
-
- ## Examples
-
- iex> create_list(%{field: value})
- {:ok, %List{}}
-
- iex> create_list(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_list(attrs \\ %{}) do
- %List{}
- |> List.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a list.
-
- ## Examples
-
- iex> update_list(list, %{field: new_value})
- {:ok, %List{}}
-
- iex> update_list(list, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_list(%List{} = list, attrs) do
- list
- |> List.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a List.
-
- ## Examples
-
- iex> delete_list(list)
- {:ok, %List{}}
-
- iex> delete_list(list)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_list(%List{} = list) do
- Repo.delete(list)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking list changes.
-
- ## Examples
-
- iex> change_list(list)
- %Ecto.Changeset{source: %List{}}
-
- """
- def change_list(%List{} = list) do
- List.changeset(list, %{})
- end
-
- alias App.Ctx.Timer
-
- @doc """
- Returns the list of timers.
-
- ## Examples
-
- iex> list_timers()
- [%Timer{}, ...]
-
- """
- def list_timers do
- Repo.all(Timer)
- end
-
- @doc """
- Gets a single timer.
-
- Raises `Ecto.NoResultsError` if the Timer does not exist.
-
- ## Examples
-
- iex> get_timer!(123)
- %Timer{}
-
- iex> get_timer!(456)
- ** (Ecto.NoResultsError)
-
- """
- def get_timer!(id), do: Repo.get!(Timer, id)
-
- @doc """
- Creates a timer.
-
- ## Examples
-
- iex> create_timer(%{field: value})
- {:ok, %Timer{}}
-
- iex> create_timer(%{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def create_timer(attrs \\ %{}) do
- %Timer{}
- |> Timer.changeset(attrs)
- |> Repo.insert()
- end
-
- @doc """
- Updates a timer.
-
- ## Examples
-
- iex> update_timer(timer, %{field: new_value})
- {:ok, %Timer{}}
-
- iex> update_timer(timer, %{field: bad_value})
- {:error, %Ecto.Changeset{}}
-
- """
- def update_timer(%Timer{} = timer, attrs) do
- timer
- |> Timer.changeset(attrs)
- |> Repo.update()
- end
-
- @doc """
- Deletes a Timer.
-
- ## Examples
-
- iex> delete_timer(timer)
- {:ok, %Timer{}}
-
- iex> delete_timer(timer)
- {:error, %Ecto.Changeset{}}
-
- """
- def delete_timer(%Timer{} = timer) do
- Repo.delete(timer)
- end
-
- @doc """
- Returns an `%Ecto.Changeset{}` for tracking timer changes.
-
- ## Examples
-
- iex> change_timer(timer)
- %Ecto.Changeset{source: %Timer{}}
-
- """
- def change_timer(%Timer{} = timer) do
- Timer.changeset(timer, %{})
- end
-
- alias App.Ctx.Session
- @doc """
- Create a session
- """
- def create_session(user, attrs \\ %{}) do
- Session.changeset(user, attrs)
- |> Repo.insert()
- end
-
- @doc """
- Create a basic session
- """
- def create_basic_session(user, attrs \\ %{}) do
- Session.basic_changeset(user, attrs)
- |> Repo.insert()
- end
-
-
-end
diff --git a/lib/app/ctx/item.ex b/lib/app/ctx/item.ex
deleted file mode 100644
index 665c7a6..0000000
--- a/lib/app/ctx/item.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule App.Ctx.Item do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "items" do
- field :text, :string
- field :person_id, :id # an item always belongs to a person
- field :status, :id
- many_to_many :tags, App.Ctx.Tag, join_through: "item_tags"
- timestamps()
- end
-
- @doc false
- def changeset(item, attrs) do
- item
- |> cast(attrs, [:text])
- |> validate_required([:text])
- end
-end
diff --git a/lib/app/ctx/list.ex b/lib/app/ctx/list.ex
deleted file mode 100644
index 6038fe3..0000000
--- a/lib/app/ctx/list.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule App.Ctx.List do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "lists" do
- field :title, :string
- field :person_id, :id # the owner of the list
- field :status, :id
- field :tag, :id
-
- timestamps()
- end
-
- @doc false
- def changeset(list, attrs) do
- list
- |> cast(attrs, [:title])
- |> validate_required([:title])
- end
-end
diff --git a/lib/app/ctx/person.ex b/lib/app/ctx/person.ex
deleted file mode 100644
index 1d8ce9c..0000000
--- a/lib/app/ctx/person.ex
+++ /dev/null
@@ -1,129 +0,0 @@
-defmodule App.Ctx.Person do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "people" do
- field :email, Fields.EmailEncrypted
- field :email_hash, Fields.EmailHash
- field :familyName, Fields.Encrypted
- field :givenName, Fields.Encrypted
- field :locale, :string
- field :password, :string, virtual: true
- field :password_hash, Fields.Password
- field :picture, :binary
- field :username, :binary
- field :username_hash, Fields.Hash
- field :status, :id
- field :tag, :id
- field :key_id, :integer
-
- has_many :sessions, App.Ctx.Session, on_delete: :delete_all
- timestamps()
- end
-
- @doc """
- Default attributes validation for Person
- """
- def changeset(person, attrs) do
- person
- |> cast(attrs, [:username, :email, :givenName, :familyName, :password_hash, :key_id, :locale, :picture])
- |> validate_required([:username, :email, :givenName, :familyName, :password_hash, :key_id])
- |> put_email_hash()
- end
-
- @doc """
- Changeset used for Google OAuth authentication
- Add email hash and set status verified
- """
- def google_changeset(profile, attrs) do
- profile
- |> cast(attrs, [:email, :givenName, :familyName, :picture, :locale])
- |> validate_required([:email])
- |> put_email_hash()
- |> put_email_status_verified()
- end
-
- defp put_email_hash(changeset) do
- case changeset do
- %{valid?: true, changes: %{email: email}} ->
- put_change(changeset, :email_hash, email)
-
- _ ->
- changeset
- end
- end
-
- defp put_email_status_verified(changeset) do
- status_verified = App.Ctx.get_status_verified()
- case changeset do
- %{valid?: true} ->
- put_change(changeset, :status, status_verified.id)
-
- _ ->
- changeset
- end
- end
-
- @doc """
- `transform_profile_data_to_person/1` transforms the profile data
- received from invoking `ElixirAuthGoogle.get_user_profile/1`
- into a `person` record that can be inserted into the people table.
-
- ## Example
-
- iex> transform_profile_data_to_person(%{
- "email" => "nelson@gmail.com",
- "email_verified" => true,
- "family_name" => "Correia",
- "given_name" => "Nelson",
- "locale" => "en",
- "name" => "Nelson Correia",
- "picture" => "https://lh3.googleusercontent.com/a-/AAuE7mApnYb260YC1JY7a",
- "sub" => "940732358705212133793"
- })
- %{
- "email" => "nelson@gmail.com",
- "email_verified" => true,
- "family_name" => "Correia",
- "given_name" => "Nelson",
- "locale" => "en",
- "name" => "Nelson Correia",
- "picture" => "https://lh3.googleusercontent.com/a-/AAuE7mApnYb260YC1JY7a",
- "sub" => "940732358705212133793"
- "status" => 1,
- "familyName" => "Correia",
- "givenName" => "Nelson"
- }
- """
- def transform_profile_data_to_person(profile) do
- profile
- |> Map.put(:familyName, profile.family_name)
- |> Map.put(:givenName, profile.given_name)
- |> Map.put(:locale, profile.locale)
- |> Map.put(:picture, profile.picture)
- end
-
- @doc """
- Changeset function used for email/password registration
- Define email hash and password hash
- """
- def changeset_registration(profile, attrs) do
- profile
- |> cast(attrs, [:email, :password])
- |> validate_required([:email, :password])
- |> validate_length(:password, min: 6, max: 100)
- |> unique_constraint(:email)
- |> put_email_hash()
- |> put_pass_hash()
- end
-
- defp put_pass_hash(changeset) do
- case changeset do
- %Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
- put_change(changeset, :password_hash, pass)
- _ ->
- changeset
- end
- end
-
-end
diff --git a/lib/app/ctx/session.ex b/lib/app/ctx/session.ex
deleted file mode 100644
index 34aa88d..0000000
--- a/lib/app/ctx/session.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule App.Ctx.Session do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "sessions" do
- field :auth_token, Fields.Encrypted
- field :refresh_token, Fields.Encrypted
- field :key_id, :integer
-
- belongs_to :person, App.Ctx.Person
- timestamps()
- end
-
-
- def changeset(people, attrs) do
- Ecto.build_assoc(people, :sessions)
- |> cast(attrs, [:auth_token, :refresh_token])
- |> validate_required([:auth_token, :refresh_token])
- end
-
- def basic_changeset(people, _attrs) do
- Ecto.build_assoc(people, :sessions)
- end
-
-end
diff --git a/lib/app/ctx/status.ex b/lib/app/ctx/status.ex
deleted file mode 100644
index 475a40d..0000000
--- a/lib/app/ctx/status.ex
+++ /dev/null
@@ -1,18 +0,0 @@
-defmodule App.Ctx.Status do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "status" do
- field :text, :string
- belongs_to :person, App.Ctx.Person
-
- timestamps()
- end
-
- @doc false
- def changeset(status, attrs) do
- status
- |> cast(attrs, [:text])
- |> validate_required([:text])
- end
-end
diff --git a/lib/app/ctx/tag.ex b/lib/app/ctx/tag.ex
deleted file mode 100644
index 4b87115..0000000
--- a/lib/app/ctx/tag.ex
+++ /dev/null
@@ -1,17 +0,0 @@
-defmodule App.Ctx.Tag do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "tags" do
- field :text, :string
- belongs_to :person, App.Ctx.Person
- timestamps()
- end
-
- @doc false
- def changeset(tag, attrs) do
- tag
- |> cast(attrs, [:text])
- |> validate_required([:text])
- end
-end
diff --git a/lib/app/ctx/timer.ex b/lib/app/ctx/timer.ex
deleted file mode 100644
index cf1d5a3..0000000
--- a/lib/app/ctx/timer.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule App.Ctx.Timer do
- use Ecto.Schema
- import Ecto.Changeset
-
- schema "timers" do
- field :end, :naive_datetime
- field :start, :naive_datetime
- field :item_id, :id
- field :person_id, :id
-
- timestamps()
- end
-
- @doc false
- def changeset(timer, attrs) do
- timer
- |> cast(attrs, [:start, :end])
- |> validate_required([:start, :end])
- end
-end
diff --git a/lib/app/repo.ex b/lib/app/repo.ex
deleted file mode 100644
index 857bd3f..0000000
--- a/lib/app/repo.ex
+++ /dev/null
@@ -1,5 +0,0 @@
-defmodule App.Repo do
- use Ecto.Repo,
- otp_app: :app,
- adapter: Ecto.Adapters.Postgres
-end
diff --git a/lib/app_web.ex b/lib/app_web.ex
deleted file mode 100644
index acad4d7..0000000
--- a/lib/app_web.ex
+++ /dev/null
@@ -1,69 +0,0 @@
-defmodule AppWeb do
- @moduledoc """
- The entrypoint for defining your web interface, such
- as controllers, views, channels and so on.
-
- This can be used in your application as:
-
- use AppWeb, :controller
- use AppWeb, :view
-
- The definitions below will be executed for every view,
- controller, etc, so keep them short and clean, focused
- on imports, uses and aliases.
-
- Do NOT define functions inside the quoted expressions
- below. Instead, define any helper function in modules
- and import those modules here.
- """
-
- def controller do
- quote do
- use Phoenix.Controller, namespace: AppWeb
-
- import Plug.Conn
- import AppWeb.Gettext
- alias AppWeb.Router.Helpers, as: Routes
- end
- end
-
- def view do
- quote do
- use Phoenix.View,
- root: "lib/app_web/templates",
- namespace: AppWeb
-
- # Import convenience functions from controllers
- import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
-
- # Use all HTML functionality (forms, tags, etc)
- use Phoenix.HTML
-
- import AppWeb.ErrorHelpers
- import AppWeb.Gettext
- alias AppWeb.Router.Helpers, as: Routes
- end
- end
-
- def router do
- quote do
- use Phoenix.Router
- import Plug.Conn
- import Phoenix.Controller
- end
- end
-
- def channel do
- quote do
- use Phoenix.Channel
- import AppWeb.Gettext
- end
- end
-
- @doc """
- When used, dispatch to the appropriate controller/view/etc.
- """
- defmacro __using__(which) when is_atom(which) do
- apply(__MODULE__, which, [])
- end
-end
diff --git a/lib/app_web/channels/user_socket.ex b/lib/app_web/channels/user_socket.ex
deleted file mode 100644
index ac17ce5..0000000
--- a/lib/app_web/channels/user_socket.ex
+++ /dev/null
@@ -1,33 +0,0 @@
-defmodule AppWeb.UserSocket do
- use Phoenix.Socket
-
- ## Channels
- # channel "room:*", AppWeb.RoomChannel
-
- # Socket params are passed from the client and can
- # be used to verify and authenticate a user. After
- # verification, you can put default assigns into
- # the socket that will be set for all channels, ie
- #
- # {:ok, assign(socket, :user_id, verified_user_id)}
- #
- # To deny connection, return `:error`.
- #
- # See `Phoenix.Token` documentation for examples in
- # performing token verification on connect.
- def connect(_params, socket, _connect_info) do
- {:ok, socket}
- end
-
- # Socket id's are topics that allow you to identify all sockets for a given user:
- #
- # def id(socket), do: "user_socket:#{socket.assigns.user_id}"
- #
- # Would allow you to broadcast a "disconnect" event and terminate
- # all active sockets and channels for a given user:
- #
- # AppWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
- #
- # Returning `nil` makes this socket anonymous.
- def id(_socket), do: nil
-end
diff --git a/lib/app_web/controllers/auth_controller.ex b/lib/app_web/controllers/auth_controller.ex
deleted file mode 100644
index f15fbae..0000000
--- a/lib/app_web/controllers/auth_controller.ex
+++ /dev/null
@@ -1,45 +0,0 @@
-defmodule AppWeb.Auth do
- use AppWeb, :controller
- # use AppWeb, :router
- import Plug.Conn
- # alias App.Repo
-
- def init(opts), do: opts
-
- def call(conn, _opts) do
- person_id = get_session(conn, :person_id)
- cond do
- person = conn.assigns[:current_person] ->
- assign(conn, :current_person, person)
-
- person = person_id && App.Ctx.get_person(person_id) ->
- assign(conn, :current_person, person)
-
- true ->
- assign(conn, :current_person, nil)
- end
- end
-
- def login(conn, person) do
- conn
- |> assign(:current_person, person)
- |> put_session(:person_id, person.id)
- |> configure_session(renew: true)
- end
-
- def logout(conn) do
- configure_session(conn, drop: true)
- end
-
-
- def authenticate_person(conn, _opts) do
- if conn.assigns.current_person do
- conn
- else
- conn
- # redirect to login page
- |> redirect(to: Routes.page_path(conn, :index))
- |> halt()
- end
- end
-end
diff --git a/lib/app_web/controllers/captures_controller.ex b/lib/app_web/controllers/captures_controller.ex
deleted file mode 100644
index be2e00f..0000000
--- a/lib/app_web/controllers/captures_controller.ex
+++ /dev/null
@@ -1,23 +0,0 @@
-defmodule AppWeb.CaptureController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Item
-
- def new(conn, _params) do
- changeset = Ctx.change_item(%Item{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"item" => capture_params}) do
- case Ctx.create_item(capture_params) do
- {:ok, _item} ->
- conn
- |> put_flash(:info, "Item created successfully.")
- |> redirect(to: Routes.categorise_path(conn, :index))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-end
diff --git a/lib/app_web/controllers/categorise_controller.ex b/lib/app_web/controllers/categorise_controller.ex
deleted file mode 100644
index ba3d424..0000000
--- a/lib/app_web/controllers/categorise_controller.ex
+++ /dev/null
@@ -1,10 +0,0 @@
-defmodule AppWeb.CategoriseController do
- use AppWeb, :controller
-
- alias App.Ctx
-
- def index(conn, _) do
- captures = Ctx.list_items()
- render(conn, "index.html", captures: captures)
- end
-end
diff --git a/lib/app_web/controllers/google_auth_controller.ex b/lib/app_web/controllers/google_auth_controller.ex
deleted file mode 100644
index d7bc26d..0000000
--- a/lib/app_web/controllers/google_auth_controller.ex
+++ /dev/null
@@ -1,39 +0,0 @@
-defmodule AppWeb.GoogleAuthController do
- use AppWeb, :controller
-
- @elixir_auth_google Application.get_env(:app, :elixir_auth_google) || ElixirAuthGoogle
-
- def index(conn, %{"code" => code}) do
- {:ok, token} = @elixir_auth_google.get_token(code, conn)
- {:ok, profile} = @elixir_auth_google.get_user_profile(token.access_token)
- person = App.Ctx.Person.transform_profile_data_to_person(profile)
-
- # get the person by email
- case App.Ctx.get_person_by_email(person.email) do
- nil ->
- # Create the person
- {:ok, person} = App.Ctx.create_google_person(person)
- create_session(conn, person, token)
- person ->
- create_session(conn, person, token)
- end
- end
-
- def create_session(conn, person, token) do
- # Create session
- session_attrs = %{
- "auth_token" => token.access_token,
- "refresh_token" => if Map.has_key?(token, :refresh_token) do
- token.refresh_token
- else
- nil
- end
- }
- App.Ctx.create_session(person, session_attrs)
-
- # login and redirect to welcome page:
- AppWeb.Auth.login(conn, person)
- |> redirect(to: Routes.person_path(conn, :info))
- end
-end
-
diff --git a/lib/app_web/controllers/item_controller.ex b/lib/app_web/controllers/item_controller.ex
deleted file mode 100644
index 86664e1..0000000
--- a/lib/app_web/controllers/item_controller.ex
+++ /dev/null
@@ -1,62 +0,0 @@
-defmodule AppWeb.ItemController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Item
-
- def index(conn, _params) do
- items = Ctx.list_items()
- render(conn, "index.html", items: items)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_item(%Item{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"item" => item_params}) do
- case Ctx.create_item(item_params) do
- {:ok, item} ->
- conn
- |> put_flash(:info, "Item created successfully.")
- |> redirect(to: Routes.item_path(conn, :show, item))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- item = Ctx.get_item!(id)
- render(conn, "show.html", item: item)
- end
-
- def edit(conn, %{"id" => id}) do
- item = Ctx.get_item!(id)
- changeset = Ctx.change_item(item)
- render(conn, "edit.html", item: item, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "item" => item_params}) do
- item = Ctx.get_item!(id)
-
- case Ctx.update_item(item, item_params) do
- {:ok, item} ->
- conn
- |> put_flash(:info, "Item updated successfully.")
- |> redirect(to: Routes.item_path(conn, :show, item))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", item: item, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- item = Ctx.get_item!(id)
- {:ok, _item} = Ctx.delete_item(item)
-
- conn
- |> put_flash(:info, "Item deleted successfully.")
- |> redirect(to: Routes.item_path(conn, :index))
- end
-end
diff --git a/lib/app_web/controllers/list_controller.ex b/lib/app_web/controllers/list_controller.ex
deleted file mode 100644
index fc221d5..0000000
--- a/lib/app_web/controllers/list_controller.ex
+++ /dev/null
@@ -1,62 +0,0 @@
-defmodule AppWeb.ListController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.List
-
- def index(conn, _params) do
- lists = Ctx.list_lists()
- render(conn, "index.html", lists: lists)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_list(%List{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"list" => list_params}) do
- case Ctx.create_list(list_params) do
- {:ok, list} ->
- conn
- |> put_flash(:info, "List created successfully.")
- |> redirect(to: Routes.list_path(conn, :show, list))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- list = Ctx.get_list!(id)
- render(conn, "show.html", list: list)
- end
-
- def edit(conn, %{"id" => id}) do
- list = Ctx.get_list!(id)
- changeset = Ctx.change_list(list)
- render(conn, "edit.html", list: list, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "list" => list_params}) do
- list = Ctx.get_list!(id)
-
- case Ctx.update_list(list, list_params) do
- {:ok, list} ->
- conn
- |> put_flash(:info, "List updated successfully.")
- |> redirect(to: Routes.list_path(conn, :show, list))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", list: list, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- list = Ctx.get_list!(id)
- {:ok, _list} = Ctx.delete_list(list)
-
- conn
- |> put_flash(:info, "List deleted successfully.")
- |> redirect(to: Routes.list_path(conn, :index))
- end
-end
diff --git a/lib/app_web/controllers/page_controller.ex b/lib/app_web/controllers/page_controller.ex
deleted file mode 100644
index a466868..0000000
--- a/lib/app_web/controllers/page_controller.ex
+++ /dev/null
@@ -1,58 +0,0 @@
-defmodule AppWeb.PageController do
- use AppWeb, :controller
- alias App.Ctx.Person
- alias App.Ctx
-
- # auth_controller assign current_person on each request
- # when the person is loggedin, otherwise the value doesn't exists or is nil
- def index(%{assigns: %{current_person: person}} = conn, _params) when not is_nil(person) do
- redirect(conn, to: Routes.person_path(conn, :info))
- end
-
- def index(conn, _params) do
- url_oauth_google = ElixirAuthGoogle.generate_oauth_url(conn)
- changeset = Person.changeset_registration(%Person{}, %{})
- render(conn, "index.html",
- [url_oauth_google: url_oauth_google, changeset: changeset])
- end
-
-
- def register(conn, %{"person" => person_params}) do
- person = Ctx.get_person_by_email(person_params["email"])
-
- if is_nil(person) do #create new person
- case Ctx.register_person(person_params) do
- {:ok, person} ->
- create_basic_session(conn, person)
-
- {:error, %Ecto.Changeset{} = changeset} ->
- url_oauth_google = ElixirAuthGoogle.generate_oauth_url(conn)
- render(conn, "index.html",
- [url_oauth_google: url_oauth_google, changeset: changeset])
- end
- else # Login person if password ok
- login(conn, person, person_params)
- end
- end
-
- # verify provided password
- # create Phx session
- # and redirect to correct page:
- # user info page if password ok or index page if it doesn't match
- defp login(conn, person, person_params) do
- if Argon2.verify_pass(person_params["password"], person.password_hash) do
- create_basic_session(conn, person)
- else
- redirect(conn, to: Routes.page_path(conn, :index))
- end
- end
-
- # Insert a new basic session in Postgres
- defp create_basic_session(conn, person) do
- App.Ctx.create_basic_session(person, %{})
-
- AppWeb.Auth.login(conn, person)
- |> redirect(to: Routes.person_path(conn, :info))
- end
-end
-
diff --git a/lib/app_web/controllers/person_controller.ex b/lib/app_web/controllers/person_controller.ex
deleted file mode 100644
index b2f906c..0000000
--- a/lib/app_web/controllers/person_controller.ex
+++ /dev/null
@@ -1,66 +0,0 @@
-defmodule AppWeb.PersonController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Person
-
- def index(conn, _params) do
- people = Ctx.list_people()
- render(conn, "index.html", people: people)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_person(%Person{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"person" => person_params}) do
- case Ctx.create_person(person_params) do
- {:ok, person} ->
- conn
- |> put_flash(:info, "Person created successfully.")
- |> redirect(to: Routes.person_path(conn, :show, person))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- person = Ctx.get_person!(id)
- render(conn, "show.html", person: person)
- end
-
- def edit(conn, %{"id" => id}) do
- person = Ctx.get_person!(id)
- changeset = Ctx.change_person(person)
- render(conn, "edit.html", person: person, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "person" => person_params}) do
- person = Ctx.get_person!(id)
-
- case Ctx.update_person(person, person_params) do
- {:ok, person} ->
- conn
- |> put_flash(:info, "Person updated successfully.")
- |> redirect(to: Routes.person_path(conn, :show, person))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", person: person, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- person = Ctx.get_person!(id)
- {:ok, _person} = Ctx.delete_person(person)
-
- conn
- |> put_flash(:info, "Person deleted successfully.")
- |> redirect(to: Routes.person_path(conn, :index))
- end
-
- def info(%{assigns: %{current_person: person}} = conn, _params) do
- render(conn, "info.html", person: person)
- end
-end
diff --git a/lib/app_web/controllers/sessions_controller.ex b/lib/app_web/controllers/sessions_controller.ex
deleted file mode 100644
index a13631c..0000000
--- a/lib/app_web/controllers/sessions_controller.ex
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule AppWeb.SessionController do
- use AppWeb, :controller
-
- def delete(conn, _params) do
- conn
- |> AppWeb.Auth.logout()
- |> redirect(to: Routes.page_path(conn, :index))
- end
-end
diff --git a/lib/app_web/controllers/status_controller.ex b/lib/app_web/controllers/status_controller.ex
deleted file mode 100644
index f055070..0000000
--- a/lib/app_web/controllers/status_controller.ex
+++ /dev/null
@@ -1,62 +0,0 @@
-defmodule AppWeb.StatusController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Status
-
- def index(conn, _params) do
- status = Ctx.list_status()
- render(conn, "index.html", status: status)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_status(%Status{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"status" => status_params}) do
- case Ctx.create_status(status_params) do
- {:ok, status} ->
- conn
- |> put_flash(:info, "Status created successfully.")
- |> redirect(to: Routes.status_path(conn, :show, status))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- status = Ctx.get_status!(id)
- render(conn, "show.html", status: status)
- end
-
- def edit(conn, %{"id" => id}) do
- status = Ctx.get_status!(id)
- changeset = Ctx.change_status(status)
- render(conn, "edit.html", status: status, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "status" => status_params}) do
- status = Ctx.get_status!(id)
-
- case Ctx.update_status(status, status_params) do
- {:ok, status} ->
- conn
- |> put_flash(:info, "Status updated successfully.")
- |> redirect(to: Routes.status_path(conn, :show, status))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", status: status, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- status = Ctx.get_status!(id)
- {:ok, _status} = Ctx.delete_status(status)
-
- conn
- |> put_flash(:info, "Status deleted successfully.")
- |> redirect(to: Routes.status_path(conn, :index))
- end
-end
diff --git a/lib/app_web/controllers/tag_controller.ex b/lib/app_web/controllers/tag_controller.ex
deleted file mode 100644
index 7587c01..0000000
--- a/lib/app_web/controllers/tag_controller.ex
+++ /dev/null
@@ -1,62 +0,0 @@
-defmodule AppWeb.TagController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Tag
-
- def index(conn, _params) do
- tags = Ctx.list_tags()
- render(conn, "index.html", tags: tags)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_tag(%Tag{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"tag" => tag_params}) do
- case Ctx.create_tag(tag_params) do
- {:ok, tag} ->
- conn
- |> put_flash(:info, "Tag created successfully.")
- |> redirect(to: Routes.tag_path(conn, :show, tag))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- tag = Ctx.get_tag!(id)
- render(conn, "show.html", tag: tag)
- end
-
- def edit(conn, %{"id" => id}) do
- tag = Ctx.get_tag!(id)
- changeset = Ctx.change_tag(tag)
- render(conn, "edit.html", tag: tag, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "tag" => tag_params}) do
- tag = Ctx.get_tag!(id)
-
- case Ctx.update_tag(tag, tag_params) do
- {:ok, tag} ->
- conn
- |> put_flash(:info, "Tag updated successfully.")
- |> redirect(to: Routes.tag_path(conn, :show, tag))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", tag: tag, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- tag = Ctx.get_tag!(id)
- {:ok, _tag} = Ctx.delete_tag(tag)
-
- conn
- |> put_flash(:info, "Tag deleted successfully.")
- |> redirect(to: Routes.tag_path(conn, :index))
- end
-end
diff --git a/lib/app_web/controllers/timer_controller.ex b/lib/app_web/controllers/timer_controller.ex
deleted file mode 100644
index 34057de..0000000
--- a/lib/app_web/controllers/timer_controller.ex
+++ /dev/null
@@ -1,62 +0,0 @@
-defmodule AppWeb.TimerController do
- use AppWeb, :controller
-
- alias App.Ctx
- alias App.Ctx.Timer
-
- def index(conn, _params) do
- timers = Ctx.list_timers()
- render(conn, "index.html", timers: timers)
- end
-
- def new(conn, _params) do
- changeset = Ctx.change_timer(%Timer{})
- render(conn, "new.html", changeset: changeset)
- end
-
- def create(conn, %{"timer" => timer_params}) do
- case Ctx.create_timer(timer_params) do
- {:ok, timer} ->
- conn
- |> put_flash(:info, "Timer created successfully.")
- |> redirect(to: Routes.timer_path(conn, :show, timer))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "new.html", changeset: changeset)
- end
- end
-
- def show(conn, %{"id" => id}) do
- timer = Ctx.get_timer!(id)
- render(conn, "show.html", timer: timer)
- end
-
- def edit(conn, %{"id" => id}) do
- timer = Ctx.get_timer!(id)
- changeset = Ctx.change_timer(timer)
- render(conn, "edit.html", timer: timer, changeset: changeset)
- end
-
- def update(conn, %{"id" => id, "timer" => timer_params}) do
- timer = Ctx.get_timer!(id)
-
- case Ctx.update_timer(timer, timer_params) do
- {:ok, timer} ->
- conn
- |> put_flash(:info, "Timer updated successfully.")
- |> redirect(to: Routes.timer_path(conn, :show, timer))
-
- {:error, %Ecto.Changeset{} = changeset} ->
- render(conn, "edit.html", timer: timer, changeset: changeset)
- end
- end
-
- def delete(conn, %{"id" => id}) do
- timer = Ctx.get_timer!(id)
- {:ok, _timer} = Ctx.delete_timer(timer)
-
- conn
- |> put_flash(:info, "Timer deleted successfully.")
- |> redirect(to: Routes.timer_path(conn, :index))
- end
-end
diff --git a/lib/app_web/endpoint.ex b/lib/app_web/endpoint.ex
deleted file mode 100644
index 2fe6aa9..0000000
--- a/lib/app_web/endpoint.ex
+++ /dev/null
@@ -1,46 +0,0 @@
-defmodule AppWeb.Endpoint do
- use Phoenix.Endpoint, otp_app: :app
-
- socket "/socket", AppWeb.UserSocket,
- websocket: [timeout: 45_000],
- longpoll: false
-
- # Serve at "/" the static files from "priv/static" directory.
- #
- # You should set gzip to true if you are running phx.digest
- # when deploying your static files in production.
- plug Plug.Static,
- at: "/",
- from: :app,
- gzip: false,
- only: ~w(css fonts images js favicon.ico robots.txt)
-
- # Code reloading can be explicitly enabled under the
- # :code_reloader configuration of your endpoint.
- if code_reloading? do
- socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
- plug Phoenix.LiveReloader
- plug Phoenix.CodeReloader
- end
-
- plug Plug.RequestId
- plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
-
- plug Plug.Parsers,
- parsers: [:urlencoded, :multipart, :json],
- pass: ["*/*"],
- json_decoder: Phoenix.json_library()
-
- plug Plug.MethodOverride
- plug Plug.Head
-
- # The session will be stored in the cookie and signed,
- # this means its contents can be read but not tampered with.
- # Set :encryption_salt if you would also like to encrypt it.
- plug Plug.Session,
- store: :cookie,
- key: "_app_key",
- signing_salt: "tUhOGa5d"
-
- plug AppWeb.Router
-end
diff --git a/lib/app_web/gettext.ex b/lib/app_web/gettext.ex
deleted file mode 100644
index 19bc04e..0000000
--- a/lib/app_web/gettext.ex
+++ /dev/null
@@ -1,24 +0,0 @@
-defmodule AppWeb.Gettext do
- @moduledoc """
- A module providing Internationalization with a gettext-based API.
-
- By using [Gettext](https://hexdocs.pm/gettext),
- your module gains a set of macros for translations, for example:
-
- import AppWeb.Gettext
-
- # Simple translation
- gettext("Here is the string to translate")
-
- # Plural translation
- ngettext("Here is the string to translate",
- "Here are the strings to translate",
- 3)
-
- # Domain-based translation
- dgettext("errors", "Here is the error message to translate")
-
- See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
- """
- use Gettext, otp_app: :app
-end
diff --git a/lib/app_web/router.ex b/lib/app_web/router.ex
deleted file mode 100644
index b2e5d9a..0000000
--- a/lib/app_web/router.ex
+++ /dev/null
@@ -1,56 +0,0 @@
-defmodule AppWeb.Router do
- use AppWeb, :router
- import AppWeb.Auth
-
- pipeline :browser do
- plug :accepts, ["html"]
- plug :fetch_session
- plug :fetch_flash
- plug :protect_from_forgery
- plug :put_secure_browser_headers
- plug AppWeb.Auth
- end
-
- pipeline :api do
- plug :accepts, ["json"]
- end
-
- pipeline :person do
- plug :authenticate_person
- end
-
- scope "/", AppWeb do
- pipe_through :browser
-
- get "/", PageController, :index
- post "/register", PageController, :register
- get "/auth/google/callback", GoogleAuthController, :index
- end
-
- scope "/", AppWeb do
- pipe_through [:browser, :person]
-
- # person information
- get "/people/info", PersonController, :info
-
- # generic resources for schemas:
- resources "/items", ItemController
- resources "/lists", ListController
- resources "/people", PersonController
- resources "/status", StatusController
- resources "/tags", TagController
- resources "/timers", TimerController
-
-
- # capture
- resources "/capture", CaptureController, only: [:new, :create]
-
- # categorise
- resources "/categorise", CategoriseController, only: [:index]
- end
-
- # Other scopes may use custom stacks.
- # scope "/api", AppWeb do
- # pipe_through :api
- # end
-end
diff --git a/lib/app_web/templates/capture/new.html.eex b/lib/app_web/templates/capture/new.html.eex
deleted file mode 100644
index 77b5a25..0000000
--- a/lib/app_web/templates/capture/new.html.eex
+++ /dev/null
@@ -1,14 +0,0 @@
-Capture
-
-<%= form_for @changeset, Routes.capture_path(@conn, :create), [class: "h-75"], fn f -> %>
- <%= textarea f, :text, class: "db mb2 center w-100 w-60-l h-100 resize-none", placeholder: "write down everything that is on your mind" %>
-
- <%= error_tag f, :text %>
-
-
-
- <%= submit class: "bg-near-white bn" do %>
-
- <% end %>
-
-<% end %>
diff --git a/lib/app_web/templates/categorise/_capture.html.eex b/lib/app_web/templates/categorise/_capture.html.eex
deleted file mode 100644
index 8081b9e..0000000
--- a/lib/app_web/templates/categorise/_capture.html.eex
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
- <%= text_to_html @categorise.text %>
-
-
-
- <%= link "Edit", to: Routes.item_path(@conn, :edit, @categorise) %>
- <%= link "Delete", to: Routes.item_path(@conn, :delete, @categorise), method: :delete, data: [confirm: "Are you sure?"] %>
-
\ No newline at end of file
diff --git a/lib/app_web/templates/categorise/index.html.eex b/lib/app_web/templates/categorise/index.html.eex
deleted file mode 100644
index b3baee1..0000000
--- a/lib/app_web/templates/categorise/index.html.eex
+++ /dev/null
@@ -1,4 +0,0 @@
-Captures
-
- <%= render_many @captures, AppWeb.CategoriseView, "_capture.html", conn: @conn %>
-
\ No newline at end of file
diff --git a/lib/app_web/templates/item/edit.html.eex b/lib/app_web/templates/item/edit.html.eex
deleted file mode 100644
index 421afd2..0000000
--- a/lib/app_web/templates/item/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit Item
-
-<%= render "form.html", Map.put(assigns, :action, Routes.item_path(@conn, :update, @item)) %>
-
-<%= link "Back", to: Routes.item_path(@conn, :index) %>
diff --git a/lib/app_web/templates/item/form.html.eex b/lib/app_web/templates/item/form.html.eex
deleted file mode 100644
index 1c656c3..0000000
--- a/lib/app_web/templates/item/form.html.eex
+++ /dev/null
@@ -1,15 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :text %>
- <%= text_input f, :text %>
- <%= error_tag f, :text %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/item/index.html.eex b/lib/app_web/templates/item/index.html.eex
deleted file mode 100644
index dbe79d8..0000000
--- a/lib/app_web/templates/item/index.html.eex
+++ /dev/null
@@ -1,26 +0,0 @@
-Listing Items
-
-
-
-
- Text
-
-
-
-
-
-<%= for item <- @items do %>
-
- <%= item.text %>
-
-
- <%= link "Show", to: Routes.item_path(@conn, :show, item) %>
- <%= link "Edit", to: Routes.item_path(@conn, :edit, item) %>
- <%= link "Delete", to: Routes.item_path(@conn, :delete, item), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New Item", to: Routes.item_path(@conn, :new) %>
diff --git a/lib/app_web/templates/item/new.html.eex b/lib/app_web/templates/item/new.html.eex
deleted file mode 100644
index fe5c45b..0000000
--- a/lib/app_web/templates/item/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New Item
-
-<%= render "form.html", Map.put(assigns, :action, Routes.item_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.item_path(@conn, :index) %>
diff --git a/lib/app_web/templates/item/show.html.eex b/lib/app_web/templates/item/show.html.eex
deleted file mode 100644
index 1bffa82..0000000
--- a/lib/app_web/templates/item/show.html.eex
+++ /dev/null
@@ -1,13 +0,0 @@
-Show Item
-
-
-
-
- Text:
- <%= @item.text %>
-
-
-
-
-<%= link "Edit", to: Routes.item_path(@conn, :edit, @item) %>
-<%= link "Back", to: Routes.item_path(@conn, :index) %>
diff --git a/lib/app_web/templates/layout/app.html.eex b/lib/app_web/templates/layout/app.html.eex
deleted file mode 100644
index 0516576..0000000
--- a/lib/app_web/templates/layout/app.html.eex
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
- dwyl app
- "/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <%= get_flash(@conn, :info) %>
- <%= get_flash(@conn, :error) %>
- <%= render @view_module, @view_template, assigns %>
-
-
-
-
diff --git a/lib/app_web/templates/list/edit.html.eex b/lib/app_web/templates/list/edit.html.eex
deleted file mode 100644
index 5a126b5..0000000
--- a/lib/app_web/templates/list/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit List
-
-<%= render "form.html", Map.put(assigns, :action, Routes.list_path(@conn, :update, @list)) %>
-
-<%= link "Back", to: Routes.list_path(@conn, :index) %>
diff --git a/lib/app_web/templates/list/form.html.eex b/lib/app_web/templates/list/form.html.eex
deleted file mode 100644
index a812b90..0000000
--- a/lib/app_web/templates/list/form.html.eex
+++ /dev/null
@@ -1,15 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :title %>
- <%= text_input f, :title %>
- <%= error_tag f, :title %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/list/index.html.eex b/lib/app_web/templates/list/index.html.eex
deleted file mode 100644
index 2e6fb29..0000000
--- a/lib/app_web/templates/list/index.html.eex
+++ /dev/null
@@ -1,26 +0,0 @@
-Listing Lists
-
-
-
-
- Title
-
-
-
-
-
-<%= for list <- @lists do %>
-
- <%= list.title %>
-
-
- <%= link "Show", to: Routes.list_path(@conn, :show, list) %>
- <%= link "Edit", to: Routes.list_path(@conn, :edit, list) %>
- <%= link "Delete", to: Routes.list_path(@conn, :delete, list), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New List", to: Routes.list_path(@conn, :new) %>
diff --git a/lib/app_web/templates/list/new.html.eex b/lib/app_web/templates/list/new.html.eex
deleted file mode 100644
index 42fae48..0000000
--- a/lib/app_web/templates/list/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New List
-
-<%= render "form.html", Map.put(assigns, :action, Routes.list_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.list_path(@conn, :index) %>
diff --git a/lib/app_web/templates/list/show.html.eex b/lib/app_web/templates/list/show.html.eex
deleted file mode 100644
index b3178eb..0000000
--- a/lib/app_web/templates/list/show.html.eex
+++ /dev/null
@@ -1,13 +0,0 @@
-Show List
-
-
-
-
- Title:
- <%= @list.title %>
-
-
-
-
-<%= link "Edit", to: Routes.list_path(@conn, :edit, @list) %>
-<%= link "Back", to: Routes.list_path(@conn, :index) %>
diff --git a/lib/app_web/templates/page/index.html.eex b/lib/app_web/templates/page/index.html.eex
deleted file mode 100644
index e996400..0000000
--- a/lib/app_web/templates/page/index.html.eex
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
- dwyl
- Unlock a new level of personal effectiveness .
-
-
-
-
-OR
-
- <%= form_for @changeset, Routes.page_path(@conn, :register), fn f -> %>
-
-<%= email_input f, :email, placeholder: "email address" %>
-
- <%= error_tag f, :email %>
-
-
-
- <%= password_input f, :password, placeholder: "password" %>
-
- <%= error_tag f, :password%>
-
-
-
- <%= submit "Login / Register", class: "pointer f6 link br1 ph3 pv2 mb2 dib white dwyl-bg-teal" %>
-
- <% end %>
-
diff --git a/lib/app_web/templates/person/edit.html.eex b/lib/app_web/templates/person/edit.html.eex
deleted file mode 100644
index bf7ba55..0000000
--- a/lib/app_web/templates/person/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit Person
-
-<%= render "form.html", Map.put(assigns, :action, Routes.person_path(@conn, :update, @person)) %>
-
-<%= link "Back", to: Routes.person_path(@conn, :index) %>
diff --git a/lib/app_web/templates/person/form.html.eex b/lib/app_web/templates/person/form.html.eex
deleted file mode 100644
index d9b6806..0000000
--- a/lib/app_web/templates/person/form.html.eex
+++ /dev/null
@@ -1,39 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :username %>
- <%= text_input f, :username %>
- <%= error_tag f, :username %>
-
- <%= label f, :username_hash %>
- <%= text_input f, :username_hash %>
- <%= error_tag f, :username_hash %>
-
- <%= label f, :email %>
- <%= text_input f, :email %>
- <%= error_tag f, :email %>
-
- <%= label f, :givenName %>
- <%= text_input f, :givenName %>
- <%= error_tag f, :givenName %>
-
- <%= label f, :familyName %>
- <%= text_input f, :familyName %>
- <%= error_tag f, :familyName %>
-
- <%= label f, :password_hash %>
- <%= text_input f, :password_hash %>
- <%= error_tag f, :password_hash %>
-
- <%= label f, :key_id %>
- <%= number_input f, :key_id %>
- <%= error_tag f, :key_id %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/person/index.html.eex b/lib/app_web/templates/person/index.html.eex
deleted file mode 100644
index 671e3ab..0000000
--- a/lib/app_web/templates/person/index.html.eex
+++ /dev/null
@@ -1,40 +0,0 @@
-Listing People
-
-
-
-
- Username
- Username hash
- Email
- Email hash
- Givenname
- Familyname
- Password hash
- Key
-
-
-
-
-
-<%= for person <- @people do %>
-
- <%= person.username %>
- <%= person.username_hash %>
- <%= person.email %>
- <%= person.email_hash %>
- <%= person.givenName %>
- <%= person.familyName %>
- <%= person.password_hash %>
- <%= person.key_id %>
-
-
- <%= link "Show", to: Routes.person_path(@conn, :show, person) %>
- <%= link "Edit", to: Routes.person_path(@conn, :edit, person) %>
- <%= link "Delete", to: Routes.person_path(@conn, :delete, person), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New Person", to: Routes.person_path(@conn, :new) %>
diff --git a/lib/app_web/templates/person/info.html.eex b/lib/app_web/templates/person/info.html.eex
deleted file mode 100644
index 551414c..0000000
--- a/lib/app_web/templates/person/info.html.eex
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
- Hello <%= @person.givenName %>!
-
- You are signed in
- with
-
- <%= @person.email %>
-
-
-
-
-<%= link "Capture", to: Routes.capture_path(@conn, :new) %>
\ No newline at end of file
diff --git a/lib/app_web/templates/person/new.html.eex b/lib/app_web/templates/person/new.html.eex
deleted file mode 100644
index 3f3617f..0000000
--- a/lib/app_web/templates/person/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New Person
-
-<%= render "form.html", Map.put(assigns, :action, Routes.person_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.person_path(@conn, :index) %>
diff --git a/lib/app_web/templates/person/show.html.eex b/lib/app_web/templates/person/show.html.eex
deleted file mode 100644
index 0fac7ac..0000000
--- a/lib/app_web/templates/person/show.html.eex
+++ /dev/null
@@ -1,48 +0,0 @@
-Show Person
-
-
-
-
- Username:
- <%= @person.username %>
-
-
-
- Username hash:
- <%= @person.username_hash %>
-
-
-
- Email:
- <%= @person.email %>
-
-
-
- Email hash:
- <%= @person.email_hash %>
-
-
-
- Givenname:
- <%= @person.givenName %>
-
-
-
- Familyname:
- <%= @person.familyName %>
-
-
-
- Password hash:
- <%= @person.password_hash %>
-
-
-
- Key:
- <%= @person.key_id %>
-
-
-
-
-<%= link "Edit", to: Routes.person_path(@conn, :edit, @person) %>
-<%= link "Back", to: Routes.person_path(@conn, :index) %>
diff --git a/lib/app_web/templates/status/edit.html.eex b/lib/app_web/templates/status/edit.html.eex
deleted file mode 100644
index 0efa349..0000000
--- a/lib/app_web/templates/status/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit Status
-
-<%= render "form.html", Map.put(assigns, :action, Routes.status_path(@conn, :update, @status)) %>
-
-<%= link "Back", to: Routes.status_path(@conn, :index) %>
diff --git a/lib/app_web/templates/status/form.html.eex b/lib/app_web/templates/status/form.html.eex
deleted file mode 100644
index 1c656c3..0000000
--- a/lib/app_web/templates/status/form.html.eex
+++ /dev/null
@@ -1,15 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :text %>
- <%= text_input f, :text %>
- <%= error_tag f, :text %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/status/index.html.eex b/lib/app_web/templates/status/index.html.eex
deleted file mode 100644
index fce3e6c..0000000
--- a/lib/app_web/templates/status/index.html.eex
+++ /dev/null
@@ -1,26 +0,0 @@
-Listing Status
-
-
-
-
- Text
-
-
-
-
-
-<%= for status <- @status do %>
-
- <%= status.text %>
-
-
- <%= link "Show", to: Routes.status_path(@conn, :show, status) %>
- <%= link "Edit", to: Routes.status_path(@conn, :edit, status) %>
- <%= link "Delete", to: Routes.status_path(@conn, :delete, status), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New Status", to: Routes.status_path(@conn, :new) %>
diff --git a/lib/app_web/templates/status/new.html.eex b/lib/app_web/templates/status/new.html.eex
deleted file mode 100644
index ea37b20..0000000
--- a/lib/app_web/templates/status/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New Status
-
-<%= render "form.html", Map.put(assigns, :action, Routes.status_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.status_path(@conn, :index) %>
diff --git a/lib/app_web/templates/status/show.html.eex b/lib/app_web/templates/status/show.html.eex
deleted file mode 100644
index da7c1df..0000000
--- a/lib/app_web/templates/status/show.html.eex
+++ /dev/null
@@ -1,13 +0,0 @@
-Show Status
-
-
-
-
- Text:
- <%= @status.text %>
-
-
-
-
-<%= link "Edit", to: Routes.status_path(@conn, :edit, @status) %>
-<%= link "Back", to: Routes.status_path(@conn, :index) %>
diff --git a/lib/app_web/templates/tag/edit.html.eex b/lib/app_web/templates/tag/edit.html.eex
deleted file mode 100644
index f2f4987..0000000
--- a/lib/app_web/templates/tag/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit Tag
-
-<%= render "form.html", Map.put(assigns, :action, Routes.tag_path(@conn, :update, @tag)) %>
-
-<%= link "Back", to: Routes.tag_path(@conn, :index) %>
diff --git a/lib/app_web/templates/tag/form.html.eex b/lib/app_web/templates/tag/form.html.eex
deleted file mode 100644
index 1c656c3..0000000
--- a/lib/app_web/templates/tag/form.html.eex
+++ /dev/null
@@ -1,15 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :text %>
- <%= text_input f, :text %>
- <%= error_tag f, :text %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/tag/index.html.eex b/lib/app_web/templates/tag/index.html.eex
deleted file mode 100644
index c5aadc3..0000000
--- a/lib/app_web/templates/tag/index.html.eex
+++ /dev/null
@@ -1,26 +0,0 @@
-Listing Tags
-
-
-
-
- Text
-
-
-
-
-
-<%= for tag <- @tags do %>
-
- <%= tag.text %>
-
-
- <%= link "Show", to: Routes.tag_path(@conn, :show, tag) %>
- <%= link "Edit", to: Routes.tag_path(@conn, :edit, tag) %>
- <%= link "Delete", to: Routes.tag_path(@conn, :delete, tag), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New Tag", to: Routes.tag_path(@conn, :new) %>
diff --git a/lib/app_web/templates/tag/new.html.eex b/lib/app_web/templates/tag/new.html.eex
deleted file mode 100644
index 51af2aa..0000000
--- a/lib/app_web/templates/tag/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New Tag
-
-<%= render "form.html", Map.put(assigns, :action, Routes.tag_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.tag_path(@conn, :index) %>
diff --git a/lib/app_web/templates/tag/show.html.eex b/lib/app_web/templates/tag/show.html.eex
deleted file mode 100644
index f6d587d..0000000
--- a/lib/app_web/templates/tag/show.html.eex
+++ /dev/null
@@ -1,13 +0,0 @@
-Show Tag
-
-
-
-
- Text:
- <%= @tag.text %>
-
-
-
-
-<%= link "Edit", to: Routes.tag_path(@conn, :edit, @tag) %>
-<%= link "Back", to: Routes.tag_path(@conn, :index) %>
diff --git a/lib/app_web/templates/timer/edit.html.eex b/lib/app_web/templates/timer/edit.html.eex
deleted file mode 100644
index ce1474d..0000000
--- a/lib/app_web/templates/timer/edit.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-Edit Timer
-
-<%= render "form.html", Map.put(assigns, :action, Routes.timer_path(@conn, :update, @timer)) %>
-
-<%= link "Back", to: Routes.timer_path(@conn, :index) %>
diff --git a/lib/app_web/templates/timer/form.html.eex b/lib/app_web/templates/timer/form.html.eex
deleted file mode 100644
index cd51fca..0000000
--- a/lib/app_web/templates/timer/form.html.eex
+++ /dev/null
@@ -1,19 +0,0 @@
-<%= form_for @changeset, @action, fn f -> %>
- <%= if @changeset.action do %>
-
-
Oops, something went wrong! Please check the errors below.
-
- <% end %>
-
- <%= label f, :start %>
- <%= datetime_select f, :start %>
- <%= error_tag f, :start %>
-
- <%= label f, :end %>
- <%= datetime_select f, :end %>
- <%= error_tag f, :end %>
-
-
- <%= submit "Save" %>
-
-<% end %>
diff --git a/lib/app_web/templates/timer/index.html.eex b/lib/app_web/templates/timer/index.html.eex
deleted file mode 100644
index 69e2dfb..0000000
--- a/lib/app_web/templates/timer/index.html.eex
+++ /dev/null
@@ -1,28 +0,0 @@
-Listing Timers
-
-
-
-
- Start
- End
-
-
-
-
-
-<%= for timer <- @timers do %>
-
- <%= timer.start %>
- <%= timer.end %>
-
-
- <%= link "Show", to: Routes.timer_path(@conn, :show, timer) %>
- <%= link "Edit", to: Routes.timer_path(@conn, :edit, timer) %>
- <%= link "Delete", to: Routes.timer_path(@conn, :delete, timer), method: :delete, data: [confirm: "Are you sure?"] %>
-
-
-<% end %>
-
-
-
-<%= link "New Timer", to: Routes.timer_path(@conn, :new) %>
diff --git a/lib/app_web/templates/timer/new.html.eex b/lib/app_web/templates/timer/new.html.eex
deleted file mode 100644
index 725c06c..0000000
--- a/lib/app_web/templates/timer/new.html.eex
+++ /dev/null
@@ -1,5 +0,0 @@
-New Timer
-
-<%= render "form.html", Map.put(assigns, :action, Routes.timer_path(@conn, :create)) %>
-
-<%= link "Back", to: Routes.timer_path(@conn, :index) %>
diff --git a/lib/app_web/templates/timer/show.html.eex b/lib/app_web/templates/timer/show.html.eex
deleted file mode 100644
index 70b20bc..0000000
--- a/lib/app_web/templates/timer/show.html.eex
+++ /dev/null
@@ -1,18 +0,0 @@
-Show Timer
-
-
-
-
- Start:
- <%= @timer.start %>
-
-
-
- End:
- <%= @timer.end %>
-
-
-
-
-<%= link "Edit", to: Routes.timer_path(@conn, :edit, @timer) %>
-<%= link "Back", to: Routes.timer_path(@conn, :index) %>
diff --git a/lib/app_web/views/capture_view.ex b/lib/app_web/views/capture_view.ex
deleted file mode 100644
index 6733f85..0000000
--- a/lib/app_web/views/capture_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.CaptureView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/categorise_view.ex b/lib/app_web/views/categorise_view.ex
deleted file mode 100644
index 22a8d42..0000000
--- a/lib/app_web/views/categorise_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.CategoriseView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/error_helpers.ex b/lib/app_web/views/error_helpers.ex
deleted file mode 100644
index 9f7ba73..0000000
--- a/lib/app_web/views/error_helpers.ex
+++ /dev/null
@@ -1,44 +0,0 @@
-defmodule AppWeb.ErrorHelpers do
- @moduledoc """
- Conveniences for translating and building error messages.
- """
-
- use Phoenix.HTML
-
- @doc """
- Generates tag for inlined form input errors.
- """
- def error_tag(form, field) do
- Enum.map(Keyword.get_values(form.errors, field), fn error ->
- content_tag(:span, translate_error(error), class: "help-block")
- end)
- end
-
- @doc """
- Translates an error message using gettext.
- """
- def translate_error({msg, opts}) do
- # When using gettext, we typically pass the strings we want
- # to translate as a static argument:
- #
- # # Translate "is invalid" in the "errors" domain
- # dgettext("errors", "is invalid")
- #
- # # Translate the number of files with plural rules
- # dngettext("errors", "1 file", "%{count} files", count)
- #
- # Because the error messages we show in our forms and APIs
- # are defined inside Ecto, we need to translate them dynamically.
- # This requires us to call the Gettext module passing our gettext
- # backend as first argument.
- #
- # Note we use the "errors" domain, which means translations
- # should be written to the errors.po file. The :count option is
- # set by Ecto and indicates we should also apply plural rules.
- if count = opts[:count] do
- Gettext.dngettext(AppWeb.Gettext, "errors", msg, msg, count, opts)
- else
- Gettext.dgettext(AppWeb.Gettext, "errors", msg, opts)
- end
- end
-end
diff --git a/lib/app_web/views/error_view.ex b/lib/app_web/views/error_view.ex
deleted file mode 100644
index a6651a5..0000000
--- a/lib/app_web/views/error_view.ex
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule AppWeb.ErrorView do
- use AppWeb, :view
-
- # If you want to customize a particular status code
- # for a certain format, you may uncomment below.
- # def render("500.html", _assigns) do
- # "Internal Server Error"
- # end
-
- # By default, Phoenix returns the status message from
- # the template name. For example, "404.html" becomes
- # "Not Found".
- def template_not_found(template, _assigns) do
- Phoenix.Controller.status_message_from_template(template)
- end
-end
diff --git a/lib/app_web/views/google_auth_view.ex b/lib/app_web/views/google_auth_view.ex
deleted file mode 100644
index c966fc0..0000000
--- a/lib/app_web/views/google_auth_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.GoogleAuthView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/item_view.ex b/lib/app_web/views/item_view.ex
deleted file mode 100644
index 84240e4..0000000
--- a/lib/app_web/views/item_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.ItemView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/layout_view.ex b/lib/app_web/views/layout_view.ex
deleted file mode 100644
index 80c818d..0000000
--- a/lib/app_web/views/layout_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.LayoutView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/list_view.ex b/lib/app_web/views/list_view.ex
deleted file mode 100644
index 89a80c2..0000000
--- a/lib/app_web/views/list_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.ListView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/page_view.ex b/lib/app_web/views/page_view.ex
deleted file mode 100644
index 53d7bb7..0000000
--- a/lib/app_web/views/page_view.ex
+++ /dev/null
@@ -1,7 +0,0 @@
-defmodule AppWeb.PageView do
- use AppWeb, :view
-
- def authenticated?(person) do
- Map.has_key?(person, :email) && String.length( person["email"] ) > 0
- end
-end
diff --git a/lib/app_web/views/person_view.ex b/lib/app_web/views/person_view.ex
deleted file mode 100644
index 1cec690..0000000
--- a/lib/app_web/views/person_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.PersonView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/status_view.ex b/lib/app_web/views/status_view.ex
deleted file mode 100644
index c7de3b1..0000000
--- a/lib/app_web/views/status_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.StatusView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/tag_view.ex b/lib/app_web/views/tag_view.ex
deleted file mode 100644
index d238df9..0000000
--- a/lib/app_web/views/tag_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.TagView do
- use AppWeb, :view
-end
diff --git a/lib/app_web/views/timer_view.ex b/lib/app_web/views/timer_view.ex
deleted file mode 100644
index 25b22f4..0000000
--- a/lib/app_web/views/timer_view.ex
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.TimerView do
- use AppWeb, :view
-end
diff --git a/lib/elixir_auth_google/mock.ex b/lib/elixir_auth_google/mock.ex
deleted file mode 100644
index f61f602..0000000
--- a/lib/elixir_auth_google/mock.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule App.ElixirAuthGoogle.Mock do
- def get_token(_code, _conn) do
- {:ok, %{:access_token => "token"}}
- end
-
- def get_user_profile(_token) do
- {:ok,
- %{
- email: "nelson@gmail.com",
- email_verified: true,
- family_name: "Correia",
- given_name: "Nelson",
- locale: "en",
- name: "Nelson Correia",
- picture: "https://lh3.googleusercontent.com/a-/AAuE7mApnYb260YC1JY7a",
- sub: "940732358705212133793"
- }
- }
- end
-end
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..5e9ddeb
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,16 @@
+{
+ "short_name": "DWYL App",
+ "name": "Spike using progressive web app",
+ "decription": "The dwyl application",
+ "icons": [
+ {
+ "src": "/elm-pwa-example/assets/images/dwyl.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "/elm-pwa-example/",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+ }
\ No newline at end of file
diff --git a/mix.exs b/mix.exs
deleted file mode 100644
index 3cc2d0d..0000000
--- a/mix.exs
+++ /dev/null
@@ -1,79 +0,0 @@
-defmodule App.MixProject do
- use Mix.Project
-
- def project do
- [
- app: :app,
- version: "0.1.0",
- elixir: "~> 1.9",
- elixirc_paths: elixirc_paths(Mix.env()),
- compilers: [:phoenix, :gettext] ++ Mix.compilers(),
- start_permanent: Mix.env() == :prod,
- aliases: aliases(),
- deps: deps(),
-
- test_coverage: [tool: ExCoveralls],
- preferred_cli_env: [
- coveralls: :test,
- "coveralls.json": :test,
- "coveralls.html": :test
- ]
- ]
- end
-
- # Configuration for the OTP application.
- #
- # Type `mix help compile.app` for more information.
- def application do
- [
- mod: {App.Application, []},
- extra_applications: [:logger, :runtime_tools]
- ]
- end
-
- # Specifies which paths to compile per environment.
- defp elixirc_paths(:test), do: ["lib", "test/support"]
- defp elixirc_paths(_), do: ["lib"]
-
- # Specifies your project dependencies.
- #
- # Type `mix help deps` for examples and options.
- defp deps do
- [
- {:phoenix, "~> 1.4.10"},
- {:phoenix_pubsub, "~> 1.1"},
- {:phoenix_ecto, "~> 4.0"},
- {:ecto_sql, "~> 3.1"},
- {:postgrex, ">= 0.0.0"},
- {:phoenix_html, "~> 2.11"},
- {:phoenix_live_reload, "~> 1.2", only: :dev},
- {:gettext, "~> 0.11"},
- {:jason, "~> 1.0"},
- {:plug_cowboy, "~> 2.0"},
- {:elixir_auth_google, "~> 1.0.2" },
- {:fields, "~> 2.1.0"},
-
- # create docs on localhost by running "mix docs"
- {:ex_doc, "~> 0.21", only: :dev, runtime: false},
- # track test coverage
- {:excoveralls, "~> 0.12.1", only: [:test, :dev]},
- # git pre-commit hook runs tests before allowing commits
- {:pre_commit, "~> 0.3.4"},
- {:credo, "~> 1.1.0", only: [:dev, :test], runtime: false}
- ]
- end
-
- # Aliases are shortcuts or tasks specific to the current project.
- # For example, to create, migrate and run the seeds file at once:
- #
- # $ mix ecto.setup
- #
- # See the documentation for `Mix` for more info on aliases.
- defp aliases do
- [
- "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
- "ecto.reset": ["ecto.drop", "ecto.setup"],
- test: ["ecto.create --quiet", "ecto.migrate", "run priv/repo/seeds.exs", "test"]
- ]
- end
-end
diff --git a/mix.lock b/mix.lock
deleted file mode 100644
index 09cefbb..0000000
--- a/mix.lock
+++ /dev/null
@@ -1,50 +0,0 @@
-%{
- "argon2_elixir": {:hex, :argon2_elixir, "2.1.2", "c276b960f0b550a7613a9bebf8e14645ca5eb71a34a1bf0f896fe3511966b051", [:make, :mix], [{:comeonin, "~> 5.1", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
- "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
- "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
- "comeonin": {:hex, :comeonin, "5.1.3", "4c9880ed348cc0330c74086b4383ffb0b5a599aa603416497b7374c168cae340", [:mix], [], "hexpm"},
- "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
- "cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
- "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"},
- "credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
- "db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
- "decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
- "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
- "ecto": {:hex, :ecto, "3.2.5", "76c864b77948a479e18e69cc1d0f0f4ee7cced1148ffe6a093ff91eba644f0b5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
- "ecto_sql": {:hex, :ecto_sql, "3.2.2", "d10845bc147b9f61ef485cbf0973c0a337237199bd9bd30dd9542db00aadc26b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0 or ~> 0.3.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
- "elixir_auth_google": {:hex, :elixir_auth_google, "1.0.2", "46a1884d14ba2eb2ab92c33c24bf6366e4c610757c5bea8f95e674ff3ae2bd6c", [:mix], [{:httpoison, "~> 1.6", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 4.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
- "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm"},
- "ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
- "excoveralls": {:hex, :excoveralls, "0.12.1", "a553c59f6850d0aff3770e4729515762ba7c8e41eedde03208182a8dc9d0ce07", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
- "fields": {:hex, :fields, "2.1.0", "1dc42be9c7b518fde38e37c0f2ce7ea97f9b23c21fd661a11fc92da99e8d7f01", [:mix], [{:argon2_elixir, "~> 2.1.2", [hex: :argon2_elixir, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:html_sanitize_ex, "~> 1.3", [hex: :html_sanitize_ex, repo: "hexpm", optional: false]}], "hexpm"},
- "file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
- "gettext": {:hex, :gettext, "0.17.1", "8baab33482df4907b3eae22f719da492cee3981a26e649b9c2be1c0192616962", [:mix], [], "hexpm"},
- "hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
- "html_sanitize_ex": {:hex, :html_sanitize_ex, "1.4.0", "0310d27d7bafb662f30bff22ec732a72414799c83eaf44239781fd23b96216c0", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
- "httpoison": {:hex, :httpoison, "1.6.2", "ace7c8d3a361cebccbed19c283c349b3d26991eff73a1eaaa8abae2e3c8089b6", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
- "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
- "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
- "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
- "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
- "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
- "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
- "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
- "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
- "nimble_parsec": {:hex, :nimble_parsec, "0.5.2", "1d71150d5293d703a9c38d4329da57d3935faed2031d64bc19e77b654ef2d177", [:mix], [], "hexpm"},
- "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
- "phoenix": {:hex, :phoenix, "1.4.11", "d112c862f6959f98e6e915c3b76c7a87ca3efd075850c8daa7c3c7a609014b0d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
- "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
- "phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
- "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
- "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
- "plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
- "plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
- "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
- "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"},
- "postgrex": {:hex, :postgrex, "0.15.2", "052dad08d934863d1a4dcbd48ae7fc2af21a8535f556121e91b13b2884b0965a", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
- "pre_commit": {:hex, :pre_commit, "0.3.4", "e2850f80be8090d50ad8019ef2426039307ff5dfbe70c736ad0d4d401facf304", [:mix], [], "hexpm"},
- "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
- "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
- "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm"},
- "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
-}
diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po
deleted file mode 100644
index a589998..0000000
--- a/priv/gettext/en/LC_MESSAGES/errors.po
+++ /dev/null
@@ -1,97 +0,0 @@
-## `msgid`s in this file come from POT (.pot) files.
-##
-## Do not add, change, or remove `msgid`s manually here as
-## they're tied to the ones in the corresponding POT file
-## (with the same domain).
-##
-## Use `mix gettext.extract --merge` or `mix gettext.merge`
-## to merge POT files into PO files.
-msgid ""
-msgstr ""
-"Language: en\n"
-
-## From Ecto.Changeset.cast/4
-msgid "can't be blank"
-msgstr ""
-
-## From Ecto.Changeset.unique_constraint/3
-msgid "has already been taken"
-msgstr ""
-
-## From Ecto.Changeset.put_change/3
-msgid "is invalid"
-msgstr ""
-
-## From Ecto.Changeset.validate_acceptance/3
-msgid "must be accepted"
-msgstr ""
-
-## From Ecto.Changeset.validate_format/3
-msgid "has invalid format"
-msgstr ""
-
-## From Ecto.Changeset.validate_subset/3
-msgid "has an invalid entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_exclusion/3
-msgid "is reserved"
-msgstr ""
-
-## From Ecto.Changeset.validate_confirmation/3
-msgid "does not match confirmation"
-msgstr ""
-
-## From Ecto.Changeset.no_assoc_constraint/3
-msgid "is still associated with this entry"
-msgstr ""
-
-msgid "are still associated with this entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_length/3
-msgid "should be %{count} character(s)"
-msgid_plural "should be %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have %{count} item(s)"
-msgid_plural "should have %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at least %{count} character(s)"
-msgid_plural "should be at least %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at least %{count} item(s)"
-msgid_plural "should have at least %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at most %{count} character(s)"
-msgid_plural "should be at most %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at most %{count} item(s)"
-msgid_plural "should have at most %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-## From Ecto.Changeset.validate_number/3
-msgid "must be less than %{number}"
-msgstr ""
-
-msgid "must be greater than %{number}"
-msgstr ""
-
-msgid "must be less than or equal to %{number}"
-msgstr ""
-
-msgid "must be greater than or equal to %{number}"
-msgstr ""
-
-msgid "must be equal to %{number}"
-msgstr ""
diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot
deleted file mode 100644
index 39a220b..0000000
--- a/priv/gettext/errors.pot
+++ /dev/null
@@ -1,95 +0,0 @@
-## This is a PO Template file.
-##
-## `msgid`s here are often extracted from source code.
-## Add new translations manually only if they're dynamic
-## translations that can't be statically extracted.
-##
-## Run `mix gettext.extract` to bring this file up to
-## date. Leave `msgstr`s empty as changing them here has no
-## effect: edit them in PO (`.po`) files instead.
-
-## From Ecto.Changeset.cast/4
-msgid "can't be blank"
-msgstr ""
-
-## From Ecto.Changeset.unique_constraint/3
-msgid "has already been taken"
-msgstr ""
-
-## From Ecto.Changeset.put_change/3
-msgid "is invalid"
-msgstr ""
-
-## From Ecto.Changeset.validate_acceptance/3
-msgid "must be accepted"
-msgstr ""
-
-## From Ecto.Changeset.validate_format/3
-msgid "has invalid format"
-msgstr ""
-
-## From Ecto.Changeset.validate_subset/3
-msgid "has an invalid entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_exclusion/3
-msgid "is reserved"
-msgstr ""
-
-## From Ecto.Changeset.validate_confirmation/3
-msgid "does not match confirmation"
-msgstr ""
-
-## From Ecto.Changeset.no_assoc_constraint/3
-msgid "is still associated with this entry"
-msgstr ""
-
-msgid "are still associated with this entry"
-msgstr ""
-
-## From Ecto.Changeset.validate_length/3
-msgid "should be %{count} character(s)"
-msgid_plural "should be %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have %{count} item(s)"
-msgid_plural "should have %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at least %{count} character(s)"
-msgid_plural "should be at least %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at least %{count} item(s)"
-msgid_plural "should have at least %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should be at most %{count} character(s)"
-msgid_plural "should be at most %{count} character(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "should have at most %{count} item(s)"
-msgid_plural "should have at most %{count} item(s)"
-msgstr[0] ""
-msgstr[1] ""
-
-## From Ecto.Changeset.validate_number/3
-msgid "must be less than %{number}"
-msgstr ""
-
-msgid "must be greater than %{number}"
-msgstr ""
-
-msgid "must be less than or equal to %{number}"
-msgstr ""
-
-msgid "must be greater than or equal to %{number}"
-msgstr ""
-
-msgid "must be equal to %{number}"
-msgstr ""
diff --git a/priv/repo/migrations/.formatter.exs b/priv/repo/migrations/.formatter.exs
deleted file mode 100644
index 49f9151..0000000
--- a/priv/repo/migrations/.formatter.exs
+++ /dev/null
@@ -1,4 +0,0 @@
-[
- import_deps: [:ecto_sql],
- inputs: ["*.exs"]
-]
diff --git a/priv/repo/migrations/20191113100513_create_tags.exs b/priv/repo/migrations/20191113100513_create_tags.exs
deleted file mode 100644
index 89fd9b1..0000000
--- a/priv/repo/migrations/20191113100513_create_tags.exs
+++ /dev/null
@@ -1,12 +0,0 @@
-defmodule App.Repo.Migrations.CreateTags do
- use Ecto.Migration
-
- def change do
- create table(:tags) do
- add :text, :string
-
- timestamps()
- end
-
- end
-end
diff --git a/priv/repo/migrations/20191113100912_create_status.exs b/priv/repo/migrations/20191113100912_create_status.exs
deleted file mode 100644
index ab65021..0000000
--- a/priv/repo/migrations/20191113100912_create_status.exs
+++ /dev/null
@@ -1,12 +0,0 @@
-defmodule App.Repo.Migrations.CreateStatus do
- use Ecto.Migration
-
- def change do
- create table(:status) do
- add :text, :string
-
- timestamps()
- end
-
- end
-end
diff --git a/priv/repo/migrations/20191113100920_create_people.exs b/priv/repo/migrations/20191113100920_create_people.exs
deleted file mode 100644
index 1992fc6..0000000
--- a/priv/repo/migrations/20191113100920_create_people.exs
+++ /dev/null
@@ -1,23 +0,0 @@
-defmodule App.Repo.Migrations.CreatePeople do
- use Ecto.Migration
-
- def change do
- create table(:people) do
- add :username, :binary
- add :username_hash, :binary
- add :email, :binary
- add :email_hash, :binary
- add :givenName, :binary
- add :familyName, :binary
- add :password_hash, :binary
- add :key_id, :integer
- add :status, references(:status, on_delete: :nothing)
- add :tag, references(:tags, on_delete: :nothing)
-
- timestamps()
- end
-
- create index(:people, [:status])
- create index(:people, [:tag])
- end
-end
diff --git a/priv/repo/migrations/20191113100927_create_items.exs b/priv/repo/migrations/20191113100927_create_items.exs
deleted file mode 100644
index 2fe4754..0000000
--- a/priv/repo/migrations/20191113100927_create_items.exs
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule App.Repo.Migrations.CreateItems do
- use Ecto.Migration
-
- def change do
- create table(:items) do
- add :text, :string
- add :person_id, references(:people, on_delete: :nothing)
- add :status, references(:status, on_delete: :nothing)
-
- timestamps()
- end
-
- create index(:items, [:person_id])
- create index(:items, [:status])
- end
-end
diff --git a/priv/repo/migrations/20191113100933_create_lists.exs b/priv/repo/migrations/20191113100933_create_lists.exs
deleted file mode 100644
index 68706f0..0000000
--- a/priv/repo/migrations/20191113100933_create_lists.exs
+++ /dev/null
@@ -1,18 +0,0 @@
-defmodule App.Repo.Migrations.CreateLists do
- use Ecto.Migration
-
- def change do
- create table(:lists) do
- add :title, :string
- add :person_id, references(:people, on_delete: :nothing)
- add :status, references(:status, on_delete: :nothing)
- add :tag, references(:tags, on_delete: :nothing)
-
- timestamps()
- end
-
- create index(:lists, [:person_id])
- create index(:lists, [:status])
- create index(:lists, [:tag])
- end
-end
diff --git a/priv/repo/migrations/20191113100938_create_timers.exs b/priv/repo/migrations/20191113100938_create_timers.exs
deleted file mode 100644
index 63101df..0000000
--- a/priv/repo/migrations/20191113100938_create_timers.exs
+++ /dev/null
@@ -1,17 +0,0 @@
-defmodule App.Repo.Migrations.CreateTimers do
- use Ecto.Migration
-
- def change do
- create table(:timers) do
- add :start, :naive_datetime
- add :end, :naive_datetime
- add :item_id, references(:items, on_delete: :nothing)
- add :person_id, references(:people, on_delete: :nothing)
-
- timestamps()
- end
-
- create index(:timers, [:item_id])
- create index(:timers, [:person_id])
- end
-end
diff --git a/priv/repo/migrations/20191113114340_add_person_id_to_tag.exs b/priv/repo/migrations/20191113114340_add_person_id_to_tag.exs
deleted file mode 100644
index 27c7290..0000000
--- a/priv/repo/migrations/20191113114340_add_person_id_to_tag.exs
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule App.Repo.Migrations.AddPersonIdToTag do
- use Ecto.Migration
-
- def change do
- alter table(:tags) do
- add :person_id, references(:people, on_delete: :nothing)
- end
- end
-end
diff --git a/priv/repo/migrations/20191113141229_add_person_id_to_status.exs b/priv/repo/migrations/20191113141229_add_person_id_to_status.exs
deleted file mode 100644
index 31427a9..0000000
--- a/priv/repo/migrations/20191113141229_add_person_id_to_status.exs
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule App.Repo.Migrations.AddPersonIdToStatus do
- use Ecto.Migration
-
- def change do
- alter table(:status) do
- add :person_id, references(:people, on_delete: :nothing)
- end
- end
-end
diff --git a/priv/repo/migrations/20191113144142_create_list_items_association.exs b/priv/repo/migrations/20191113144142_create_list_items_association.exs
deleted file mode 100644
index f03555a..0000000
--- a/priv/repo/migrations/20191113144142_create_list_items_association.exs
+++ /dev/null
@@ -1,14 +0,0 @@
-defmodule App.Repo.Migrations.CreateListItemsAssociation do
- use Ecto.Migration
-
- def change do
- create table(:list_items) do
- add :item_id, references(:items)
- add :list_id, references(:lists)
-
- timestamps()
- end
-
- create unique_index(:list_items, [:item_id, :list_id])
- end
-end
diff --git a/priv/repo/migrations/20191113195733_create_item_tags_association.exs b/priv/repo/migrations/20191113195733_create_item_tags_association.exs
deleted file mode 100644
index 6ddffd1..0000000
--- a/priv/repo/migrations/20191113195733_create_item_tags_association.exs
+++ /dev/null
@@ -1,14 +0,0 @@
-defmodule App.Repo.Migrations.CreateItemTagsAssociation do
- use Ecto.Migration
-
- def change do
- create table(:item_tags) do
- add :item_id, references(:items)
- add :tag_id, references(:tags)
-
- timestamps()
- end
-
- create unique_index(:item_tags, [:item_id, :tag_id])
- end
-end
diff --git a/priv/repo/migrations/20191115144039_update_item_text_type.exs b/priv/repo/migrations/20191115144039_update_item_text_type.exs
deleted file mode 100644
index fe40ff4..0000000
--- a/priv/repo/migrations/20191115144039_update_item_text_type.exs
+++ /dev/null
@@ -1,9 +0,0 @@
-defmodule App.Repo.Migrations.UpdateItemTextType do
- use Ecto.Migration
-
- def change do
- alter table(:items) do
- modify :text, :text
- end
- end
-end
diff --git a/priv/repo/migrations/20191126144556_create_session_table.exs b/priv/repo/migrations/20191126144556_create_session_table.exs
deleted file mode 100644
index 7705c9d..0000000
--- a/priv/repo/migrations/20191126144556_create_session_table.exs
+++ /dev/null
@@ -1,15 +0,0 @@
-defmodule App.Repo.Migrations.CreateSessionTable do
- use Ecto.Migration
-
- def change do
- create table(:sessions) do
- add :auth_token, :binary
- add :refresh_token, :binary
- add :key_id, :integer
-
- # keep sessions when user is deleted
- add :person_id, references(:people, on_delete: :nothing)
- timestamps()
- end
- end
-end
diff --git a/priv/repo/migrations/20191130210036_add_picture_locale_to_people.exs b/priv/repo/migrations/20191130210036_add_picture_locale_to_people.exs
deleted file mode 100644
index e0cddd6..0000000
--- a/priv/repo/migrations/20191130210036_add_picture_locale_to_people.exs
+++ /dev/null
@@ -1,10 +0,0 @@
-defmodule App.Repo.Migrations.AddPictureLocaleToPeople do
- use Ecto.Migration
-
- def change do
- alter table(:people) do
- add :picture, :binary
- add :locale, :string, default: "en"
- end
- end
-end
diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs
deleted file mode 100644
index d448b9d..0000000
--- a/priv/repo/seeds.exs
+++ /dev/null
@@ -1,2 +0,0 @@
-App.Ctx.create_status(%{text: "unverified"})
-App.Ctx.create_status(%{text: "verified"})
diff --git a/service_worker.js b/service_worker.js
new file mode 100644
index 0000000..32693c7
--- /dev/null
+++ b/service_worker.js
@@ -0,0 +1,24 @@
+self.addEventListener('install', function (e) {
+ e.waitUntil(
+ caches.open('dwylapp').then(function (cache) {
+ return cache.addAll([
+ '/elm-pwa-example/',
+ '/elm-pwa-example/manifest.json',
+ '/elm-pwa-example/elm.js',
+ '/elm-pwa-example/assets/images/dwyl.png',
+ '/elm-pwa-example/assets/images/signal_wifi_off.svg',
+ '/elm-pwa-example/assets/css/tachyons.css',
+ '/elm-pwa-example/assets/css/app.css',
+ ]);
+ })
+ );
+});
+
+self.addEventListener('fetch', function (event) {
+ console.log(event.request.url);
+ event.respondWith(
+ caches.match(event.request).then(function (response) {
+ return response || fetch(event.request);
+ })
+ );
+});
diff --git a/src/Main.elm b/src/Main.elm
new file mode 100644
index 0000000..7334658
--- /dev/null
+++ b/src/Main.elm
@@ -0,0 +1,159 @@
+port module Main exposing (main)
+
+import Browser
+import Browser.Navigation as Nav
+import Html exposing (..)
+import Html.Attributes exposing (..)
+import Html.Events exposing (onClick, onInput)
+import Http
+import Json.Decode as JD
+import Json.Encode as JE
+import Url
+
+
+
+-- MAIN
+
+
+main : Program () Model Msg
+main =
+ Browser.application
+ { init = init
+ , view = view
+ , update = update
+ , subscriptions = subscriptions
+ , onUrlChange = UrlChanged
+ , onUrlRequest = LinkClicked
+ }
+
+
+
+-- MODEL
+
+
+type alias Model =
+ { key : Nav.Key
+ , url : Url.Url
+ , capture : String
+ , message : String
+ , online : Bool
+ }
+
+
+init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
+init flags url key =
+ ( Model key url "" "" True, Cmd.none )
+
+
+
+-- UPDATE
+
+
+type Msg
+ = LinkClicked Browser.UrlRequest
+ | UrlChanged Url.Url
+ | Capture String
+ | CreateCapture
+ | SaveCaptureResult (Result Http.Error String)
+ | Online Bool
+
+
+update : Msg -> Model -> ( Model, Cmd Msg )
+update msg model =
+ case msg of
+ LinkClicked urlRequest ->
+ case urlRequest of
+ Browser.Internal url ->
+ ( model, Nav.pushUrl model.key (Url.toString url) )
+
+ Browser.External href ->
+ ( model, Nav.load href )
+
+ UrlChanged url ->
+ ( { model | url = url }
+ , Cmd.none
+ )
+
+ Capture text ->
+ ( { model | capture = text }, Cmd.none )
+
+ CreateCapture ->
+ ( model, saveCapture model.capture )
+
+ SaveCaptureResult (Ok response) ->
+ ( { model | capture = "", message = "Capture saved" }, Cmd.none )
+
+ SaveCaptureResult (Err e) ->
+ ( { model | message = "The capture couldn't be saved" }, Cmd.none )
+
+ Online status ->
+ ({model | online = status}, Cmd.none)
+
+
+
+-- SUBSCRIPTIONS
+
+port online : (Bool -> msg) -> Sub msg
+
+subscriptions : Model -> Sub Msg
+subscriptions _ =
+ Sub.batch [online Online]
+
+
+
+-- VIEW
+
+
+view : Model -> Browser.Document Msg
+view model =
+ { title = "DWYL App"
+ , body =
+ [ main_ [ class "pa2" ]
+ [ text model.message
+ , onlineView model.online
+ , h1 [ class "tc " ] [ text "Capture" ]
+ , div [ class "h-75" ]
+ [ textarea
+ [ onInput Capture
+ , value model.capture
+ , class "db mb2 center w-100 w-60-l h-100 resize-none"
+ , placeholder "write down everything that is on your mind"
+ ]
+ []
+ , div [ class "tc" ]
+ [ button [ class "bg-near-white bn", onClick CreateCapture ]
+ [ img [ class "pointer tc center", src "/elm-pwa-example/assets/images/submit.png", alt "capture" ] []
+ ]
+ ]
+ ]
+ ]
+ ]
+ }
+
+onlineView : Bool -> Html Msg
+onlineView onlineStatus =
+ div [classList [("dn", onlineStatus)]] [
+ img [src "/elm-pwa-example/assets/images/signal_wifi_off.svg", alt "offline icon"] []
+ ]
+
+
+-- Capture
+
+
+saveCapture : String -> Cmd Msg
+saveCapture capture =
+ Http.post
+ { url = "https://dwylapp.herokuapp.com/api/captures/create"
+ , body = Http.jsonBody (captureEncode capture)
+ , expect = Http.expectJson SaveCaptureResult captureDecoder
+ }
+
+
+captureEncode : String -> JE.Value
+captureEncode capture =
+ JE.object [ ( "text", JE.string capture ) ]
+
+
+captureDecoder : JD.Decoder String
+captureDecoder =
+ JD.field "text" JD.string
diff --git a/test/app/ctx_test.exs b/test/app/ctx_test.exs
deleted file mode 100644
index 7255a04..0000000
--- a/test/app/ctx_test.exs
+++ /dev/null
@@ -1,358 +0,0 @@
-defmodule App.CtxTest do
- use App.DataCase
-
- alias App.Ctx
-
- describe "tags" do
- alias App.Ctx.Tag
-
- @valid_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
- def tag_fixture(attrs \\ %{}) do
- {:ok, tag} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_tag()
-
- tag
- end
-
- test "list_tags/0 returns all tags" do
- tag = tag_fixture()
- assert Ctx.list_tags() == [tag]
- end
-
- test "get_tag!/1 returns the tag with given id" do
- tag = tag_fixture()
- assert Ctx.get_tag!(tag.id) == tag
- end
-
- test "create_tag/1 with valid data creates a tag" do
- assert {:ok, %Tag{} = tag} = Ctx.create_tag(@valid_attrs)
- assert tag.text == "some text"
- end
-
- test "create_tag/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_tag(@invalid_attrs)
- end
-
- test "update_tag/2 with valid data updates the tag" do
- tag = tag_fixture()
- assert {:ok, %Tag{} = tag} = Ctx.update_tag(tag, @update_attrs)
- assert tag.text == "some updated text"
- end
-
- test "update_tag/2 with invalid data returns error changeset" do
- tag = tag_fixture()
- assert {:error, %Ecto.Changeset{}} = Ctx.update_tag(tag, @invalid_attrs)
- assert tag == Ctx.get_tag!(tag.id)
- end
-
- test "delete_tag/1 deletes the tag" do
- tag = tag_fixture()
- assert {:ok, %Tag{}} = Ctx.delete_tag(tag)
- assert_raise Ecto.NoResultsError, fn -> Ctx.get_tag!(tag.id) end
- end
-
- test "change_tag/1 returns a tag changeset" do
- tag = tag_fixture()
- assert %Ecto.Changeset{} = Ctx.change_tag(tag)
- end
- end
-
- describe "status" do
- alias App.Ctx.Status
-
- @valid_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
- def status_fixture(attrs \\ %{}) do
- {:ok, status} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_status()
-
- status
- end
-
- test "list_status/0 returns all status" do
- status_fixture()
- assert Enum.count(Ctx.list_status()) > 1
- end
-
- test "get_status!/1 returns the status with given id" do
- status = status_fixture()
- assert Ctx.get_status!(status.id) == status
- end
-
- test "create_status/1 with valid data creates a status" do
- assert {:ok, %Status{} = status} = Ctx.create_status(@valid_attrs)
- assert status.text == "some text"
- end
-
- test "create_status/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_status(@invalid_attrs)
- end
-
- test "update_status/2 with valid data updates the status" do
- status = status_fixture()
- assert {:ok, %Status{} = status} = Ctx.update_status(status, @update_attrs)
- assert status.text == "some updated text"
- end
-
- test "update_status/2 with invalid data returns error changeset" do
- status = status_fixture()
- assert {:error, %Ecto.Changeset{}} = Ctx.update_status(status, @invalid_attrs)
- assert status == Ctx.get_status!(status.id)
- end
-
- test "delete_status/1 deletes the status" do
- status = status_fixture()
- assert {:ok, %Status{}} = Ctx.delete_status(status)
- assert_raise Ecto.NoResultsError, fn -> Ctx.get_status!(status.id) end
- end
-
- test "change_status/1 returns a status changeset" do
- status = status_fixture()
- assert %Ecto.Changeset{} = Ctx.change_status(status)
- end
- end
-
- describe "people" do
- alias App.Ctx.Person
- @valid_attrs %{email: "a@b.com", email_hash: "some email_hash", familyName: "some familyName", givenName: "some givenName", key_id: 42, password_hash: "some password_hash", username: "some username", username_hash: "some username_hash", locale: "en", picture: "https://imgur.com/a/DFXNawx"}
- @update_attrs %{email: "c@d.net", email_hash: "some updated email_hash", familyName: "some updated familyName", givenName: "some updated givenName", key_id: 43, password_hash: "some updated password_hash", username: "updated username", username_hash: "updated username_hash"}
- @invalid_attrs %{email: nil, email_hash: nil, familyName: nil, givenName: nil, key_id: nil, password_hash: nil, username: nil, username_hash: nil}
-
- def person_fixture(attrs \\ %{}) do
- {:ok, person} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_person()
- person
- end
-
- test "list_people/0 returns all people" do
- person_fixture()
- assert Enum.count(Ctx.list_people()) >= 1
- end
-
- test "get_person!/1 returns the person with given id" do
- person_data = person_fixture()
- person = Ctx.get_person!(person_data.id)
-
- assert person_data.email == person.email
- end
-
- test "create_person/1 with valid data creates a person" do
- assert {:ok, %Person{} = person} = Ctx.create_person(@valid_attrs)
- assert person.email == "a@b.com"
- # <<116, 223, 252, 249, 57, 13, 89, 186, 199, 10, 177, 236, 117, 117, 76, 147,
- # 109, 87, 187, 126, 168, 1, 63, 236, 134, 67, 92, 136, 136, 224, 45, 65>>
- assert person.familyName == "some familyName"
- assert person.givenName == "some givenName"
- assert person.key_id == 42
- assert person.password_hash == "some password_hash"
- assert person.username == "some username"
- end
-
- test "create_person/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_person(@invalid_attrs)
- end
-
- test "update_person/2 with valid data updates the person" do
- person = person_fixture()
- assert {:ok, %Person{} = person} = Ctx.update_person(person, @update_attrs)
- assert person.email == "c@d.net"
- assert person.familyName == "some updated familyName"
- assert person.givenName == "some updated givenName"
- assert person.key_id == 43
- assert person.password_hash == "some updated password_hash"
- end
-
- test "update_person/2 with invalid data returns error changeset" do
- person = person_fixture()
- assert {:error, %Ecto.Changeset{}} = Ctx.update_person(person, @invalid_attrs)
- person_data = Ctx.get_person!(person.id)
-
- assert person.id == person_data.id
- end
-
- test "delete_person/1 deletes the person" do
- person = person_fixture()
- assert {:ok, %Person{}} = Ctx.delete_person(person)
- assert_raise Ecto.NoResultsError, fn -> Ctx.get_person!(person.id) end
- end
-
- test "change_person/1 returns a person changeset" do
- person = person_fixture()
- assert %Ecto.Changeset{} = Ctx.change_person(person)
- end
- end
-
- describe "items" do
- alias App.Ctx.{Item, List}
-
- @valid_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
-
- def item_fixture(attrs \\ %{}) do
- {:ok, item} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_item()
-
- item
- end
-
- test "get_item!/1 returns the item with given id" do
- item = item_fixture(@valid_attrs)
- assert Ctx.get_item!(item.id) == item
- end
-
- test "create_item/1 with valid data creates a item" do
- assert {:ok, %Item{} = item} = Ctx.create_item(@valid_attrs)
- assert item.text == "some text"
- end
-
- test "create_item/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_item(@invalid_attrs)
- end
-
- test "update_item/2 with valid data updates the item" do
- item = item_fixture()
- assert {:ok, %Item{} = item} = Ctx.update_item(item, @update_attrs)
- assert item.text == "some updated text"
- end
-
- test "change_item/1 returns a item changeset" do
- item = item_fixture()
- assert %Ecto.Changeset{} = Ctx.change_item(item)
- end
- end
-
- describe "lists" do
- alias App.Ctx.List
-
- @valid_attrs %{title: "some title"}
- @update_attrs %{title: "some updated title"}
- @invalid_attrs %{title: nil}
-
- def list_fixture(attrs \\ %{}) do
- {:ok, list} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_list()
-
- list
- end
-
- test "list_lists/0 returns all lists" do
- list = list_fixture()
- assert Ctx.list_lists() == [list]
- end
-
- test "get_list!/1 returns the list with given id" do
- list = list_fixture()
- assert Ctx.get_list!(list.id) == list
- end
-
- test "create_list/1 with valid data creates a list" do
- assert {:ok, %List{} = list} = Ctx.create_list(@valid_attrs)
- assert list.title == "some title"
- end
-
- test "create_list/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_list(@invalid_attrs)
- end
-
- test "update_list/2 with valid data updates the list" do
- list = list_fixture()
- assert {:ok, %List{} = list} = Ctx.update_list(list, @update_attrs)
- assert list.title == "some updated title"
- end
-
- test "update_list/2 with invalid data returns error changeset" do
- list = list_fixture()
- assert {:error, %Ecto.Changeset{}} = Ctx.update_list(list, @invalid_attrs)
- assert list == Ctx.get_list!(list.id)
- end
-
- test "delete_list/1 deletes the list" do
- list = list_fixture()
- assert {:ok, %List{}} = Ctx.delete_list(list)
- assert_raise Ecto.NoResultsError, fn -> Ctx.get_list!(list.id) end
- end
-
- test "change_list/1 returns a list changeset" do
- list = list_fixture()
- assert %Ecto.Changeset{} = Ctx.change_list(list)
- end
- end
-
- describe "timers" do
- alias App.Ctx.Timer
-
- @valid_attrs %{end: ~N[2010-04-17 14:00:00], start: ~N[2010-04-17 14:00:00]}
- @update_attrs %{end: ~N[2011-05-18 15:01:01], start: ~N[2011-05-18 15:01:01]}
- @invalid_attrs %{end: nil, start: nil}
-
- def timer_fixture(attrs \\ %{}) do
- {:ok, timer} =
- attrs
- |> Enum.into(@valid_attrs)
- |> Ctx.create_timer()
-
- timer
- end
-
- test "list_timers/0 returns all timers" do
- timer = timer_fixture()
- assert Ctx.list_timers() == [timer]
- end
-
- test "get_timer!/1 returns the timer with given id" do
- timer = timer_fixture()
- assert Ctx.get_timer!(timer.id) == timer
- end
-
- test "create_timer/1 with valid data creates a timer" do
- assert {:ok, %Timer{} = timer} = Ctx.create_timer(@valid_attrs)
- assert timer.end == ~N[2010-04-17 14:00:00]
- assert timer.start == ~N[2010-04-17 14:00:00]
- end
-
- test "create_timer/1 with invalid data returns error changeset" do
- assert {:error, %Ecto.Changeset{}} = Ctx.create_timer(@invalid_attrs)
- end
-
- test "update_timer/2 with valid data updates the timer" do
- timer = timer_fixture()
- assert {:ok, %Timer{} = timer} = Ctx.update_timer(timer, @update_attrs)
- assert timer.end == ~N[2011-05-18 15:01:01]
- assert timer.start == ~N[2011-05-18 15:01:01]
- end
-
- test "update_timer/2 with invalid data returns error changeset" do
- timer = timer_fixture()
- assert {:error, %Ecto.Changeset{}} = Ctx.update_timer(timer, @invalid_attrs)
- assert timer == Ctx.get_timer!(timer.id)
- end
-
- test "delete_timer/1 deletes the timer" do
- timer = timer_fixture()
- assert {:ok, %Timer{}} = Ctx.delete_timer(timer)
- assert_raise Ecto.NoResultsError, fn -> Ctx.get_timer!(timer.id) end
- end
-
- test "change_timer/1 returns a timer changeset" do
- timer = timer_fixture()
- assert %Ecto.Changeset{} = Ctx.change_timer(timer)
- end
- end
-end
diff --git a/test/app_web/controllers/capture_controller_test.exs b/test/app_web/controllers/capture_controller_test.exs
deleted file mode 100644
index a18670d..0000000
--- a/test/app_web/controllers/capture_controller_test.exs
+++ /dev/null
@@ -1,29 +0,0 @@
-defmodule AppWeb.CaptureControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
-
- @create_attrs %{text: "some text"}
- @invalid_attrs %{text: nil}
-
- describe "new capture" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.capture_path(conn, :new))
- assert html_response(conn, 200) =~ "Capture"
- end
- end
-
- describe "create capture" do
- setup [:person_login]
- test "redirects to categorise page when data is valid", %{conn: conn} do
- conn = post(conn, Routes.capture_path(conn, :create), item: @create_attrs)
- assert redirected_to(conn) == Routes.categorise_path(conn, :index)
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.capture_path(conn, :create), item: @invalid_attrs)
- assert html_response(conn, 200) =~ "Capture"
- end
- end
-
-end
diff --git a/test/app_web/controllers/categorise_controller_test.exs b/test/app_web/controllers/categorise_controller_test.exs
deleted file mode 100644
index 2421582..0000000
--- a/test/app_web/controllers/categorise_controller_test.exs
+++ /dev/null
@@ -1,13 +0,0 @@
-defmodule AppWeb.CategoriseControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
-
- describe "return captured text" do
- setup [:person_login]
- test "index page for categorise", %{conn: conn} do
- conn = get(conn, Routes.categorise_path(conn, :index))
- assert html_response(conn, 200) =~ "Captures"
- end
- end
-
-end
diff --git a/test/app_web/controllers/google_auth_controller_test.exs b/test/app_web/controllers/google_auth_controller_test.exs
deleted file mode 100644
index 9c54bd1..0000000
--- a/test/app_web/controllers/google_auth_controller_test.exs
+++ /dev/null
@@ -1,41 +0,0 @@
-defmodule AppWeb.GoogleAuthControllerTest do
- use AppWeb.ConnCase
-
- test "transform_profile_data_to_person/1 transforms profile to person" do
-
- profile = %{
- email: "nelson@gmail.com",
- email_verified: true,
- family_name: "Correia",
- given_name: "Nelson",
- locale: "en",
- name: "Nelson Correia",
- picture: "https://lh3.googleusercontent.com/a-/AAuE7mApnYb260YC1JY7a",
- sub: "940732358705212133793"
- }
- expected = %{
- email: "nelson@gmail.com",
- email_verified: true,
- familyName: "Correia",
- family_name: "Correia",
- givenName: "Nelson",
- given_name: "Nelson",
- locale: "en",
- name: "Nelson Correia",
- picture: "https://lh3.googleusercontent.com/a-/AAuE7mApnYb260YC1JY7a",
- sub: "940732358705212133793"
- }
- # invoke our transformer function using the sample data:
- person = App.Ctx.Person.transform_profile_data_to_person(profile)
-
- assert Map.equal?(expected, person)
- end
-
-
- test "GET /", %{conn: conn} do
- conn = get(conn, Routes.google_auth_path(conn, :index, code: "code"))
- assert html_response(conn, 302)
- end
-
-
-end
diff --git a/test/app_web/controllers/item_controller_test.exs b/test/app_web/controllers/item_controller_test.exs
deleted file mode 100644
index 0b8dd6d..0000000
--- a/test/app_web/controllers/item_controller_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-defmodule AppWeb.ItemControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
- def fixture(:item) do
- {:ok, item} = Ctx.create_item(@create_attrs)
- item
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all items", %{conn: conn} do
- conn = get(conn, Routes.item_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing Items"
- end
- end
-
- describe "new item" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.item_path(conn, :new))
- assert html_response(conn, 200) =~ "New Item"
- end
- end
-
- describe "create item" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.item_path(conn, :create), item: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.item_path(conn, :show, id)
-
- conn = get(conn, Routes.item_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show Item"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.item_path(conn, :create), item: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Item"
- end
- end
-
- describe "edit item" do
- setup [:person_login, :create_item]
-
- test "renders form for editing chosen item", %{conn: conn, item: item} do
- conn = get(conn, Routes.item_path(conn, :edit, item))
- assert html_response(conn, 200) =~ "Edit Item"
- end
- end
-
- describe "update item" do
- setup [:person_login, :create_item]
-
- test "redirects when data is valid", %{conn: conn, item: item} do
- conn = put(conn, Routes.item_path(conn, :update, item), item: @update_attrs)
- assert redirected_to(conn) == Routes.item_path(conn, :show, item)
-
- conn = get(conn, Routes.item_path(conn, :show, item))
- assert html_response(conn, 200) =~ "some updated text"
- end
-
- test "renders errors when data is invalid", %{conn: conn, item: item} do
- conn = put(conn, Routes.item_path(conn, :update, item), item: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Item"
- end
- end
-
- describe "delete item" do
- setup [:create_item, :person_login]
-
- test "deletes chosen item", %{conn: conn, item: item} do
- conn = delete(conn, Routes.item_path(conn, :delete, item))
- assert redirected_to(conn) == Routes.item_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.item_path(conn, :show, item))
- end
- end
- end
-
- defp create_item(_) do
- item = fixture(:item)
- {:ok, item: item}
- end
-end
diff --git a/test/app_web/controllers/list_controller_test.exs b/test/app_web/controllers/list_controller_test.exs
deleted file mode 100644
index 3dda6ea..0000000
--- a/test/app_web/controllers/list_controller_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-defmodule AppWeb.ListControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{title: "some title"}
- @update_attrs %{title: "some updated title"}
- @invalid_attrs %{title: nil}
-
- def fixture(:list) do
- {:ok, list} = Ctx.create_list(@create_attrs)
- list
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all lists", %{conn: conn} do
- conn = get(conn, Routes.list_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing Lists"
- end
- end
-
- describe "new list" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.list_path(conn, :new))
- assert html_response(conn, 200) =~ "New List"
- end
- end
-
- describe "create list" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.list_path(conn, :create), list: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.list_path(conn, :show, id)
-
- conn = get(conn, Routes.list_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show List"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.list_path(conn, :create), list: @invalid_attrs)
- assert html_response(conn, 200) =~ "New List"
- end
- end
-
- describe "edit list" do
- setup [:create_list, :person_login]
-
- test "renders form for editing chosen list", %{conn: conn, list: list} do
- conn = get(conn, Routes.list_path(conn, :edit, list))
- assert html_response(conn, 200) =~ "Edit List"
- end
- end
-
- describe "update list" do
- setup [:create_list, :person_login]
-
- test "redirects when data is valid", %{conn: conn, list: list} do
- conn = put(conn, Routes.list_path(conn, :update, list), list: @update_attrs)
- assert redirected_to(conn) == Routes.list_path(conn, :show, list)
-
- conn = get(conn, Routes.list_path(conn, :show, list))
- assert html_response(conn, 200) =~ "some updated title"
- end
-
- test "renders errors when data is invalid", %{conn: conn, list: list} do
- conn = put(conn, Routes.list_path(conn, :update, list), list: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit List"
- end
- end
-
- describe "delete list" do
- setup [:create_list, :person_login]
-
- test "deletes chosen list", %{conn: conn, list: list} do
- conn = delete(conn, Routes.list_path(conn, :delete, list))
- assert redirected_to(conn) == Routes.list_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.list_path(conn, :show, list))
- end
- end
- end
-
- defp create_list(_) do
- list = fixture(:list)
- {:ok, list: list}
- end
-end
diff --git a/test/app_web/controllers/page_controller_test.exs b/test/app_web/controllers/page_controller_test.exs
deleted file mode 100644
index be2fb57..0000000
--- a/test/app_web/controllers/page_controller_test.exs
+++ /dev/null
@@ -1,26 +0,0 @@
-defmodule AppWeb.PageControllerTest do
- use AppWeb.ConnCase
-
- test "GET /", %{conn: conn} do
- conn = get(conn, "/")
- assert html_response(conn, 200) =~ "effectiveness"
- end
-
- describe "login/register" do
- test "display error when password invalid", %{conn: conn} do
- params = %{"person" => %{"email" => "test@email.com", "password" => "p"}}
- conn = post(conn, Routes.page_path(conn, :register), params)
-
- assert html_response(conn, 200) =~ "should be at least 6 character(s)"
- end
-
- test "redirects to home", %{conn: conn} do
- params = %{"person" => %{"email" => "test@email.com", "password" => "password"}}
- conn = post(conn, Routes.page_path(conn, :register), params)
-
- assert redirected_to(conn, 302) =~ "/people/info"
- end
-
- end
-
-end
diff --git a/test/app_web/controllers/person_controller_test.exs b/test/app_web/controllers/person_controller_test.exs
deleted file mode 100644
index c711f7f..0000000
--- a/test/app_web/controllers/person_controller_test.exs
+++ /dev/null
@@ -1,100 +0,0 @@
-defmodule AppWeb.PersonControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{email: "a@b.com", email_hash: "some email_hash", familyName: "some familyName", givenName: "some givenName", key_id: 42, password_hash: "some password_hash", username: "some username", username_hash: "some username_hash"}
- @update_attrs %{email: "c@d.net", email_hash: "some updated email_hash", familyName: "some updated familyName", givenName: "some updated givenName", key_id: 43, password_hash: "some updated password_hash", username: "some updated username", username_hash: "some updated username_hash"}
- @invalid_attrs %{email: nil, email_hash: nil, familyName: nil, givenName: nil, key_id: nil, password_hash: nil, username: nil, username_hash: nil}
-
- def fixture(:person) do
- {:ok, person} = Ctx.create_person(@create_attrs)
- person
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all people", %{conn: conn} do
- conn = get(conn, Routes.person_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing People"
- end
- end
-
- describe "new person" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.person_path(conn, :new))
- assert html_response(conn, 200) =~ "New Person"
- end
- end
-
- describe "create person" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.person_path(conn, :create), person: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.person_path(conn, :show, id)
-
- conn = get(conn, Routes.person_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show Person"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.person_path(conn, :create), person: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Person"
- end
- end
-
- describe "edit person" do
- setup [:person_login, :create_person]
-
- test "renders form for editing chosen person", %{conn: conn, person: person} do
- conn = get(conn, Routes.person_path(conn, :edit, person))
- assert html_response(conn, 200) =~ "Edit Person"
- end
- end
-
- describe "update person" do
- setup [:person_login, :create_person]
-
- test "redirects when data is valid", %{conn: conn, person: person} do
- conn = put(conn, Routes.person_path(conn, :update, person), person: @update_attrs)
- assert redirected_to(conn) == Routes.person_path(conn, :show, person)
-
- conn = get(conn, Routes.person_path(conn, :show, person))
- assert html_response(conn, 200)
- end
-
- test "renders errors when data is invalid", %{conn: conn, person: person} do
- conn = put(conn, Routes.person_path(conn, :update, person), person: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Person"
- end
- end
-
- describe "delete person" do
- setup [:person_login, :create_person]
-
- test "deletes chosen person", %{conn: conn, person: person} do
- conn = delete(conn, Routes.person_path(conn, :delete, person))
- assert redirected_to(conn) == Routes.person_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.person_path(conn, :show, person))
- end
- end
- end
-
- describe "info person" do
- setup [:person_login, :create_person]
-
- test "display info person", %{conn: conn} do
- conn = get(conn, Routes.person_path(conn, :info))
- assert html_response(conn, 200)
- end
- end
-
- defp create_person(_) do
- person = fixture(:person)
- {:ok, person: person}
- end
-end
diff --git a/test/app_web/controllers/status_controller_test.exs b/test/app_web/controllers/status_controller_test.exs
deleted file mode 100644
index 986fcdb..0000000
--- a/test/app_web/controllers/status_controller_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-defmodule AppWeb.StatusControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
- def fixture(:status) do
- {:ok, status} = Ctx.create_status(@create_attrs)
- status
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all status", %{conn: conn} do
- conn = get(conn, Routes.status_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing Status"
- end
- end
-
- describe "new status" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.status_path(conn, :new))
- assert html_response(conn, 200) =~ "New Status"
- end
- end
-
- describe "create status" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.status_path(conn, :create), status: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.status_path(conn, :show, id)
-
- conn = get(conn, Routes.status_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show Status"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.status_path(conn, :create), status: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Status"
- end
- end
-
- describe "edit status" do
- setup [:person_login, :create_status]
-
- test "renders form for editing chosen status", %{conn: conn, status: status} do
- conn = get(conn, Routes.status_path(conn, :edit, status))
- assert html_response(conn, 200) =~ "Edit Status"
- end
- end
-
- describe "update status" do
- setup [:person_login, :create_status]
-
- test "redirects when data is valid", %{conn: conn, status: status} do
- conn = put(conn, Routes.status_path(conn, :update, status), status: @update_attrs)
- assert redirected_to(conn) == Routes.status_path(conn, :show, status)
-
- conn = get(conn, Routes.status_path(conn, :show, status))
- assert html_response(conn, 200) =~ "some updated text"
- end
-
- test "renders errors when data is invalid", %{conn: conn, status: status} do
- conn = put(conn, Routes.status_path(conn, :update, status), status: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Status"
- end
- end
-
- describe "delete status" do
- setup [:person_login, :create_status]
-
- test "deletes chosen status", %{conn: conn, status: status} do
- conn = delete(conn, Routes.status_path(conn, :delete, status))
- assert redirected_to(conn) == Routes.status_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.status_path(conn, :show, status))
- end
- end
- end
-
- defp create_status(_) do
- status = fixture(:status)
- {:ok, status: status}
- end
-end
diff --git a/test/app_web/controllers/tag_controller_test.exs b/test/app_web/controllers/tag_controller_test.exs
deleted file mode 100644
index 42db723..0000000
--- a/test/app_web/controllers/tag_controller_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-defmodule AppWeb.TagControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{text: "some text"}
- @update_attrs %{text: "some updated text"}
- @invalid_attrs %{text: nil}
-
- def fixture(:tag) do
- {:ok, tag} = Ctx.create_tag(@create_attrs)
- tag
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all tags", %{conn: conn} do
- conn = get(conn, Routes.tag_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing Tags"
- end
- end
-
- describe "new tag" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.tag_path(conn, :new))
- assert html_response(conn, 200) =~ "New Tag"
- end
- end
-
- describe "create tag" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.tag_path(conn, :create), tag: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.tag_path(conn, :show, id)
-
- conn = get(conn, Routes.tag_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show Tag"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.tag_path(conn, :create), tag: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Tag"
- end
- end
-
- describe "edit tag" do
- setup [:person_login, :create_tag]
-
- test "renders form for editing chosen tag", %{conn: conn, tag: tag} do
- conn = get(conn, Routes.tag_path(conn, :edit, tag))
- assert html_response(conn, 200) =~ "Edit Tag"
- end
- end
-
- describe "update tag" do
- setup [:person_login, :create_tag]
-
- test "redirects when data is valid", %{conn: conn, tag: tag} do
- conn = put(conn, Routes.tag_path(conn, :update, tag), tag: @update_attrs)
- assert redirected_to(conn) == Routes.tag_path(conn, :show, tag)
-
- conn = get(conn, Routes.tag_path(conn, :show, tag))
- assert html_response(conn, 200) =~ "some updated text"
- end
-
- test "renders errors when data is invalid", %{conn: conn, tag: tag} do
- conn = put(conn, Routes.tag_path(conn, :update, tag), tag: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Tag"
- end
- end
-
- describe "delete tag" do
- setup [:person_login, :create_tag]
-
- test "deletes chosen tag", %{conn: conn, tag: tag} do
- conn = delete(conn, Routes.tag_path(conn, :delete, tag))
- assert redirected_to(conn) == Routes.tag_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.tag_path(conn, :show, tag))
- end
- end
- end
-
- defp create_tag(_) do
- tag = fixture(:tag)
- {:ok, tag: tag}
- end
-end
diff --git a/test/app_web/controllers/timer_controller_test.exs b/test/app_web/controllers/timer_controller_test.exs
deleted file mode 100644
index 7df05f2..0000000
--- a/test/app_web/controllers/timer_controller_test.exs
+++ /dev/null
@@ -1,91 +0,0 @@
-defmodule AppWeb.TimerControllerTest do
- use AppWeb.ConnCase
- import App.SetupHelpers
- alias App.Ctx
-
- @create_attrs %{end: ~N[2010-04-17 14:00:00], start: ~N[2010-04-17 14:00:00]}
- @update_attrs %{end: ~N[2011-05-18 15:01:01], start: ~N[2011-05-18 15:01:01]}
- @invalid_attrs %{end: nil, start: nil}
-
- def fixture(:timer) do
- {:ok, timer} = Ctx.create_timer(@create_attrs)
- timer
- end
-
- describe "index" do
- setup [:person_login]
- test "lists all timers", %{conn: conn} do
- conn = get(conn, Routes.timer_path(conn, :index))
- assert html_response(conn, 200) =~ "Listing Timers"
- end
- end
-
- describe "new timer" do
- setup [:person_login]
- test "renders form", %{conn: conn} do
- conn = get(conn, Routes.timer_path(conn, :new))
- assert html_response(conn, 200) =~ "New Timer"
- end
- end
-
- describe "create timer" do
- setup [:person_login]
- test "redirects to show when data is valid", %{conn: conn} do
- conn = post(conn, Routes.timer_path(conn, :create), timer: @create_attrs)
-
- assert %{id: id} = redirected_params(conn)
- assert redirected_to(conn) == Routes.timer_path(conn, :show, id)
-
- conn = get(conn, Routes.timer_path(conn, :show, id))
- assert html_response(conn, 200) =~ "Show Timer"
- end
-
- test "renders errors when data is invalid", %{conn: conn} do
- conn = post(conn, Routes.timer_path(conn, :create), timer: @invalid_attrs)
- assert html_response(conn, 200) =~ "New Timer"
- end
- end
-
- describe "edit timer" do
- setup [:person_login, :create_timer]
-
- test "renders form for editing chosen timer", %{conn: conn, timer: timer} do
- conn = get(conn, Routes.timer_path(conn, :edit, timer))
- assert html_response(conn, 200) =~ "Edit Timer"
- end
- end
-
- describe "update timer" do
- setup [:person_login, :create_timer]
-
- test "redirects when data is valid", %{conn: conn, timer: timer} do
- conn = put(conn, Routes.timer_path(conn, :update, timer), timer: @update_attrs)
- assert redirected_to(conn) == Routes.timer_path(conn, :show, timer)
-
- conn = get(conn, Routes.timer_path(conn, :show, timer))
- assert html_response(conn, 200)
- end
-
- test "renders errors when data is invalid", %{conn: conn, timer: timer} do
- conn = put(conn, Routes.timer_path(conn, :update, timer), timer: @invalid_attrs)
- assert html_response(conn, 200) =~ "Edit Timer"
- end
- end
-
- describe "delete timer" do
- setup [:person_login, :create_timer]
-
- test "deletes chosen timer", %{conn: conn, timer: timer} do
- conn = delete(conn, Routes.timer_path(conn, :delete, timer))
- assert redirected_to(conn) == Routes.timer_path(conn, :index)
- assert_error_sent 404, fn ->
- get(conn, Routes.timer_path(conn, :show, timer))
- end
- end
- end
-
- defp create_timer(_) do
- timer = fixture(:timer)
- {:ok, timer: timer}
- end
-end
diff --git a/test/app_web/views/error_view_test.exs b/test/app_web/views/error_view_test.exs
deleted file mode 100644
index 85a326c..0000000
--- a/test/app_web/views/error_view_test.exs
+++ /dev/null
@@ -1,14 +0,0 @@
-defmodule AppWeb.ErrorViewTest do
- use AppWeb.ConnCase, async: true
-
- # Bring render/3 and render_to_string/3 for testing custom views
- import Phoenix.View
-
- test "renders 404.html" do
- assert render_to_string(AppWeb.ErrorView, "404.html", []) == "Not Found"
- end
-
- test "renders 500.html" do
- assert render_to_string(AppWeb.ErrorView, "500.html", []) == "Internal Server Error"
- end
-end
diff --git a/test/app_web/views/layout_view_test.exs b/test/app_web/views/layout_view_test.exs
deleted file mode 100644
index 6a04f46..0000000
--- a/test/app_web/views/layout_view_test.exs
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.LayoutViewTest do
- use AppWeb.ConnCase, async: true
-end
diff --git a/test/app_web/views/page_view_test.exs b/test/app_web/views/page_view_test.exs
deleted file mode 100644
index 75067ce..0000000
--- a/test/app_web/views/page_view_test.exs
+++ /dev/null
@@ -1,3 +0,0 @@
-defmodule AppWeb.PageViewTest do
- use AppWeb.ConnCase, async: true
-end
diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex
deleted file mode 100644
index b7c6d72..0000000
--- a/test/support/channel_case.ex
+++ /dev/null
@@ -1,37 +0,0 @@
-defmodule AppWeb.ChannelCase do
- @moduledoc """
- This module defines the test case to be used by
- channel tests.
-
- Such tests rely on `Phoenix.ChannelTest` and also
- import other functionality to make it easier
- to build common data structures and query the data layer.
-
- Finally, if the test case interacts with the database,
- it cannot be async. For this reason, every test runs
- inside a transaction which is reset at the beginning
- of the test unless the test case is marked as async.
- """
-
- use ExUnit.CaseTemplate
-
- using do
- quote do
- # Import conveniences for testing with channels
- use Phoenix.ChannelTest
-
- # The default endpoint for testing
- @endpoint AppWeb.Endpoint
- end
- end
-
- setup tags do
- :ok = Ecto.Adapters.SQL.Sandbox.checkout(App.Repo)
-
- unless tags[:async] do
- Ecto.Adapters.SQL.Sandbox.mode(App.Repo, {:shared, self()})
- end
-
- :ok
- end
-end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
deleted file mode 100644
index 2158cdd..0000000
--- a/test/support/conn_case.ex
+++ /dev/null
@@ -1,38 +0,0 @@
-defmodule AppWeb.ConnCase do
- @moduledoc """
- This module defines the test case to be used by
- tests that require setting up a connection.
-
- Such tests rely on `Phoenix.ConnTest` and also
- import other functionality to make it easier
- to build common data structures and query the data layer.
-
- Finally, if the test case interacts with the database,
- it cannot be async. For this reason, every test runs
- inside a transaction which is reset at the beginning
- of the test unless the test case is marked as async.
- """
-
- use ExUnit.CaseTemplate
-
- using do
- quote do
- # Import conveniences for testing with connections
- use Phoenix.ConnTest
- alias AppWeb.Router.Helpers, as: Routes
-
- # The default endpoint for testing
- @endpoint AppWeb.Endpoint
- end
- end
-
- setup tags do
- :ok = Ecto.Adapters.SQL.Sandbox.checkout(App.Repo)
-
- unless tags[:async] do
- Ecto.Adapters.SQL.Sandbox.mode(App.Repo, {:shared, self()})
- end
-
- {:ok, conn: Phoenix.ConnTest.build_conn()}
- end
-end
diff --git a/test/support/data_case.ex b/test/support/data_case.ex
deleted file mode 100644
index d5188cb..0000000
--- a/test/support/data_case.ex
+++ /dev/null
@@ -1,53 +0,0 @@
-defmodule App.DataCase do
- @moduledoc """
- This module defines the setup for tests requiring
- access to the application's data layer.
-
- You may define functions here to be used as helpers in
- your tests.
-
- Finally, if the test case interacts with the database,
- it cannot be async. For this reason, every test runs
- inside a transaction which is reset at the beginning
- of the test unless the test case is marked as async.
- """
-
- use ExUnit.CaseTemplate
-
- using do
- quote do
- alias App.Repo
-
- import Ecto
- import Ecto.Changeset
- import Ecto.Query
- import App.DataCase
- end
- end
-
- setup tags do
- :ok = Ecto.Adapters.SQL.Sandbox.checkout(App.Repo)
-
- unless tags[:async] do
- Ecto.Adapters.SQL.Sandbox.mode(App.Repo, {:shared, self()})
- end
-
- :ok
- end
-
- @doc """
- A helper that transforms changeset errors into a map of messages.
-
- assert {:error, changeset} = Accounts.create_user(%{password: "short"})
- assert "password is too short" in errors_on(changeset).password
- assert %{password: ["password is too short"]} = errors_on(changeset)
-
- """
- def errors_on(changeset) do
- Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
- Regex.replace(~r"%{(\w+)}", message, fn _, key ->
- opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()
- end)
- end)
- end
-end
diff --git a/test/support/setup_helpers.ex b/test/support/setup_helpers.ex
deleted file mode 100644
index afe6f2d..0000000
--- a/test/support/setup_helpers.ex
+++ /dev/null
@@ -1,17 +0,0 @@
-defmodule App.SetupHelpers do
- use Phoenix.ConnTest
- import AppWeb.Router.Helpers
-
- @endpoint AppWeb.Endpoint
-
- def person_login(_) do
- {:ok,
- conn:
- build_conn()
- |> (fn c ->
- get(c, google_auth_path(c, :index, code: "code"))
- end).()
- }
- end
-
-end
diff --git a/test/test_helper.exs b/test/test_helper.exs
deleted file mode 100644
index 4fe7a40..0000000
--- a/test/test_helper.exs
+++ /dev/null
@@ -1,2 +0,0 @@
-ExUnit.start()
-Ecto.Adapters.SQL.Sandbox.mode(App.Repo, :manual)