web interface
This commit is contained in:
parent
f13d40f2ee
commit
3e45daec62
@ -1,6 +1,8 @@
|
|||||||
backcall==0.1.0
|
backcall==0.1.0
|
||||||
|
Click==7.0
|
||||||
dateparser==0.7.2
|
dateparser==0.7.2
|
||||||
decorator==4.4.0
|
decorator==4.4.0
|
||||||
|
Flask==1.1.1
|
||||||
freezegun==0.3.12
|
freezegun==0.3.12
|
||||||
fuzzywuzzy==0.17.0
|
fuzzywuzzy==0.17.0
|
||||||
geographiclib==1.49
|
geographiclib==1.49
|
||||||
@ -8,7 +10,10 @@ geopy==1.20.0
|
|||||||
importlib-resources==1.0.2
|
importlib-resources==1.0.2
|
||||||
ipython==7.8.0
|
ipython==7.8.0
|
||||||
ipython-genutils==0.2.0
|
ipython-genutils==0.2.0
|
||||||
|
itsdangerous==1.1.0
|
||||||
jedi==0.15.1
|
jedi==0.15.1
|
||||||
|
Jinja2==2.10.3
|
||||||
|
MarkupSafe==1.1.1
|
||||||
numpy==1.17.2
|
numpy==1.17.2
|
||||||
parso==0.5.1
|
parso==0.5.1
|
||||||
pexpect==4.7.0
|
pexpect==4.7.0
|
||||||
@ -25,4 +30,5 @@ timezonefinder==4.1.0
|
|||||||
traitlets==4.3.2
|
traitlets==4.3.2
|
||||||
tzlocal==2.0.0
|
tzlocal==2.0.0
|
||||||
wcwidth==0.1.7
|
wcwidth==0.1.7
|
||||||
|
Werkzeug==0.16.0
|
||||||
word2number==1.1
|
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