web interface
This commit is contained in:
parent
f13d40f2ee
commit
3e45daec62
@ -1,6 +1,8 @@
|
||||
backcall==0.1.0
|
||||
Click==7.0
|
||||
dateparser==0.7.2
|
||||
decorator==4.4.0
|
||||
Flask==1.1.1
|
||||
freezegun==0.3.12
|
||||
fuzzywuzzy==0.17.0
|
||||
geographiclib==1.49
|
||||
@ -8,7 +10,10 @@ geopy==1.20.0
|
||||
importlib-resources==1.0.2
|
||||
ipython==7.8.0
|
||||
ipython-genutils==0.2.0
|
||||
itsdangerous==1.1.0
|
||||
jedi==0.15.1
|
||||
Jinja2==2.10.3
|
||||
MarkupSafe==1.1.1
|
||||
numpy==1.17.2
|
||||
parso==0.5.1
|
||||
pexpect==4.7.0
|
||||
@ -25,4 +30,5 @@ timezonefinder==4.1.0
|
||||
traitlets==4.3.2
|
||||
tzlocal==2.0.0
|
||||
wcwidth==0.1.7
|
||||
Werkzeug==0.16.0
|
||||
word2number==1.1
|
||||
|
69
src/tww/static/jquery.debounce.js
Executable file
69
src/tww/static/jquery.debounce.js
Executable file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Debounce and throttle function's decorator plugin 1.0.5
|
||||
*
|
||||
* Copyright (c) 2009 Filatov Dmitry (alpha@zforms.ru)
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
$.extend({
|
||||
|
||||
debounce : function(fn, timeout, invokeAsap, ctx) {
|
||||
|
||||
if(arguments.length == 3 && typeof invokeAsap != 'boolean') {
|
||||
ctx = invokeAsap;
|
||||
invokeAsap = false;
|
||||
}
|
||||
|
||||
var timer;
|
||||
|
||||
return function() {
|
||||
|
||||
var args = arguments;
|
||||
ctx = ctx || this;
|
||||
|
||||
invokeAsap && !timer && fn.apply(ctx, args);
|
||||
|
||||
clearTimeout(timer);
|
||||
|
||||
timer = setTimeout(function() {
|
||||
invokeAsap || fn.apply(ctx, args);
|
||||
timer = null;
|
||||
}, timeout);
|
||||
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
throttle : function(fn, timeout, ctx) {
|
||||
|
||||
var timer, args, needInvoke;
|
||||
|
||||
return function() {
|
||||
|
||||
args = arguments;
|
||||
needInvoke = true;
|
||||
ctx = ctx || this;
|
||||
|
||||
timer || (function() {
|
||||
if(needInvoke) {
|
||||
fn.apply(ctx, args);
|
||||
needInvoke = false;
|
||||
timer = setTimeout(arguments.callee, timeout);
|
||||
}
|
||||
else {
|
||||
timer = null;
|
||||
}
|
||||
})();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
10598
src/tww/static/jquery.js
vendored
Normal file
10598
src/tww/static/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
481
src/tww/static/select2.css
Normal file
481
src/tww/static/select2.css
Normal file
@ -0,0 +1,481 @@
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
vertical-align: middle; }
|
||||
.select2-container .select2-selection--single {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 28px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-selection--single .select2-selection__clear {
|
||||
position: relative; }
|
||||
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||
padding-right: 8px;
|
||||
padding-left: 20px; }
|
||||
.select2-container .select2-selection--multiple {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-search--inline {
|
||||
float: left; }
|
||||
.select2-container .select2-search--inline .select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
padding: 0; }
|
||||
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
.select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
width: 100%;
|
||||
z-index: 1051; }
|
||||
|
||||
.select2-results {
|
||||
display: block; }
|
||||
|
||||
.select2-results__options {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-results__option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
|
||||
.select2-container--open .select2-dropdown {
|
||||
left: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--above {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--below {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-search--dropdown {
|
||||
display: block;
|
||||
padding: 4px; }
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
.select2-search--dropdown.select2-search--hide {
|
||||
display: none; }
|
||||
|
||||
.select2-close-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
z-index: 99;
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0); }
|
||||
|
||||
.select2-hidden-accessible {
|
||||
border: 0 !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
-webkit-clip-path: inset(50%) !important;
|
||||
clip-path: inset(50%) !important;
|
||||
height: 1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
white-space: nowrap !important; }
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
padding: 1px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #333; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
border: solid black 1px;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa; }
|
||||
|
||||
.select2-container--default .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield; }
|
||||
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--default .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||
color: #999; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
|
||||
.select2-container--default .select2-results__option .select2-results__option {
|
||||
padding-left: 1em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em; }
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
.select2-container--default .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic .select2-selection--single {
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
outline: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
border: none;
|
||||
border-left: 1px solid #aaa;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
border: none;
|
||||
border-right: 1px solid #aaa;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||
background: transparent;
|
||||
border: none; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||
|
||||
.select2-container--classic .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
outline: 0; }
|
||||
.select2-container--classic .select2-selection--multiple:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||
display: none; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #555; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||
border: 1px solid #5897fb; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||
outline: 0;
|
||||
box-shadow: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid transparent; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--above {
|
||||
border-bottom: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--below {
|
||||
border-top: none; }
|
||||
|
||||
.select2-container--classic .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--classic .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||
color: grey; }
|
||||
|
||||
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #3875d7;
|
||||
color: white; }
|
||||
|
||||
.select2-container--classic .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
6037
src/tww/static/select2.js
Normal file
6037
src/tww/static/select2.js
Normal file
File diff suppressed because it is too large
Load Diff
98
src/tww/templates/home.html
Normal file
98
src/tww/templates/home.html
Normal file
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Time When And Where</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-family: Open Sans, Arial, sans-serif;
|
||||
color: #444;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.main-input {
|
||||
width: 100%;
|
||||
font-family: Open Sans, Arial sans-serif;
|
||||
font-size: 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='select2.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<form>
|
||||
<input type="text" class="main-input datetime__txt" name="datetime__txt"
|
||||
value="" autocomplete="off"/>
|
||||
</br>
|
||||
<span class="datetime__error"></span>
|
||||
</br>
|
||||
<input type="text" class="datetime" name="datetime" value="" style="width: 320px;"/>
|
||||
</br></br>
|
||||
<input type="text" class="datetime__date_txt" name="datetime__date_txt"
|
||||
value=""/>
|
||||
<input type="text" class="datetime__time_txt" name="datetime__time_txt"
|
||||
value=""/>
|
||||
<input type="text" class="datetime__tz_offset" name="datetime__tz_offset"
|
||||
value="" size="8"/>
|
||||
<select class="datetime__tz_name" name="datetime__tz">
|
||||
<option disabled selected value> -- select timezone --</option>
|
||||
{% for tz in all_tz %}
|
||||
<option value="{{ tz }}">{{ tz }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</form>
|
||||
</main>
|
||||
<script src="{{ url_for('static', filename='jquery.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='jquery.debounce.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='select2.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='main.js') }}"></script>
|
||||
<script>
|
||||
var textarea = document.querySelector('textarea');
|
||||
|
||||
if (textarea)
|
||||
textarea.addEventListener('keydown', autosize);
|
||||
|
||||
function autosize() {
|
||||
var el = this;
|
||||
setTimeout(function () {
|
||||
el.style.cssText = 'height:auto; padding:0';
|
||||
el.style.cssText = 'height:' + (el.scrollHeight + 30) + 'px';
|
||||
}, 0);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('select').select2();
|
||||
|
||||
$('.datetime__txt').keyup($.debounce(function (e) {
|
||||
$el = $(this);
|
||||
$.ajax({
|
||||
"url": "{{ url_for("api_datetime") }}",
|
||||
"data": {"q": this.value}
|
||||
}).done(function (r) {
|
||||
if (r.error !== "")
|
||||
$el.next(".datetime__error").addClass("flash").addClass("error").html(r.error);
|
||||
else
|
||||
$el.next(".datetime__error").removeClass("flash").removeClass("error").html("");
|
||||
$el.siblings(".datetime").val(r.to_dt_resolve.iso);
|
||||
$el.siblings(".datetime__date_txt").val(r.to_dt_resolve.date);
|
||||
$el.siblings(".datetime__time_txt").val(r.to_dt_resolve.time);
|
||||
$el.siblings(".datetime__tz_offset").val(r.to_dt_resolve.tz_offset);
|
||||
$el.siblings(".datetime__tz_name").val(r.to_tz_resolve.tz_name).trigger('change');
|
||||
});
|
||||
}, 500));
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
99
src/tww/web.py
Normal file
99
src/tww/web.py
Normal file
@ -0,0 +1,99 @@
|
||||
import pytz
|
||||
from flask import Flask, render_template, jsonify, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
import dateparser
|
||||
from tww import resolve_timezone
|
||||
|
||||
IN_KW = " in "
|
||||
TO_KW = " to "
|
||||
NO_TZ_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
||||
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S%z'
|
||||
DATE_FORMAT = '%Y-%m-%d'
|
||||
TIME_FORMAT = '%H:%M:%S'
|
||||
TZ_OFFSET_FORMAT = '%z'
|
||||
|
||||
|
||||
def parse_query(q):
|
||||
fmt = NO_TZ_FORMAT
|
||||
to_split = q.split(TO_KW)
|
||||
in_dt_resolve_fmt, to_dt_resolve_fmt = {}, {}
|
||||
in_tz_resolve, to_tz_resolve = {}, {}
|
||||
error = ""
|
||||
if len(to_split) >= 2:
|
||||
# 18:00 to Zurich
|
||||
in_q, to_tz = to_split[0], TO_KW.join(to_split[1:])
|
||||
else:
|
||||
# 18:00
|
||||
in_q = q
|
||||
to_tz = ""
|
||||
in_split = in_q.split(IN_KW)
|
||||
if len(in_split) >= 2:
|
||||
# 18:00 in Zurich
|
||||
in_dt, in_tz = in_split[0], IN_KW.join(in_split[1:])
|
||||
else:
|
||||
# in 2 hours / 19:00 CET
|
||||
in_dt = in_q
|
||||
in_tz = ""
|
||||
try:
|
||||
in_dt_resolve = dateparser.parse(in_dt, settings={
|
||||
'RETURN_AS_TIMEZONE_AWARE': True})
|
||||
if not in_tz:
|
||||
in_tz = in_dt_resolve.strftime("%Z")
|
||||
if in_tz:
|
||||
isofmt = in_dt_resolve.isoformat()
|
||||
in_tz_resolve = resolve_timezone(in_tz)
|
||||
in_dt_resolve = dateparser.parse(isofmt, settings={
|
||||
'TO_TIMEZONE': in_tz_resolve})
|
||||
to_dt_resolve, to_tz_resolve = in_dt_resolve, in_tz_resolve
|
||||
if in_dt_resolve:
|
||||
in_dt_resolve_fmt = {
|
||||
'iso': in_dt_resolve.strftime(ISO_FORMAT),
|
||||
'fmt': in_dt_resolve.strftime(fmt),
|
||||
'date': in_dt_resolve.strftime(DATE_FORMAT),
|
||||
'time': in_dt_resolve.strftime(TIME_FORMAT),
|
||||
'tz_offset': in_dt_resolve.strftime(TZ_OFFSET_FORMAT),
|
||||
}
|
||||
if to_tz:
|
||||
isofmt = in_dt_resolve.isoformat()
|
||||
to_tz_resolve = resolve_timezone(to_tz)
|
||||
to_dt_resolve = dateparser.parse(isofmt, settings={
|
||||
'TO_TIMEZONE': to_tz_resolve})
|
||||
if to_dt_resolve:
|
||||
to_dt_resolve_fmt = {
|
||||
'iso': to_dt_resolve.strftime(ISO_FORMAT),
|
||||
'fmt': to_dt_resolve.strftime(fmt),
|
||||
'date': to_dt_resolve.strftime(DATE_FORMAT),
|
||||
'time': to_dt_resolve.strftime(TIME_FORMAT),
|
||||
'tz_offset': to_dt_resolve.strftime(TZ_OFFSET_FORMAT),
|
||||
}
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
return {
|
||||
'error': error,
|
||||
'query': q,
|
||||
'fmt': fmt,
|
||||
'in_dt': in_dt,
|
||||
'in_tz_resolve': in_tz_resolve,
|
||||
'in_dt_resolve': in_dt_resolve_fmt,
|
||||
'to_dt_resolve': to_dt_resolve_fmt,
|
||||
'in_tz': in_tz,
|
||||
'to_tz': to_tz,
|
||||
'to_tz_resolve': to_tz_resolve,
|
||||
}
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
return render_template("home.html", all_tz=pytz.all_timezones)
|
||||
|
||||
|
||||
@app.route("/api/datetime")
|
||||
def api_datetime():
|
||||
q = request.args.get('q')
|
||||
return jsonify(parse_query(q))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True)
|
Loading…
Reference in New Issue
Block a user