Compare commits
42 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
f0f4b14310 | |
|
|
62dc4fa565 | |
|
|
651ff0e04d | |
|
|
078674a06f | |
|
|
0ae0609759 | |
|
|
f67f3dd8a1 | |
|
|
a121503777 | |
|
|
28b0110e2d | |
|
|
f5e3a6e867 | |
|
|
734fe9d286 | |
|
|
80b058a869 | |
|
|
01adec7db5 | |
|
|
2bca997483 | |
|
|
95b10fd9f6 | |
|
|
568aa6a229 | |
|
|
fc088ec240 | |
|
|
435ff82683 | |
|
|
2763b68bc4 | |
|
|
327fdb925c | |
|
|
f84614a8da | |
|
|
5e70a49c2c | |
|
|
c2ed541604 | |
|
|
0f8637c9ff | |
|
|
8c7fe2e9ef | |
|
|
c90cbfc7be | |
|
|
9301ddd467 | |
|
|
8a47f5f321 | |
|
|
d5ec073f75 | |
|
|
b8f0efc01c | |
|
|
81c8743de7 | |
|
|
6abfab229a | |
|
|
ec780f7d9b | |
|
|
94a14f8b9d | |
|
|
90dbfd6f5a | |
|
|
de5f17e2c9 | |
|
|
0e22586e12 | |
|
|
80becbb7a7 | |
|
|
2e98bdff2d | |
|
|
8f966c98a4 | |
|
|
a0f336ca67 | |
|
|
f8b5eb71e0 | |
|
|
7c70ba27cb |
|
|
@ -8,3 +8,4 @@ todo-server
|
|||
exec-todo-server
|
||||
notes-server
|
||||
exec-notes-server
|
||||
testdata/mytinytodo-v1.6.5*
|
||||
|
|
|
|||
|
|
@ -2,19 +2,21 @@ package config
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"local/args"
|
||||
"gogs.inhome.blapointe.com/local/args"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
Port string
|
||||
StoreType string
|
||||
StoreAddr string
|
||||
StoreUser string
|
||||
StorePass string
|
||||
Root string
|
||||
MyTinyTodo string
|
||||
Port string
|
||||
StoreType string
|
||||
StoreAddr string
|
||||
StoreUser string
|
||||
StorePass string
|
||||
Root string
|
||||
OAuth string
|
||||
Loop time.Duration
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -32,8 +34,9 @@ func Refresh() {
|
|||
as.Append(args.STRING, "storeaddr", "addr of store", "")
|
||||
as.Append(args.STRING, "storeuser", "user of store", "")
|
||||
as.Append(args.STRING, "storepass", "pass of store", "")
|
||||
as.Append(args.STRING, "mtt", "url of php server", "http://localhost:38808")
|
||||
as.Append(args.STRING, "oauth", "url for boauthz", "")
|
||||
as.Append(args.STRING, "root", "root of static files", "./public")
|
||||
as.Append(args.DURATION, "loop", "loop duration for refreshing completed tasks", time.Minute)
|
||||
if err := as.Parse(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -44,5 +47,6 @@ func Refresh() {
|
|||
StoreUser = as.Get("storeuser").GetString()
|
||||
StorePass = as.Get("storepass").GetString()
|
||||
Root = as.Get("root").GetString()
|
||||
MyTinyTodo = as.Get("mtt").GetString()
|
||||
Loop = as.Get("loop").GetDuration()
|
||||
OAuth = as.Get("oauth").GetString()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
module gogs.inhome.blapointe.com/local/todo-server
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34
|
||||
gogs.inhome.blapointe.com/local/gziphttp v0.0.0-20230410171240-32da87640b26
|
||||
gogs.inhome.blapointe.com/local/oauth2 v0.0.0-20230410162733-d39498ff8454
|
||||
gogs.inhome.blapointe.com/local/router v0.0.0-20230410162418-08ccdc13df87
|
||||
gogs.inhome.blapointe.com/local/storage v0.0.0-20230410162102-db39d7b02e29
|
||||
)
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
cloud.google.com/go v0.33.1 h1:fmJQWZ1w9PGkHR1YL/P7HloDvqlmKQ4Vpb7PC2e+aCk=
|
||||
cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||
github.com/Azure/azure-storage-blob-go v0.0.0-20181023070848-cf01652132cc/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Unknwon/goconfig v0.0.0-20181105214110-56bd8ab18619 h1:6X8iB881g299aNEv6KXrcjL31iLOH7yA6NXoQX+MbDg=
|
||||
github.com/Unknwon/goconfig v0.0.0-20181105214110-56bd8ab18619/go.mod h1:wngxua9XCNjvHjDiTiV26DaKDT+0c63QR6H5hjVUUxw=
|
||||
github.com/a8m/tree v0.0.0-20180321023834-3cf936ce15d6/go.mod h1:FSdwKX97koS5efgm8WevNf7XS3PqtyFkKDDXrz778cg=
|
||||
github.com/abbot/go-http-auth v0.4.0 h1:QjmvZ5gSC7jm3Zg54DqWE/T5m1t2AfDu6QlXJT0EVT0=
|
||||
github.com/abbot/go-http-auth v0.4.0/go.mod h1:Cz6ARTIzApMJDzh5bRMSUou6UMSp0IEXg9km/ci7TJM=
|
||||
github.com/anacrolix/dms v0.0.0-20180117034613-8af4925bffb5/go.mod h1:DGqLjaZ3ziKKNRt+U5Q9PLWJ52Q/4rxfaaH/b3QYKaE=
|
||||
github.com/aws/aws-sdk-go v1.15.81 h1:va7uoFaV9uKAtZ6BTmp1u7paoMsizYRRLvRuoC07nQ8=
|
||||
github.com/aws/aws-sdk-go v1.15.81/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
|
||||
github.com/billziss-gh/cgofuse v1.1.0/go.mod h1:LJjoaUojlVjgo5GQoEJTcJNqZJeRU0nCR84CyxKt2YM=
|
||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/coreos/bbolt v0.0.0-20180318001526-af9db2027c98/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/djherbis/times v1.1.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8=
|
||||
github.com/dropbox/dropbox-sdk-go-unofficial v5.4.0+incompatible/go.mod h1:lr+LhMM3F6Y3lW1T9j2U5l7QeuWm87N9+PPXo3yH4qY=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
|
||||
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
|
||||
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
|
||||
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
|
||||
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
|
||||
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
|
||||
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
|
||||
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
|
||||
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
|
||||
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
|
||||
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
|
||||
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
|
||||
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
|
||||
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
|
||||
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
|
||||
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
|
||||
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9/go.mod h1:GpOj6zuVBG3Inr9qjEnuVTgBlk2lZ1S9DcoFiXWyKss=
|
||||
github.com/goftp/server v0.0.0-20190111142836-88de73f463af/go.mod h1:k/SS6VWkxY7dHPhoMQ8IdRu8L4lQtmGbhyXGg+vCnXE=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
|
||||
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jlaffaye/ftp v0.0.0-20181101112434-47f21d10f0ee/go.mod h1:lli8NYPQOFy3O++YmYbqVgOcQ1JPCwdOy+5zSjKJ9qY=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
|
||||
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
github.com/minio/minio-go/v6 v6.0.57 h1:ixPkbKkyD7IhnluRgQpGSpHdpvNVaW6OD5R9IAO/9Tw=
|
||||
github.com/minio/minio-go/v6 v6.0.57/go.mod h1:5+R/nM9Pwrh0vqF+HbYYDQ84wdUFPyXHkrdT4AIkifM=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/ncw/go-acd v0.0.0-20171120105400-887eb06ab6a2/go.mod h1:MLIrzg7gp/kzVBxRE1olT7CWYMCklcUWU+ekoxOD9x0=
|
||||
github.com/ncw/rclone v1.46.0 h1:5SY9lB6LIIXqwOaCWp5twUqNWgJVZMW+0D4rX90A2+E=
|
||||
github.com/ncw/rclone v1.46.0/go.mod h1:+uFY4HNpat/yXXIEin5ETWXxIwEplC+eDe/vT8vlk1w=
|
||||
github.com/ncw/swift v1.0.44 h1:EKvOTvUxElbpDWqxsyVaVGvc2IfuOqQnRmjnR2AGhQ4=
|
||||
github.com/ncw/swift v1.0.44/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/nsf/termbox-go v0.0.0-20181027232701-60ab7e3d12ed/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd/go.mod h1:4soZNh0zW0LtYGdQ416i0jO0EIqMGcbtaspRS4BDvRQ=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pengsrc/go-shared v0.2.0/go.mod h1:jVblp62SafmidSkvWrXyxAme3gaTfEtWwRPGz5cpvHg=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.8.3/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46 h1:w2CpS5muK+jyydnmlkqpAhzKmHmMBzBkfYUDjQNS1Dk=
|
||||
github.com/rfjakob/eme v0.0.0-20171028163933-2222dbd4ba46/go.mod h1:U2bmx0hDj8EyDdcxmD5t3XHDnBFnyNNc22n1R4008eM=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sevlyar/go-daemon v0.1.4/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
||||
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c h1:fyKiXKO1/I/B6Y2U8T7WdQGWzwehOuGIrljPtt7YTTI=
|
||||
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t3rm1n4l/go-mega v0.0.0-20190205172012-55a226cf41da/go.mod h1:XWL4vDyd3JKmJx+hZWUVgCNmmhZ2dTBcaNDcxH465s0=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc=
|
||||
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yunify/qingstor-sdk-go v2.2.15+incompatible/go.mod h1:w6wqLDQ5bBTzxGJ55581UrSwLrsTAsdo9N6yX/8d9RY=
|
||||
go.mongodb.org/mongo-driver v1.7.2 h1:pFttQyIiJUHEn50YfZgC9ECjITMT44oiN36uArf/OFg=
|
||||
go.mongodb.org/mongo-driver v1.7.2/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8=
|
||||
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34 h1:0tuX5dfOksiOQD1vbJjVNVTVxTTIng7UrUdSLF5T+Ao=
|
||||
gogs.inhome.blapointe.com/local/args v0.0.0-20230410154220-44370f257b34/go.mod h1:YG9n3Clg7683ohkVnJK2hdX8bBS9EojIsd1qPZumX0Y=
|
||||
gogs.inhome.blapointe.com/local/gziphttp v0.0.0-20230410171240-32da87640b26 h1:zo9E05aBiyvtuuQiT3XjzBnpbm8+bVbzHe7soBQS0Tk=
|
||||
gogs.inhome.blapointe.com/local/gziphttp v0.0.0-20230410171240-32da87640b26/go.mod h1:Sdj/NB9h3xrzPDqViQAHoDhA5gmpHkrWRXUauvLSA74=
|
||||
gogs.inhome.blapointe.com/local/logb v0.0.0-20230410154319-880efa39d871 h1:cMGPiwvK/QGg4TfW8VasO6SsS/O7UQmwyKDErV/ozoA=
|
||||
gogs.inhome.blapointe.com/local/logb v0.0.0-20230410154319-880efa39d871/go.mod h1:E0pLNvMLzY0Kth1W078y+06z1AUyVMWnChMpRFf4w2Q=
|
||||
gogs.inhome.blapointe.com/local/oauth2 v0.0.0-20230410162733-d39498ff8454 h1:U8gUhe9E97/uG3ne6D1VONCCVC6jjBbF1gDMKn3GCeo=
|
||||
gogs.inhome.blapointe.com/local/oauth2 v0.0.0-20230410162733-d39498ff8454/go.mod h1:YDG4DAUbmKcQUDWdZAJyoUtX+N2zQIFQ0fz88lAPuiU=
|
||||
gogs.inhome.blapointe.com/local/router v0.0.0-20230410162418-08ccdc13df87 h1:jlIDVPGFk42puv6NYzRkGFMhsZ0L1AHGRyx5ooGb4Ew=
|
||||
gogs.inhome.blapointe.com/local/router v0.0.0-20230410162418-08ccdc13df87/go.mod h1:FCXhK6+lzJcxBsptnei6vw9pChuQvr4NtuosngjVJDk=
|
||||
gogs.inhome.blapointe.com/local/storage v0.0.0-20230410162102-db39d7b02e29 h1:SPSz7yQsEfScqyLlBS5uNSOGeT203BkIkFCL8jrm/FA=
|
||||
gogs.inhome.blapointe.com/local/storage v0.0.0-20230410162102-db39d7b02e29/go.mod h1:zk8Fe2Ezc2f6oOe2yllsbEhXqssUU1K2faoS0eQ9alY=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/oauth2 v0.0.0-20181120190819-8f65e3013eba h1:YDkOrzGLLYybtuP6ZgebnO4OWYEYVMFSniazXsxrFN8=
|
||||
golang.org/x/oauth2 v0.0.0-20181120190819-8f65e3013eba/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20181120235003-faade3cbb06a h1:yMfgT1baklxtECXVk3UtZBELVXtVhDbK3/7xLFkFypw=
|
||||
google.golang.org/api v0.0.0-20181120235003-faade3cbb06a/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
5
main.go
|
|
@ -1,8 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"local/todo-server/config"
|
||||
"local/todo-server/server"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/config"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
|
@ -12,6 +12,7 @@ func main() {
|
|||
if err := s.Routes(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go s.Async()
|
||||
log.Println("listening on", config.Port)
|
||||
if err := http.ListenAndServe(config.Port, s); err != nil {
|
||||
panic(err)
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title>todo breel</title>
|
||||
<link rel="stylesheet" type="text/css" href="/themes/default/style.css?v=1.4.3" media="all"/>
|
||||
<link rel="stylesheet" type="text/css" href="/themes/default/print.css?v=1.4.3" media="print"/>
|
||||
<link rel="stylesheet" type="text/css" href="/themes/default/print.css?v=1.4.3" media="print"/>
|
||||
<link rel="stylesheet" type="text/css" href="/themes/default/pda.css?v=1.4.3" media="only screen and (max-device-width: 720px)"/>
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script type="text/javascript" src="/jquery/jquery-1.4.4.min.js"></script>
|
||||
<script type="text/javascript" src="/jquery/jquery-ui-1.8.7.custom.min.js"></script>
|
||||
<script type="text/javascript" src="/jquery/jquery.autocomplete-1.1.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/mytinytodo.js?v=1.4.3"></script>
|
||||
<script type="text/javascript" src="/mytinytodo_lang.php?v=1.4.3"></script>
|
||||
<script type="text/javascript" src="/mytinytodo_ajax_storage.js?v=1.4.3"></script>
|
||||
|
|
@ -71,6 +73,7 @@
|
|||
<ul class="mtt-tabs"></ul>
|
||||
<div class="mtt-tabs-add-button" title="New list"><span></span>
|
||||
</div>
|
||||
<div style="flex-grow: 100"></div>
|
||||
<div id="tabs_buttons">
|
||||
<div class="mtt-tabs-select-button mtt-tabs-button" title="Select list">
|
||||
<span></span></div>
|
||||
|
|
@ -150,7 +153,7 @@
|
|||
</div>
|
||||
</h3>
|
||||
|
||||
<form id="taskedit_form" name="edittask" method="post">
|
||||
<form id="taskedit_form" name="edittask" method="post" onsubmit="return false;">
|
||||
<input type="hidden" name="isadd" value="0"/>
|
||||
<input type="hidden" name="id" value=""/>
|
||||
<div class="form-row form-row-short">
|
||||
|
|
@ -166,6 +169,14 @@
|
|||
<span class="h">Due </span>
|
||||
<input name="duedate" id="duedate" value="" class="in100" title="Y-M-D, M/D/Y, D.M.Y, M/D, D.M" autocomplete="off"/>
|
||||
</div>
|
||||
<div class="form-row form-row-short">
|
||||
<span class="h">Loop </span>
|
||||
<input type="text" name="loop" value="" class="in100" maxlength="30"/>
|
||||
</div>
|
||||
<div class="form-row form-row-short">
|
||||
<span class="h">Cron </span>
|
||||
<input type="text" name="cron" value="" class="in100" maxlength="30"/>
|
||||
</div>
|
||||
<div class="form-row-short-end"></div>
|
||||
<div class="form-row">
|
||||
<div class="h">Task</div>
|
||||
|
|
@ -255,6 +266,8 @@
|
|||
<li class="mtt-menu-delimiter"></li>
|
||||
<li class="mtt-need-list" id="btnShowCompleted">
|
||||
<div class="menu-icon"></div>Show completed tasks</li>
|
||||
<li class="mtt-need-list" id="btnShowLooping">
|
||||
<div class="menu-icon"></div>Show looping tasks</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,839 +0,0 @@
|
|||
/*
|
||||
* jQuery Autocomplete plugin 1.1
|
||||
*
|
||||
* Copyright (c) 2009 Jörn Zaefferer
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Changes for myTinyTodo, www.mytinytodo.net
|
||||
* Copyright (c) 2010 Max Pozdeev
|
||||
* Dual licensed under the MIT and GPL licenses
|
||||
*/
|
||||
|
||||
;(function($) {
|
||||
|
||||
$.fn.extend({
|
||||
autocomplete: function(urlOrData, options) {
|
||||
var isUrl = typeof urlOrData == "string";
|
||||
var isFunc = typeof urlOrData == "function";
|
||||
options = $.extend({}, $.Autocompleter.defaults, {
|
||||
url: isUrl ? urlOrData : null,
|
||||
data: !isUrl && !isFunc ? urlOrData : null,
|
||||
func: isFunc ? urlOrData : null,
|
||||
delay: isUrl ? $.Autocompleter.defaults.delay : 10,
|
||||
max: options && !options.scroll ? 10 : 150
|
||||
}, options);
|
||||
|
||||
// if highlight is set to false, replace it with a do-nothing function
|
||||
options.highlight = options.highlight || function(value) { return value; };
|
||||
|
||||
// if the formatMatch option is not specified, then use formatItem for backwards compatibility
|
||||
options.formatMatch = options.formatMatch || options.formatItem;
|
||||
|
||||
return this.each(function() {
|
||||
new $.Autocompleter(this, options);
|
||||
});
|
||||
},
|
||||
result: function(handler) {
|
||||
return this.bind("result", handler);
|
||||
},
|
||||
search: function(handler) {
|
||||
return this.trigger("search", [handler]);
|
||||
},
|
||||
flushCache: function() {
|
||||
return this.trigger("flushCache");
|
||||
},
|
||||
setOptions: function(options){
|
||||
return this.trigger("setOptions", [options]);
|
||||
},
|
||||
unautocomplete: function() {
|
||||
return this.trigger("unautocomplete");
|
||||
}
|
||||
});
|
||||
|
||||
$.Autocompleter = function(input, options) {
|
||||
|
||||
var KEY = {
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
DEL: 46,
|
||||
TAB: 9,
|
||||
RETURN: 13,
|
||||
ESC: 27,
|
||||
COMMA: 188,
|
||||
PAGEUP: 33,
|
||||
PAGEDOWN: 34,
|
||||
BACKSPACE: 8
|
||||
};
|
||||
|
||||
// Create $ object for input element
|
||||
var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
|
||||
|
||||
var timeout;
|
||||
var previousValue = "";
|
||||
var cache = $.Autocompleter.Cache(options);
|
||||
var hasFocus = 0;
|
||||
var lastKeyPressCode;
|
||||
var config = {
|
||||
mouseDownOnSelect: false
|
||||
};
|
||||
var select = $.Autocompleter.Select(options, input, selectCurrent, config);
|
||||
|
||||
var blockSubmit;
|
||||
|
||||
// prevent form submit in opera when selecting with return key
|
||||
$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
|
||||
if (blockSubmit) {
|
||||
blockSubmit = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
|
||||
$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
|
||||
// a keypress means the input has focus
|
||||
// avoids issue where input had focus before the autocomplete was applied
|
||||
hasFocus = 1;
|
||||
// track last key pressed
|
||||
lastKeyPressCode = event.keyCode;
|
||||
switch(event.keyCode) {
|
||||
|
||||
case KEY.UP:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.prev();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.DOWN:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.next();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.PAGEUP:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.pageUp();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.PAGEDOWN:
|
||||
event.preventDefault();
|
||||
if ( select.visible() ) {
|
||||
select.pageDown();
|
||||
} else {
|
||||
onChange(0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
// matches also semicolon
|
||||
case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
|
||||
case KEY.TAB:
|
||||
case KEY.RETURN:
|
||||
if( selectCurrent() ) {
|
||||
// stop default to prevent a form submit, Opera needs special handling
|
||||
event.preventDefault();
|
||||
blockSubmit = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY.ESC:
|
||||
select.hide();
|
||||
break;
|
||||
|
||||
default:
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(onChange, options.delay);
|
||||
break;
|
||||
}
|
||||
}).focus(function(){
|
||||
// track whether the field has focus, we shouldn't process any
|
||||
// results if the field no longer has focus
|
||||
hasFocus++;
|
||||
}).blur(function() {
|
||||
hasFocus = 0;
|
||||
if (!config.mouseDownOnSelect) {
|
||||
hideResults();
|
||||
}
|
||||
}).click(function() {
|
||||
// show select when clicking in a focused field
|
||||
if ( hasFocus++ > 1 && !select.visible() ) {
|
||||
onChange(0, true);
|
||||
}
|
||||
}).bind("search", function() {
|
||||
// TODO why not just specifying both arguments?
|
||||
var fn = (arguments.length > 1) ? arguments[1] : null;
|
||||
function findValueCallback(q, data) {
|
||||
var result;
|
||||
if( data && data.length ) {
|
||||
for (var i=0; i < data.length; i++) {
|
||||
if( data[i].result.toLowerCase() == q.toLowerCase() ) {
|
||||
result = data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( typeof fn == "function" ) fn(result);
|
||||
else $input.trigger("result", result && [result.data, result.value]);
|
||||
}
|
||||
$.each(trimWords($input.val()), function(i, value) {
|
||||
request(value, findValueCallback, findValueCallback);
|
||||
});
|
||||
}).bind("flushCache", function() {
|
||||
cache.flush();
|
||||
}).bind("setOptions", function() {
|
||||
$.extend(options, arguments[1]);
|
||||
// if we've updated the data, repopulate
|
||||
if ( "data" in arguments[1] )
|
||||
cache.populate();
|
||||
}).bind("unautocomplete", function() {
|
||||
select.unbind();
|
||||
$input.unbind();
|
||||
$(input.form).unbind(".autocomplete");
|
||||
});
|
||||
|
||||
|
||||
function selectCurrent() {
|
||||
var selected = select.selected();
|
||||
if( !selected )
|
||||
return false;
|
||||
|
||||
var v = selected.result;
|
||||
previousValue = v;
|
||||
|
||||
if ( options.multiple ) {
|
||||
var words = trimWords($input.val());
|
||||
if ( words.length > 1 ) {
|
||||
var seperator = options.multipleSeparator.length;
|
||||
var cursorAt = $(input).selection().start;
|
||||
var wordAt, progress = 0;
|
||||
$.each(words, function(i, word) {
|
||||
progress += word.length;
|
||||
if (cursorAt <= progress) {
|
||||
wordAt = i;
|
||||
return false;
|
||||
}
|
||||
progress += seperator;
|
||||
});
|
||||
words[wordAt] = v;
|
||||
// TODO this should set the cursor to the right position, but it gets overriden somewhere
|
||||
//$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
|
||||
v = words.join( options.multipleSeparator );
|
||||
}
|
||||
v += options.multipleSeparator;
|
||||
}
|
||||
|
||||
$input.val(v);
|
||||
hideResultsNow();
|
||||
$input.trigger("result", [selected.data, selected.value]);
|
||||
return true;
|
||||
}
|
||||
|
||||
function onChange(crap, skipPrevCheck) {
|
||||
if( lastKeyPressCode == KEY.DEL ) {
|
||||
select.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentValue = $input.val();
|
||||
|
||||
if ( !skipPrevCheck && currentValue == previousValue )
|
||||
return;
|
||||
|
||||
previousValue = currentValue;
|
||||
|
||||
currentValue = lastWord(currentValue);
|
||||
if ( currentValue.length >= options.minChars) {
|
||||
$input.addClass(options.loadingClass);
|
||||
if (!options.matchCase)
|
||||
currentValue = currentValue.toLowerCase();
|
||||
request(currentValue, receiveData, hideResultsNow);
|
||||
} else {
|
||||
stopLoading();
|
||||
select.hide();
|
||||
}
|
||||
};
|
||||
|
||||
function trimWords(value) {
|
||||
if (!value)
|
||||
return [""];
|
||||
if (!options.multiple)
|
||||
return [$.trim(value)];
|
||||
return $.map(value.split(options.multipleSeparator), function(word) {
|
||||
return $.trim(value).length ? $.trim(word) : null;
|
||||
});
|
||||
}
|
||||
|
||||
function lastWord(value) {
|
||||
if ( !options.multiple )
|
||||
return value;
|
||||
var words = trimWords(value);
|
||||
if (words.length == 1)
|
||||
return words[0];
|
||||
var cursorAt = $(input).selection().start;
|
||||
if (cursorAt == value.length) {
|
||||
words = trimWords(value)
|
||||
} else {
|
||||
words = trimWords(value.replace(value.substring(cursorAt), ""));
|
||||
}
|
||||
return words[words.length - 1];
|
||||
}
|
||||
|
||||
// fills in the input box w/the first match (assumed to be the best match)
|
||||
// q: the term entered
|
||||
// sValue: the first matching result
|
||||
function autoFill(q, sValue){
|
||||
// autofill in the complete box w/the first match as long as the user hasn't entered in more data
|
||||
// if the last user key pressed was backspace, don't autofill
|
||||
if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
|
||||
// fill in the value (keep the case the user has typed)
|
||||
$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
|
||||
// select the portion of the value not typed by the user (so the next character will erase)
|
||||
$(input).selection(previousValue.length, previousValue.length + sValue.length);
|
||||
}
|
||||
};
|
||||
|
||||
function hideResults() {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(hideResultsNow, 200);
|
||||
};
|
||||
|
||||
function hideResultsNow() {
|
||||
var wasVisible = select.visible();
|
||||
select.hide();
|
||||
clearTimeout(timeout);
|
||||
stopLoading();
|
||||
if (options.mustMatch) {
|
||||
// call search and run callback
|
||||
$input.search(
|
||||
function (result){
|
||||
// if no value found, clear the input box
|
||||
if( !result ) {
|
||||
if (options.multiple) {
|
||||
var words = trimWords($input.val()).slice(0, -1);
|
||||
$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
|
||||
}
|
||||
else {
|
||||
$input.val( "" );
|
||||
$input.trigger("result", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function receiveData(q, data) {
|
||||
if ( data && data.length && hasFocus ) {
|
||||
stopLoading();
|
||||
select.display(data, q);
|
||||
autoFill(q, data[0].value);
|
||||
select.show();
|
||||
} else {
|
||||
hideResultsNow();
|
||||
}
|
||||
};
|
||||
|
||||
function request(term, success, failure) {
|
||||
if (!options.matchCase)
|
||||
term = term.toLowerCase();
|
||||
var data = cache.load(term);
|
||||
// recieve the cached data
|
||||
if (data && data.length) {
|
||||
success(term, data);
|
||||
}
|
||||
// if function was supplied
|
||||
else if(options.func)
|
||||
{
|
||||
var extraParams = {
|
||||
timestamp: +new Date()
|
||||
};
|
||||
$.each(options.extraParams, function(key, param) {
|
||||
extraParams[key] = typeof param == "function" ? param() : param;
|
||||
});
|
||||
|
||||
options.func({
|
||||
data: $.extend({
|
||||
q: lastWord(term),
|
||||
limit: options.max
|
||||
}, extraParams)},
|
||||
function(data){
|
||||
var parsed = options.parse && options.parse(data) || parse(data);
|
||||
cache.add(term, parsed)
|
||||
success(term, parsed);
|
||||
}
|
||||
);
|
||||
}
|
||||
// if an AJAX url has been supplied, try loading the data now
|
||||
else if( (typeof options.url == "string") && (options.url.length > 0) ){
|
||||
|
||||
var extraParams = {
|
||||
timestamp: +new Date()
|
||||
};
|
||||
$.each(options.extraParams, function(key, param) {
|
||||
extraParams[key] = typeof param == "function" ? param() : param;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
// try to leverage ajaxQueue plugin to abort previous requests
|
||||
mode: "abort",
|
||||
// limit abortion to this input
|
||||
port: "autocomplete" + input.name,
|
||||
dataType: options.dataType,
|
||||
url: options.url,
|
||||
data: $.extend({
|
||||
q: lastWord(term),
|
||||
limit: options.max
|
||||
}, extraParams),
|
||||
success: function(data) {
|
||||
var parsed = options.parse && options.parse(data) || parse(data);
|
||||
cache.add(term, parsed);
|
||||
success(term, parsed);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
|
||||
select.emptyList();
|
||||
failure(term);
|
||||
}
|
||||
};
|
||||
|
||||
function parse(data) {
|
||||
var parsed = [];
|
||||
var rows = data.split("\n");
|
||||
for (var i=0; i < rows.length; i++) {
|
||||
var row = $.trim(rows[i]);
|
||||
if (row) {
|
||||
row = row.split("|");
|
||||
parsed[parsed.length] = {
|
||||
data: row,
|
||||
value: row[0],
|
||||
result: options.formatResult && options.formatResult(row, row[0]) || row[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
};
|
||||
|
||||
function stopLoading() {
|
||||
$input.removeClass(options.loadingClass);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
$.Autocompleter.defaults = {
|
||||
inputClass: "ac_input",
|
||||
resultsClass: "ac_results",
|
||||
loadingClass: "ac_loading",
|
||||
minChars: 1,
|
||||
delay: 400,
|
||||
matchCase: false,
|
||||
matchSubset: true,
|
||||
matchContains: false,
|
||||
cacheLength: 10,
|
||||
max: 100,
|
||||
mustMatch: false,
|
||||
extraParams: {},
|
||||
selectFirst: true,
|
||||
formatItem: function(row) { return row[0]; },
|
||||
formatMatch: null,
|
||||
autoFill: false,
|
||||
width: 0,
|
||||
multiple: false,
|
||||
multipleSeparator: ", ",
|
||||
highlight: function(value, term) {
|
||||
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
|
||||
},
|
||||
scroll: true,
|
||||
scrollHeight: 180
|
||||
};
|
||||
|
||||
$.Autocompleter.Cache = function(options) {
|
||||
|
||||
var data = {};
|
||||
var length = 0;
|
||||
|
||||
function matchSubset(s, sub) {
|
||||
if (!options.matchCase)
|
||||
s = s.toLowerCase();
|
||||
var i = s.indexOf(sub);
|
||||
if (options.matchContains == "word"){
|
||||
i = s.toLowerCase().search("\\b" + sub.toLowerCase());
|
||||
}
|
||||
if (i == -1) return false;
|
||||
return i == 0 || options.matchContains;
|
||||
};
|
||||
|
||||
function add(q, value) {
|
||||
if (length > options.cacheLength){
|
||||
flush();
|
||||
}
|
||||
if (!data[q]){
|
||||
length++;
|
||||
}
|
||||
data[q] = value;
|
||||
}
|
||||
|
||||
function populate(){
|
||||
if( !options.data ) return false;
|
||||
// track the matches
|
||||
var stMatchSets = {},
|
||||
nullData = 0;
|
||||
|
||||
// no url was specified, we need to adjust the cache length to make sure it fits the local data store
|
||||
if( !options.url && !options.func ) options.cacheLength = 1;
|
||||
|
||||
// track all options for minChars = 0
|
||||
stMatchSets[""] = [];
|
||||
|
||||
// loop through the array and create a lookup structure
|
||||
for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
|
||||
var rawValue = options.data[i];
|
||||
// if rawValue is a string, make an array otherwise just reference the array
|
||||
rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
|
||||
|
||||
var value = options.formatMatch(rawValue, i+1, options.data.length);
|
||||
if ( value === false )
|
||||
continue;
|
||||
|
||||
var firstChar = value.charAt(0).toLowerCase();
|
||||
// if no lookup array for this character exists, look it up now
|
||||
if( !stMatchSets[firstChar] )
|
||||
stMatchSets[firstChar] = [];
|
||||
|
||||
// if the match is a string
|
||||
var row = {
|
||||
value: value,
|
||||
data: rawValue,
|
||||
result: options.formatResult && options.formatResult(rawValue) || value
|
||||
};
|
||||
|
||||
// push the current match into the set list
|
||||
stMatchSets[firstChar].push(row);
|
||||
|
||||
// keep track of minChars zero items
|
||||
if ( nullData++ < options.max ) {
|
||||
stMatchSets[""].push(row);
|
||||
}
|
||||
};
|
||||
|
||||
// add the data items to the cache
|
||||
$.each(stMatchSets, function(i, value) {
|
||||
// increase the cache size
|
||||
options.cacheLength++;
|
||||
// add to the cache
|
||||
add(i, value);
|
||||
});
|
||||
}
|
||||
|
||||
// populate any existing data
|
||||
setTimeout(populate, 25);
|
||||
|
||||
function flush(){
|
||||
data = {};
|
||||
length = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
flush: flush,
|
||||
add: add,
|
||||
populate: populate,
|
||||
load: function(q) {
|
||||
if (!options.cacheLength || !length)
|
||||
return null;
|
||||
/*
|
||||
* if dealing w/local data and matchContains than we must make sure
|
||||
* to loop through all the data collections looking for matches
|
||||
*/
|
||||
if( (!options.url && !options.func) && options.matchContains ){
|
||||
// track all matches
|
||||
var csub = [];
|
||||
// loop through all the data grids for matches
|
||||
for( var k in data ){
|
||||
// don't search through the stMatchSets[""] (minChars: 0) cache
|
||||
// this prevents duplicates
|
||||
if( k.length > 0 ){
|
||||
var c = data[k];
|
||||
$.each(c, function(i, x) {
|
||||
// if we've got a match, add it to the array
|
||||
if (matchSubset(x.value, q)) {
|
||||
csub.push(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return csub;
|
||||
} else
|
||||
// if the exact item exists, use it
|
||||
if (data[q]){
|
||||
return data[q];
|
||||
} else
|
||||
if (options.matchSubset) {
|
||||
for (var i = q.length - 1; i >= options.minChars; i--) {
|
||||
var c = data[q.substr(0, i)];
|
||||
if (c) {
|
||||
var csub = [];
|
||||
$.each(c, function(i, x) {
|
||||
if (matchSubset(x.value, q)) {
|
||||
csub[csub.length] = x;
|
||||
}
|
||||
});
|
||||
return csub;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$.Autocompleter.Select = function (options, input, select, config) {
|
||||
var CLASSES = {
|
||||
ACTIVE: "ac_over"
|
||||
};
|
||||
|
||||
var listItems,
|
||||
active = -1,
|
||||
data,
|
||||
term = "",
|
||||
needsInit = true,
|
||||
element,
|
||||
list;
|
||||
|
||||
// Create results
|
||||
function init() {
|
||||
if (!needsInit)
|
||||
return;
|
||||
element = $("<div/>")
|
||||
.hide()
|
||||
.addClass(options.resultsClass)
|
||||
.css("position", "absolute")
|
||||
.appendTo(document.body);
|
||||
|
||||
list = $("<ul/>").appendTo(element).mouseover( function(event) {
|
||||
if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
|
||||
active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
|
||||
$(target(event)).addClass(CLASSES.ACTIVE);
|
||||
}
|
||||
}).click(function(event) {
|
||||
$(target(event)).addClass(CLASSES.ACTIVE);
|
||||
select();
|
||||
// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
|
||||
input.focus();
|
||||
return false;
|
||||
}).mousedown(function() {
|
||||
config.mouseDownOnSelect = true;
|
||||
}).mouseup(function() {
|
||||
config.mouseDownOnSelect = false;
|
||||
});
|
||||
|
||||
if( options.width > 0 )
|
||||
element.css("width", options.width);
|
||||
|
||||
needsInit = false;
|
||||
}
|
||||
|
||||
function target(event) {
|
||||
var element = event.target;
|
||||
while(element && element.tagName.toUpperCase() != "LI")
|
||||
element = element.parentNode;
|
||||
// more fun with IE, sometimes event.target is empty, just ignore it then
|
||||
if(!element)
|
||||
return [];
|
||||
return element;
|
||||
}
|
||||
|
||||
function moveSelect(step) {
|
||||
listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
|
||||
movePosition(step);
|
||||
var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
|
||||
if(options.scroll) {
|
||||
var offset = 0;
|
||||
listItems.slice(0, active).each(function() {
|
||||
offset += this.offsetHeight;
|
||||
});
|
||||
if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
|
||||
list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
|
||||
} else if(offset < list.scrollTop()) {
|
||||
list.scrollTop(offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function movePosition(step) {
|
||||
active += step;
|
||||
if (active < 0) {
|
||||
active = listItems.size() - 1;
|
||||
} else if (active >= listItems.size()) {
|
||||
active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function limitNumberOfItems(available) {
|
||||
return options.max && options.max < available
|
||||
? options.max
|
||||
: available;
|
||||
}
|
||||
|
||||
function fillList() {
|
||||
list.empty();
|
||||
var max = limitNumberOfItems(data.length);
|
||||
for (var i=0; i < max; i++) {
|
||||
if (!data[i])
|
||||
continue;
|
||||
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
|
||||
if ( formatted === false )
|
||||
continue;
|
||||
var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
|
||||
$.data(li, "ac_data", data[i]);
|
||||
}
|
||||
listItems = list.find("li");
|
||||
if ( options.selectFirst ) {
|
||||
listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
|
||||
active = 0;
|
||||
}
|
||||
// apply bgiframe if available
|
||||
if ( $.fn.bgiframe )
|
||||
list.bgiframe();
|
||||
}
|
||||
|
||||
return {
|
||||
display: function(d, q) {
|
||||
init();
|
||||
data = d;
|
||||
term = q;
|
||||
fillList();
|
||||
},
|
||||
next: function() {
|
||||
moveSelect(1);
|
||||
},
|
||||
prev: function() {
|
||||
moveSelect(-1);
|
||||
},
|
||||
pageUp: function() {
|
||||
if (active != 0 && active - 8 < 0) {
|
||||
moveSelect( -active );
|
||||
} else {
|
||||
moveSelect(-8);
|
||||
}
|
||||
},
|
||||
pageDown: function() {
|
||||
if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
|
||||
moveSelect( listItems.size() - 1 - active );
|
||||
} else {
|
||||
moveSelect(8);
|
||||
}
|
||||
},
|
||||
hide: function() {
|
||||
element && element.hide();
|
||||
listItems && listItems.removeClass(CLASSES.ACTIVE);
|
||||
active = -1;
|
||||
},
|
||||
visible : function() {
|
||||
return element && element.is(":visible");
|
||||
},
|
||||
current: function() {
|
||||
return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
|
||||
},
|
||||
show: function() {
|
||||
var offset = $(input).offset();
|
||||
element.css({
|
||||
width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
|
||||
top: offset.top + input.offsetHeight,
|
||||
left: offset.left
|
||||
}).show();
|
||||
if(options.scroll) {
|
||||
list.scrollTop(0);
|
||||
list.css({
|
||||
maxHeight: options.scrollHeight,
|
||||
overflow: 'auto'
|
||||
});
|
||||
|
||||
if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
|
||||
var listHeight = 0;
|
||||
listItems.each(function() {
|
||||
listHeight += this.offsetHeight;
|
||||
});
|
||||
var scrollbarsVisible = listHeight > options.scrollHeight;
|
||||
list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
|
||||
if (!scrollbarsVisible) {
|
||||
// IE doesn't recalculate width when scrollbar disappears
|
||||
listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
selected: function() {
|
||||
var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
|
||||
return selected && selected.length && $.data(selected[0], "ac_data");
|
||||
},
|
||||
emptyList: function (){
|
||||
list && list.empty();
|
||||
},
|
||||
unbind: function() {
|
||||
element && element.remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
$.fn.selection = function(start, end) {
|
||||
if (start !== undefined) {
|
||||
return this.each(function() {
|
||||
if( this.createTextRange ){
|
||||
var selRange = this.createTextRange();
|
||||
if (end === undefined || start == end) {
|
||||
selRange.move("character", start);
|
||||
selRange.select();
|
||||
} else {
|
||||
selRange.collapse(true);
|
||||
selRange.moveStart("character", start);
|
||||
selRange.moveEnd("character", end);
|
||||
selRange.select();
|
||||
}
|
||||
} else if( this.setSelectionRange ){
|
||||
this.setSelectionRange(start, end);
|
||||
} else if( this.selectionStart ){
|
||||
this.selectionStart = start;
|
||||
this.selectionEnd = end;
|
||||
}
|
||||
});
|
||||
}
|
||||
var field = this[0];
|
||||
if ( field.createTextRange ) {
|
||||
var range = document.selection.createRange(),
|
||||
orig = field.value,
|
||||
teststring = "<->",
|
||||
textLength = range.text.length;
|
||||
range.text = teststring;
|
||||
var caretAt = field.value.indexOf(teststring);
|
||||
field.value = orig;
|
||||
this.selection(caretAt, caretAt + textLength);
|
||||
return {
|
||||
start: caretAt,
|
||||
end: caretAt + textLength
|
||||
}
|
||||
} else if( field.selectionStart !== undefined ){
|
||||
return {
|
||||
start: field.selectionStart,
|
||||
end: field.selectionEnd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
This file is part of myTinyTodo.
|
||||
(C) Copyright 2009-2010 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL v2 license. See file COPYRIGHT for details.
|
||||
This file is part of myTinyTodo.
|
||||
(C) Copyright 2009-2010 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL v2 license. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
@ -50,7 +50,7 @@ function getGetParamValue(url, paramName) {
|
|||
this._lists = {};
|
||||
this._length = 0;
|
||||
this._order = [];
|
||||
this._alltasks = {id: -1, showCompl: 0, sort: 3};
|
||||
this._alltasks = {id: -1, showCompl: 0, showLooping: 0, sort: 3};
|
||||
},
|
||||
length: function () {
|
||||
return this._length;
|
||||
|
|
@ -204,7 +204,7 @@ function getGetParamValue(url, paramName) {
|
|||
|
||||
$('#search').keyup(function (event) {
|
||||
if (event.keyCode == 27) return;
|
||||
if ($(this).val() == '') $('#search_close').hide(); //actual value is only on keyup
|
||||
if ($(this).val() == '') $('#search_close').hide(); //actual value is only on keyup
|
||||
else $('#search_close').show();
|
||||
clearTimeout(searchTimer);
|
||||
searchTimer = setTimeout(function () {
|
||||
|
|
@ -308,12 +308,12 @@ function getGetParamValue(url, paramName) {
|
|||
|
||||
$('#lists li.mtt-tab .list-action').live('click', function () {
|
||||
listMenu(this);
|
||||
return false; //stop bubble to tab click
|
||||
return false; //stop bubble to tab click
|
||||
});
|
||||
|
||||
$('#list_all .list-action').click(function (event) {
|
||||
listMenu(this);
|
||||
return false; //stop bubble to tab click
|
||||
return false; //stop bubble to tab click
|
||||
});
|
||||
|
||||
//Priority popup
|
||||
|
|
@ -851,6 +851,7 @@ function getGetParamValue(url, paramName) {
|
|||
_mtt.db.request('loadTasks', {
|
||||
list: curList.id,
|
||||
compl: curList.showCompl,
|
||||
looping: curList.showLooping,
|
||||
sort: curList.sort,
|
||||
search: filter.search,
|
||||
tag: _mtt.filter.getTags(true),
|
||||
|
|
@ -875,6 +876,43 @@ function getGetParamValue(url, paramName) {
|
|||
}
|
||||
|
||||
function prepareTaskStr(item, noteExp) {
|
||||
return '' +
|
||||
'<li id="taskrow_'+item.id+'" class="task-row ' + (item.compl?'task-completed ':'') + item.dueClass + (item.note!=''?' task-has-note':'') +
|
||||
((curList.showNotes && item.note != '') || noteExp ? ' task-expanded' : '') + prepareTagsClass(item.tags_ids) + '"><div class="task-container">' +
|
||||
prepareTaskBlocks(item) + "</div></li>\n";
|
||||
}
|
||||
|
||||
function prepareTaskBlocks(item, noteExp) {
|
||||
var id = item.id;
|
||||
return ''+
|
||||
'<div class="task-left">' +
|
||||
'<div class="task-toggle"></div>' +
|
||||
'<label><input type="checkbox" '+(flag.readOnly?'disabled="disabled"':'')+(item.compl?'checked="checked"':'')+'/></label>' +
|
||||
"</div>\n" +
|
||||
|
||||
'<div class="task-middle">' +
|
||||
|
||||
'<div class="task-middle-top">' +
|
||||
'<div class="task-through">' +
|
||||
preparePrio(item.prio,id) +
|
||||
'<span class="task-title">' + prepareHtml(item.title) + '</span> ' +
|
||||
(curList.id == -1 ? '<span class="task-listname">'+ tabLists.get(item.listId).name +'</span>' : '') +
|
||||
prepareTagsStr(item) +
|
||||
'<span class="task-date">'+item.dateInlineTitle+'</span>' +
|
||||
'</div>' +
|
||||
'<div class="task-through-right">' + prepareDueDate(item) + prepareCompletedDate(item) + "</div>" +
|
||||
'</div>' +
|
||||
|
||||
'<div class="task-note-block">' +
|
||||
'<div id="tasknote'+id+'" class="task-note"><span>'+prepareHtml(item.note)+'</span></div>' +
|
||||
'<div id="tasknotearea'+id+'" class="task-note-area"><textarea id="notetext'+id+'"></textarea>'+
|
||||
'<span class="task-note-actions"><a href="#" class="mtt-action-note-save">'+_mtt.lang.get('actionNoteSave') +
|
||||
'</a> | <a href="#" class="mtt-action-note-cancel">'+_mtt.lang.get('actionNoteCancel')+'</a></span>' +
|
||||
'</div>' +
|
||||
'</div>'+
|
||||
"</div>" +
|
||||
'<div class="task-actions"><div class="taskactionbtn"></div></div>';
|
||||
/*
|
||||
// — = — = —
|
||||
var id = item.id;
|
||||
var prio = item.prio;
|
||||
|
|
@ -896,6 +934,7 @@ function getGetParamValue(url, paramName) {
|
|||
'</a> | <a href="#" class="mtt-action-note-cancel">' + _mtt.lang.get('actionNoteCancel') + '</a></span></div>' +
|
||||
'</div>' +
|
||||
"</div></li>\n";
|
||||
*/
|
||||
}
|
||||
|
||||
function prepareHtml(s) {
|
||||
|
|
@ -910,7 +949,7 @@ function getGetParamValue(url, paramName) {
|
|||
if (prio < 0) {
|
||||
cl = 'prio-neg prio-neg-' + Math.abs(prio);
|
||||
v = '−' + Math.abs(prio);
|
||||
} // − = − = −
|
||||
} // − = − = −
|
||||
else if (prio > 0) {
|
||||
cl = 'prio-pos prio-pos-' + prio;
|
||||
v = '+' + prio;
|
||||
|
|
@ -918,7 +957,7 @@ function getGetParamValue(url, paramName) {
|
|||
else {
|
||||
cl = 'prio-zero';
|
||||
v = '±0';
|
||||
} // ± = ± = ±
|
||||
} // ± = ± = ±
|
||||
return '<span class="task-prio ' + cl + '">' + v + '</span>';
|
||||
}
|
||||
|
||||
|
|
@ -943,11 +982,24 @@ function getGetParamValue(url, paramName) {
|
|||
return ' ' + a.join(' ');
|
||||
}
|
||||
|
||||
function prepareDueDate(item) {
|
||||
return prepareDuedate(item);
|
||||
}
|
||||
|
||||
function prepareDuedate(item) {
|
||||
if (!item.duedate) return '';
|
||||
return '<span class="duedate" title="' + item.dueTitle + '"><span class="duedate-arrow">→</span> ' + item.dueStr + '</span>';
|
||||
}
|
||||
|
||||
function prepareCompletedDate(item) {
|
||||
// — = — = —
|
||||
return '<span class="task-date-completed">' +
|
||||
'<span title="' + item.dateInlineTitle + '">' + item.dateInline + '</span>—' +
|
||||
'<span title="' + item.dateCompletedInlineTitle + '">' + item.dateCompletedInline + '</span>' +
|
||||
'</span>';
|
||||
}
|
||||
|
||||
|
||||
function submitNewTask(form) {
|
||||
if (form.task.value == '') return false;
|
||||
_mtt.db.request('newTask', {
|
||||
|
|
@ -1233,6 +1285,9 @@ function getGetParamValue(url, paramName) {
|
|||
case 'btnRssFeed':
|
||||
feedCurList();
|
||||
break;
|
||||
case 'btnShowLooping':
|
||||
showLoopingToggle();
|
||||
break;
|
||||
case 'btnShowCompleted':
|
||||
showCompletedToggle();
|
||||
break;
|
||||
|
|
@ -1354,6 +1409,8 @@ function getGetParamValue(url, paramName) {
|
|||
form.tags.value = item.tags.split(',').join(', ');
|
||||
form.duedate.value = item.duedate;
|
||||
form.prio.value = item.prio;
|
||||
form.loop.value = item.loop;
|
||||
form.cron.value = item.cron;
|
||||
$('#taskedit-date .date-created>span').text(item.date);
|
||||
if (item.compl) $('#taskedit-date .date-completed').show().find('span').text(item.dateCompleted);
|
||||
else $('#taskedit-date .date-completed').hide();
|
||||
|
|
@ -1370,6 +1427,8 @@ function getGetParamValue(url, paramName) {
|
|||
form.duedate.value = '';
|
||||
form.prio.value = '0';
|
||||
form.id.value = '';
|
||||
form.loop.value = '';
|
||||
form.cron.value = '';
|
||||
toggleEditAllTags(0);
|
||||
}
|
||||
|
||||
|
|
@ -1408,11 +1467,17 @@ function getGetParamValue(url, paramName) {
|
|||
if (flag.readOnly) return false;
|
||||
if (form.isadd.value != 0)
|
||||
return submitFullTask(form);
|
||||
|
||||
_mtt.db.request('editTask', {
|
||||
id: form.id.value, title: form.task.value, note: form.note.value,
|
||||
prio: form.prio.value, tags: form.tags.value, duedate: form.duedate.value
|
||||
},
|
||||
var requestBody = {
|
||||
id: form.id.value,
|
||||
title: form.task.value,
|
||||
note: form.note.value,
|
||||
prio: form.prio.value,
|
||||
tags: form.tags.value,
|
||||
duedate: form.duedate.value,
|
||||
loop: form.loop.value,
|
||||
cron: form.cron.value,
|
||||
}
|
||||
_mtt.db.request('editTask', requestBody,
|
||||
function (json) {
|
||||
if (!parseInt(json.total)) return;
|
||||
var item = json.list[0];
|
||||
|
|
@ -1531,7 +1596,9 @@ function getGetParamValue(url, paramName) {
|
|||
note: form.note.value,
|
||||
prio: form.prio.value,
|
||||
tags: form.tags.value,
|
||||
duedate: form.duedate.value
|
||||
duedate: form.duedate.value,
|
||||
loop: form.loop.value,
|
||||
cron: form.cron.value,
|
||||
}, function (json) {
|
||||
if (!parseInt(json.total)) return;
|
||||
form.task.value = '';
|
||||
|
|
@ -1621,7 +1688,7 @@ function getGetParamValue(url, paramName) {
|
|||
submenu = new mttMenu($(this).attr('submenu'));
|
||||
submenu.$caller = $(this);
|
||||
submenu.parent = menu;
|
||||
if (menu.root) submenu.root = menu.root; //!! be careful with circular references
|
||||
if (menu.root) submenu.root = menu.root; //!! be careful with circular references
|
||||
else submenu.root = menu;
|
||||
menu.submenu.push(submenu);
|
||||
submenu.ts = submenu.container.mttmenu = submenu.root.ts;
|
||||
|
|
@ -1880,6 +1947,8 @@ function getGetParamValue(url, paramName) {
|
|||
}
|
||||
if (list.showCompl) $('#btnShowCompleted').addClass('mtt-item-checked');
|
||||
else $('#btnShowCompleted').removeClass('mtt-item-checked');
|
||||
if (list.showLooping) $('#btnShowLooping').addClass('mtt-item-checked');
|
||||
else $('#btnShowLooping').removeClass('mtt-item-checked');
|
||||
}
|
||||
|
||||
function listOrderChanged(event, ui) {
|
||||
|
|
@ -1893,6 +1962,14 @@ function getGetParamValue(url, paramName) {
|
|||
_mtt.doAction('listOrderChanged', {order: order});
|
||||
}
|
||||
|
||||
function showLoopingToggle() { // todo
|
||||
var act = curList.showLooping ? 0 : 1;
|
||||
curList.showLooping = tabLists.get(curList.id).showLooping = act;
|
||||
if (act) $('#btnShowLooping').addClass('mtt-item-checked');
|
||||
else $('#btnShowLooping').removeClass('mtt-item-checked');
|
||||
loadTasks({setLooping: 1});
|
||||
}
|
||||
|
||||
function showCompletedToggle() {
|
||||
var act = curList.showCompl ? 0 : 1;
|
||||
curList.showCompl = tabLists.get(curList.id).showCompl = act;
|
||||
|
|
@ -2061,7 +2138,7 @@ function getGetParamValue(url, paramName) {
|
|||
}
|
||||
|
||||
/*
|
||||
Errors and Info messages
|
||||
Errors and Info messages
|
||||
*/
|
||||
|
||||
function flashError(str, details) {
|
||||
|
|
@ -2087,7 +2164,7 @@ function getGetParamValue(url, paramName) {
|
|||
|
||||
|
||||
/*
|
||||
Authorization
|
||||
Authorization
|
||||
*/
|
||||
function updateAccessStatus() {
|
||||
// flag.needAuth is not changed after pageload
|
||||
|
|
@ -2169,7 +2246,7 @@ function getGetParamValue(url, paramName) {
|
|||
|
||||
|
||||
/*
|
||||
Settings
|
||||
Settings
|
||||
*/
|
||||
|
||||
function showSettings() {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
})
|
||||
*/
|
||||
|
||||
$.getJSON(this.mtt.mttUrl + 'ajax.php?loadTasks&list=' + params.list + '&compl=' + params.compl + '&sort=' + params.sort + q, callback);
|
||||
$.getJSON(this.mtt.mttUrl + 'ajax.php?loadTasks&list=' + params.list + '&compl=' + params.compl + '&looping=' + params.looping + '&sort=' + params.sort + q, callback);
|
||||
},
|
||||
|
||||
|
||||
|
|
@ -64,7 +64,9 @@
|
|||
note: params.note,
|
||||
prio: params.prio,
|
||||
tags: params.tags,
|
||||
duedate: params.duedate
|
||||
duedate: params.duedate,
|
||||
loop: params.loop,
|
||||
cron: params.cron,
|
||||
},
|
||||
callback, 'json');
|
||||
},
|
||||
|
|
@ -78,7 +80,9 @@
|
|||
note: params.note,
|
||||
prio: params.prio,
|
||||
tags: params.tags,
|
||||
duedate: params.duedate
|
||||
duedate: params.duedate,
|
||||
loop: params.loop,
|
||||
cron: params.cron,
|
||||
},
|
||||
callback, 'json');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
Image files page_white_text.png and calendar.png and some icons in buttons.png
|
||||
are (or based on) icons from Silk Icons set by Mark James (http://www.famfamfam.com/lab/icons/silk/),
|
||||
licensed under the Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/).
|
||||
|
||||
Some icons in buttons.png are based on "Silk Companion 1" icons set by Damien Guard
|
||||
(http://damieng.com/creative/icons/silk-companion-1-icons), licensed under the
|
||||
Creative Commons Attribution 2.5 License (http://creativecommons.org/licenses/by/2.5/).
|
||||
|
||||
Icons in mzl.png are (or based on) icons from Mozilla Source Code,
|
||||
(http://www.mozilla.org/MPL/#source-code), licensed under the terms
|
||||
of tri-license (MPL 1.1/GPL 2.0/LGPL 2.1).
|
||||
rss.svg, rss-disabled.svg - are (or based on) icons by Icons8 from https://icons8.com/icon/13841/rss
|
||||
calendar.svg - icon by Icons8 from https://icons8.com/icon/__LA9wZgJaqd/calendar
|
||||
loading48.gif - generated at Preloaders.net
|
||||
|
||||
Other images in this directory were made by Max Pozdeev and licensed under the terms of GNU GPL v2+.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<polyline points="15 4, 15 9, 2 9" stroke-width="1.5" stroke="#000" fill="none" />
|
||||
<polyline points="6 5, 1 9, 6 13" stroke-width="1.5" stroke="#000" fill="none" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 237 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<polygon points="10 3, 4 8, 10 13" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 118 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<polygon points="6 3, 12 8, 6 13" fill="#000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 117 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<!--<rect x="0" y="0" width="16" height="16" fill="red"/>-->
|
||||
<rect x="1" y="2" width="14" height="12" rx="3" fill="#999999"/>
|
||||
<polygon points="4 6, 12 6, 8 10" fill="#ffffff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 248 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<polygon points="4 6, 12 6, 8 10" fill="#888888"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 121 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
|
||||
<polygon points="0 2, 8 2, 4 6" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 115 B |
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path fill="#fff" d="M0.5 1.5H15.5V14.5H0.5z"/>
|
||||
<path fill="#788b9c" d="M15,2v12H1V2H15 M16,1H0v14h16V1L16,1z"/>
|
||||
<path fill="#f78f8f" d="M0.5 1.5H15.5V4.5H0.5z"/>
|
||||
<path fill="#c74343" d="M15,2v2H1V2H15 M16,1H0v4h16V1L16,1z"/>
|
||||
<path fill="#c5d4de" d="M5 7H6V8H5zM7 7H8V8H7zM9 7H10V8H9zM11 7H12V8H11zM3 9H4V10H3zM5 9H6V10H5zM7 9H8V10H7zM9 9H10V10H9zM11 9H12V10H11zM3 11H4V12H3zM5 11H6V12H5zM7 11H8V12H7zM9 11H10V12H9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 491 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<polyline points="4 8, 7 12, 13 5" fill="none" stroke-width="2" stroke="#000" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 149 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<g stroke-width="1.5" fill="none">
|
||||
<path d="M12.0 12.0l-8-8" stroke="#7f7f7f"/>
|
||||
<path d="M4.0 12.0l+8-8" stroke="#7f7f7f"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 196 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<g stroke-width="1.5" fill="none">
|
||||
<path d="M12.0 12.0l-8-8" stroke="#000"/>
|
||||
<path d="M4.0 12.0l+8-8" stroke="#000"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 190 B |
|
|
@ -1 +1 @@
|
|||
Direct access disallowed!
|
||||
Place for Images
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" >
|
||||
<!-- <rect x="0" y="0" width="16" height="16" fill="lightpink" /> -->
|
||||
<g stroke="#7f7f7f" fill="none">
|
||||
<polyline points="10.5 1, 1 1, 1 15, 13 15, 13 7.5" stroke-width="1.0" stroke-linejoin="round"/>
|
||||
<g stroke-width="1.0" >
|
||||
<polyline points="7 7, 6 10, 9 9, 15 3, 13 1, 7 7, 6 10" />
|
||||
<line x1="7" y1="7" x2="9" y2="9" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 406 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14">
|
||||
<!--<rect x="0" y="0" width="14" height="14" fill="lightpink"/>-->
|
||||
<polyline points="5 2, 10 7, 5 12" stroke-width="1.5" stroke="#000" fill="none" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 217 B |
|
|
@ -0,0 +1,19 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<linearGradient id="gradient1" x1="10%" y1="90%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stop-color="#fff"/>
|
||||
<stop offset="100%" stop-color="#eee"/>
|
||||
</linearGradient>
|
||||
<style type="text/css"><![CDATA[
|
||||
.line1 { stroke:#333; stroke-width:0.3; }
|
||||
]]></style>
|
||||
</defs>
|
||||
|
||||
<polygon points="2 1, 11 1, 14 4, 14 15, 2 15" stroke-width="0.2" stroke="#333" fill="#fff" fill-opacity="0.0" />
|
||||
<line x1="5" y1="4" x2="10" y2="4" class="line1"/>
|
||||
<line x1="5" y1="6" x2="11" y2="6" class="line1"/>
|
||||
<line x1="5" y1="8" x2="11" y2="8" class="line1"/>
|
||||
<line x1="5" y1="10" x2="11" y2="10" class="line1"/>
|
||||
<line x1="5" y1="12" x2="11" y2="12" class="line1"/>
|
||||
<polygon points="3 2, 10 2, 10 5, 13 5, 13 14, 3 14" fill="url(#gradient1)" fill-opacity="0.4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 856 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<line x1="3" y1="8" x2="13" y2="8" stroke-width="2" stroke="#333" />
|
||||
<line x1="8" y1="3" x2="8" y2="13" stroke-width="2" stroke="#333" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 207 B |
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
|
||||
<title>RSS feed icon</title>
|
||||
<style type="text/css">
|
||||
.button {stroke: none; fill: #bbb;}
|
||||
.symbol {stroke: none; fill: white;}
|
||||
</style>
|
||||
|
||||
<rect class="button" width="8" height="8" rx="1.5" />
|
||||
<circle class="symbol" cx="2" cy="6" r="1" />
|
||||
<path class="symbol" d="m 1,4 a 3,3 0 0 1 3,3 h 1 a 4,4 0 0 0 -4,-4 z" />
|
||||
<path class="symbol" d="m 1,2 a 5,5 0 0 1 5,5 h 1 a 6,6 0 0 0 -6,-6 z" />
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 517 B |
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
|
||||
<title>RSS feed icon</title>
|
||||
<style type="text/css">
|
||||
.button {stroke: none; fill: orange;}
|
||||
.symbol {stroke: none; fill: white;}
|
||||
</style>
|
||||
|
||||
<rect class="button" width="8" height="8" rx="1.5" />
|
||||
<circle class="symbol" cx="2" cy="6" r="1" />
|
||||
<path class="symbol" d="m 1,4 a 3,3 0 0 1 3,3 h 1 a 4,4 0 0 0 -4,-4 z" />
|
||||
<path class="symbol" d="m 1,2 a 5,5 0 0 1 5,5 h 1 a 6,6 0 0 0 -6,-6 z" />
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 519 B |
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<g stroke-width="1.5" fill="none">
|
||||
<circle cx="8" cy="8" r="7" fill="#000"/>
|
||||
<path d="M11.0 11.0l-6-6" stroke="#ffffff"/>
|
||||
<path d="M5.0 11.0l+6-6" stroke="#ffffff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 238 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<g stroke-width="1.5" stroke="#7f7f7f" fill="none">
|
||||
<path d="M14 14l-4-4"/>
|
||||
<circle cx="7" cy="7" r="4.5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 180 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<circle cx="3" cy="8" r="1.5" fill="#333"/>
|
||||
<circle cx="8" cy="8" r="1.5" fill="#333"/>
|
||||
<circle cx="13" cy="8" r="1.5" fill="#333"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 200 B |
|
|
@ -0,0 +1,7 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<g fill="none" stroke-width="1.5" stroke="#333" stroke-linecap="round">
|
||||
<line x1="2" y1="3" x2="14" y2="3"/>
|
||||
<line x1="2" y1="8" x2="14" y2="8"/>
|
||||
<line x1="4" y1="13" x2="14" y2="13"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 260 B |
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14">
|
||||
<!--<rect x="0" y="0" width="14" height="14" fill="lightpink"/>-->
|
||||
<polyline points="2 6, 7 11, 12 6" stroke-width="2" stroke="#000" fill="none" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 216 B |
|
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14">
|
||||
<!--<rect x="0" y="0" width="14" height="14" fill="lightpink"/>-->
|
||||
<g fill="#000">
|
||||
<circle cx="7" cy="2" r="1.5" />
|
||||
<circle cx="7" cy="7" r="1.5" />
|
||||
<circle cx="7" cy="12" r="1.5" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 259 B |
|
|
@ -188,3 +188,34 @@ h3 {
|
|||
.mtt-notes-showhide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mtt-tab {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mtt-tabs-selected {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* BEL */
|
||||
|
||||
#taskview ,
|
||||
#bar ,
|
||||
br[clear="all"] ,
|
||||
#task_placeholder > span ,
|
||||
#mtt_body > h2:first-child {
|
||||
display: none !important;
|
||||
}
|
||||
#toolbar ,
|
||||
#taskcontainer {
|
||||
z-index: 15;
|
||||
}
|
||||
#taskcontainer {
|
||||
position: fixed;
|
||||
top: 6em;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,3 +114,48 @@ li.task-completed {
|
|||
#taskview img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 165 */
|
||||
@media print {
|
||||
|
||||
html { height:0; }
|
||||
body { height:0; min-height:0; margin:0; }
|
||||
h2{ display: none; }
|
||||
h3 { border-bottom:2px solid #777777; }
|
||||
#toolbar { display: none; }
|
||||
|
||||
.topblock { display:none; }
|
||||
.mtt-tab { display:none; }
|
||||
.mtt-tab.mtt-tabs-selected { display:block; border:none; background:none; margin:0; }
|
||||
.mtt-tab.mtt-tabs-selected a { padding:0; display:inline-block; height:auto; }
|
||||
.mtt-tab.mtt-tabs-selected .list-action { display:none; }
|
||||
.mtt-tab a span { text-align:left; padding:0; max-width:none; font-size:1.3rem; color:#000; }
|
||||
|
||||
.mtt-tabs-add-button { display:none; }
|
||||
#list_all { display:none; }
|
||||
#tabs_buttons { display:none; }
|
||||
#taskview { padding-left:0; font-weight:normal; }
|
||||
#taskview .arrdown { display:none; }
|
||||
|
||||
#tasklist { list-style-type: decimal; list-style-position: outside; }
|
||||
#tasklist li { border-bottom:none; margin-left:2.5rem; /*border-bottom:1px solid #f0f0f0;*/ }
|
||||
|
||||
div.task-note-block { border-left:1px solid #777777; background:none; padding-left:5px; margin-top:5px; padding-top:0px; font-size:9pt; color:#333333; }
|
||||
.task-middle { margin-left:0px; margin-right:3px; }
|
||||
.task-left { display:none; }
|
||||
.task-actions { display:none; }
|
||||
.task-date { white-space:nowrap; margin-left:10px; }
|
||||
#tasklist li.today, #tasklist li.past { background-color:#ffffff; border-color:#dedede; }
|
||||
.task-prio { font-weight:bold; }
|
||||
|
||||
li.task-completed { opacity:1; }
|
||||
|
||||
#footer_content { border-top:1px solid #777777; background:none; }
|
||||
#footer_content a { text-decoration:none; color:#000000; }
|
||||
#mobileordesktop { display: none; }
|
||||
|
||||
#tagcloudbtn { display:none; }
|
||||
.mtt-notes-showhide { display:none; }
|
||||
#taskview img { display:none; }
|
||||
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ a {
|
|||
.mtt-tab a {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
/*font-size: 0.9em;*/
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
|
|
@ -454,8 +454,8 @@ a {
|
|||
}
|
||||
|
||||
.mtt-taskbox-icon.mtt-icon-submittask {
|
||||
background: url(images/mzl.png) 0px -32px no-repeat;
|
||||
right: 4px;
|
||||
/*background: url(images/mzl.png) 0px -32px no-repeat;
|
||||
right: 4px;*/
|
||||
}
|
||||
|
||||
#newtask_adv span {
|
||||
|
|
@ -627,9 +627,9 @@ li.task-expanded .task-toggle {
|
|||
}
|
||||
|
||||
.task-actions {
|
||||
float: right;
|
||||
width: 20px;
|
||||
text-align: right;
|
||||
/*float: right;*/
|
||||
/*width: 20px;*/
|
||||
/*text-align: right;*/
|
||||
}
|
||||
|
||||
.task-date {
|
||||
|
|
@ -760,18 +760,20 @@ li.task-completed .task-title a {
|
|||
}
|
||||
|
||||
a.taskactionbtn {
|
||||
display: block;
|
||||
/*display: block;*/
|
||||
/*
|
||||
float: right;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
*/
|
||||
text-decoration: none;
|
||||
background: url(images/icons.gif) 0 0 no-repeat;
|
||||
display: none;
|
||||
/*background: url(images/icons.gif) 0 0 no-repeat;*/
|
||||
/*display: none;*/
|
||||
}
|
||||
|
||||
li:hover a.taskactionbtn, a.taskactionbtn.mtt-menu-button-active {
|
||||
background-position: -16px 0;
|
||||
display: block;
|
||||
/*background-position: -16px 0;*/
|
||||
/*display: block;*/
|
||||
}
|
||||
|
||||
#tasklist.filter-past li, #tasklist.filter-today li, #tasklist.filter-soon li {
|
||||
|
|
@ -794,6 +796,7 @@ li:hover a.taskactionbtn, a.taskactionbtn.mtt-menu-button-active {
|
|||
min-height: 16px;
|
||||
display: none;
|
||||
margin: .7em .5em 0 0;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
li.task-expanded .task-note-block {
|
||||
|
|
@ -1367,3 +1370,402 @@ li.mtt-item-hidden {
|
|||
min-width: 350px;
|
||||
}
|
||||
body { filter: invert(80%); background-color: #222; }
|
||||
#newtask_adv ,
|
||||
#tagcloudbtn ,
|
||||
#settings {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 165 */
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
Copyright 2009-2010,2020 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
*/
|
||||
|
||||
/* default style */
|
||||
|
||||
html { height:100%; overflow-y:scroll; font-size:14px; /* =1rem */ }
|
||||
body { margin:0px; padding:0px; height:100%; /*background-color:#fff;*/ font-family:"Helvetica Neue",helvetica,arial,sans-serif; }
|
||||
#wrapper { display:flex; flex-direction:column; align-items:center; height:100%; }
|
||||
#container { flex: 1 0 auto; width:100%; max-width:1000px; }
|
||||
#mtt_body { padding:8px; margin-bottom:8px; } /* TODO: can combine container and mtt_body */
|
||||
#footer { flex-shrink:0; width:100%; max-width:1000px; }
|
||||
|
||||
td, th, input, textarea, select { font-family:"Helvetica Neue",helvetica,arial,sans-serif; font-size:1rem; }
|
||||
form { display: inline; }
|
||||
h2,h3 { margin:0; }
|
||||
h2 { font-size:1.5rem; padding-right:10px; }
|
||||
h3 { border-bottom:2px solid #B5D5FF; margin-bottom:10px; padding:0.6rem 0; font-size:1.1rem; }
|
||||
a { color:#0000ff; cursor:pointer; text-decoration:underline; }
|
||||
|
||||
.topblock { display:flex; align-items:flex-start; margin-bottom:1rem; }
|
||||
#footer_content { background-color:#b5d5ff; padding:0.6rem; font-size:0.9rem; display:flex; justify-content:space-between; }
|
||||
#footer_content span:last-child { text-align:center; }
|
||||
#footer_content a { color:#000000; }
|
||||
#footer_content a.powered-by-link { font-weight:bold; }
|
||||
|
||||
.topblock-title { display:flex; align-items:center; }
|
||||
.topblock-bar { flex-grow:1; display:flex; justify-content:flex-start; border-bottom:1px solid #b5d5ff; padding-bottom:5px; }
|
||||
.bar-menu { flex-grow:1; display:flex; justify-content:flex-end; text-align:right; min-height:16px; /* for loading.gif */ }
|
||||
.nodecor { text-decoration:none; }
|
||||
#bar_auth::before { content:'\00a0| '; } /* = \00a0 */
|
||||
#bar_logout { display:none; }
|
||||
#mtt_body.no-need-auth #bar_auth { display:none; }
|
||||
#mtt_body.readonly .need-owner { display:none; }
|
||||
#mtt_body.readonly #bar_auth::before { display:none; }
|
||||
|
||||
#authform { overflow: hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; border-radius:2px; padding:10px; min-width:160px; box-shadow:1px 2px 5px rgba(0,0,0,0.5); }
|
||||
#authform div { padding:2px 0px; }
|
||||
#authform div.h { font-weight:bold; }
|
||||
#authform input { padding:3px; border:1px solid #ccc; border-radius:2px; }
|
||||
#authform input[type="submit"] { padding:4px; border-radius:3px; background-color:#efefef; }
|
||||
#loading { background-color:#ffffff; display:none; margin-right:6px; width:16px; height:16px; background:url(images/loading48.gif) no-repeat; background-size:16px 16px; }
|
||||
|
||||
#msg { }
|
||||
#msg .msg-text { font-weight:bold; cursor:pointer; }
|
||||
#msg .msg-details { padding:1px 4px; background-color:#fff; display:none; max-width:700px; position:absolute; z-index:2; }
|
||||
#msg.mtt-error .msg-text { background-color:#ff3333; }
|
||||
#msg.mtt-error .msg-details { border:1px solid #ff3333; }
|
||||
#msg.mtt-info .msg-text { background-color:#EFC300; }
|
||||
#msg.mtt-info .msg-details { border:1px solid #EFC300;}
|
||||
|
||||
#lists { font-size:0.95rem; display:flex; align-items:flex-start; justify-content:flex-end; }
|
||||
.tabs-n-button { flex-grow:1; display:flex; align-items:flex-start; }
|
||||
.tab-height-wrapper { box-sizing:border-box; height:2.2rem; display:flex; align-items:center; }
|
||||
.mtt-tabs { list-style:none; padding:0; margin:0; display:flex; justify-content:flex-start; flex-wrap:wrap; }
|
||||
.mtt-tabs li { margin:1px 3px 0 0; }
|
||||
.mtt-tab { background-color:#fbfbfb; border:1px solid #ededed; border-bottom:none; border-top-right-radius:8px; transition:background-color 0.1s ease-in; }
|
||||
.mtt-tab a {
|
||||
margin:0; text-decoration:none; white-space:nowrap; color:#333333; display:inline-block; outline:none;
|
||||
box-sizing:border-box; height:2.2rem; padding:1px 0.3rem 0 0.3rem; display:flex; align-items:center;
|
||||
}
|
||||
.mtt-tab a span { display:inline-block; text-align:center; min-width:75px; max-width:195px; cursor:pointer; padding:0; overflow:hidden; padding-left:0.3rem; padding-right:0.3rem;}
|
||||
.mtt-tab .list-action { display:none; width:16px; height:16px; background:transparent url(images/arrdown.svg) no-repeat; cursor:pointer; }
|
||||
.mtt-tab .list-action:hover, .mtt-tab .list-action.mtt-menu-button-active { background-image:url(images/arrdown-hover.svg); }
|
||||
.mtt-tab.mtt-tabs-selected .list-action { display:block; }
|
||||
.mtt-tab.mtt-tabs-selected { border-color:transparent; background-color:#ededed; }
|
||||
.mtt-tab:hover { background-color:#ddd; }
|
||||
.mtt-tab.mtt-tabs-selected:hover { background-color:#ededed; }
|
||||
.mtt-tabs.mtt-tabs-only-one li { display:none; }
|
||||
.mtt-tabs.mtt-tabs-only-one li.mtt-tabs-selected { display:block; }
|
||||
.mtt-tabs-hidden { display:none; }
|
||||
.mtt-tabs .mtt-list-sort-placeholder { background-color:#ddd; border:1px solid #aaa; }
|
||||
|
||||
.mtt-tabs-alltasks { margin:1px 3px 0 3px; }
|
||||
.mtt-tabs-alltasks.mtt-tab { border-top-right-radius:0px; border-top-left-radius:8px; }
|
||||
|
||||
#tabs_buttons {
|
||||
padding-left:2px; padding-right:2px;
|
||||
border-top:1px solid transparent;
|
||||
margin-top:1px;
|
||||
}
|
||||
|
||||
.mtt-tabs-add-button { display:inline-block; margin-top:1px; border:1px solid #ededed; border-bottom:none; border-top-right-radius: 8px; background-color:#fbfbfb;
|
||||
padding-left:3px; padding-right:3px;
|
||||
}
|
||||
.mtt-tabs-add-button span { display:block; width:16px; height:16px; background:url(images/plus.svg) no-repeat; }
|
||||
.mtt-tabs-add-button:hover { cursor:pointer; background-color:#ddd; }
|
||||
#mtt_body.readonly .mtt-tabs-add-button { display:none; }
|
||||
|
||||
.mtt-tabs-select-button>span { background:url(images/selectlist2.svg) no-repeat; }
|
||||
|
||||
.mtt-img-button { padding:4px; display:block; border-radius:4px; transition:background-color 0.1s ease-in; cursor:pointer; }
|
||||
.mtt-img-button:hover, .mtt-img-button.mtt-menu-button-active { background-color:#efefef; cursor:pointer; }
|
||||
.mtt-img-button span { display:block; width:16px; height:16px; }
|
||||
|
||||
#mtt_body.no-lists #toolbar > * { visibility:hidden; }
|
||||
#toolbar { padding:8px; border-bottom:1px solid #DEDEDE; background:#ededed; }
|
||||
#toolbar .mtt-img-button:hover { background-color:#ddd; }
|
||||
|
||||
.arrdown { display:inline-block; height:9px; width:9px; background:url(images/arrdown2.svg) no-repeat; }
|
||||
.arrdown2 { display:inline-block; height:7px; width:7px; background:url(images/arrdown2.svg) no-repeat; }
|
||||
|
||||
|
||||
.newtask-n-search-container { display:flex; justify-content:flex-end; }
|
||||
|
||||
/* Quick Task Add */
|
||||
.taskbox-c { flex-grow:1; display:flex; align-items:center; }
|
||||
.mtt-taskbox { position:relative; /*padding-left:22px;*/ /*input padding+border*/ flex-grow:1; max-width:430px; }
|
||||
#task { color:#444444; background:#fff; height:1.35rem; padding:2px 4px; padding-right:20px; border:1px solid #ccc; border-radius:3px; width:100%; margin-left:-24px; }
|
||||
#mtt_body.show-all-tasks .taskbox-c, #mtt_body.readonly .taskbox-c { display:none; }
|
||||
|
||||
.mtt-taskbox-icon { width:16px; height:16px; position:absolute; top:50%; margin-top:-8px; }
|
||||
.mtt-taskbox-icon { background:url(images/add.svg) no-repeat; opacity:0.45; right:2px; cursor:pointer; transition:opacity .1s ease-in; }
|
||||
.mtt-taskbox-icon:hover { opacity:0.7; }
|
||||
#newtask_adv { margin-left:0.5rem; }
|
||||
#newtask_adv span { background:url(images/newtask-ext.svg) no-repeat; }
|
||||
|
||||
|
||||
/* Live Search */
|
||||
#search {
|
||||
color:#444444; background:#fff; height:1.35rem; padding:2px 20px; width:100%; margin-left:-42px; /*padding+border*/
|
||||
border:1px solid #ccc; border-radius:10px;
|
||||
}
|
||||
#search_close { display:none; }
|
||||
|
||||
.mtt-searchbox { position:relative; padding-left:42px; /*input padding+border*/ }
|
||||
.mtt-searchbox-icon { width:16px; height:16px; position:absolute; top:50%; margin-top:-8px; }
|
||||
|
||||
.mtt-searchbox-icon.mtt-icon-search { background:url(images/search.svg) no-repeat; left:4px; }
|
||||
.mtt-searchbox-icon.mtt-icon-cancelsearch { background:url(images/search-cancel.svg) no-repeat; opacity:0.45; right:4px; cursor:pointer; transition:opacity .1s ease-in; }
|
||||
.mtt-searchbox-icon.mtt-icon-cancelsearch:hover { opacity:0.7; }
|
||||
|
||||
#searchbar { font-size:1rem; font-weight:normal; display:none; margin-top:0.5rem; }
|
||||
#searchbarkeyword { font-weight:bold; }
|
||||
|
||||
/* */
|
||||
#page_tasks h3 { display:flex; align-items:baseline; }
|
||||
#mtt_body.no-lists #page_tasks h3 > * { visibility:hidden; }
|
||||
.mtt-notes-showhide { font-size:1rem; font-weight:normal; margin-left:5px; margin-right:5px; }
|
||||
.mtt-notes-showhide a { text-decoration:none; border-bottom:1px dotted; }
|
||||
|
||||
|
||||
/* Tag Toolbar */
|
||||
#mtt-tag-toolbar { font-size:1.0rem; font-weight:normal; margin-top:0.5rem; line-height:1.5rem; display:flex; }
|
||||
.tag-toolbar-content { flex:auto; margin-bottom:-3px; }
|
||||
.tag-toolbar-close { flex-shrink:0; }
|
||||
.tag-toolbar-header { font-weight:normal; }
|
||||
.tag-filter { margin-left:3px; margin-right:3px; display:inline-flex; align-items:center;
|
||||
border:1px solid #ddd; border-radius:2rem; background-color:#fff; padding:0.1rem 0.5rem; margin-bottom:3px; cursor:pointer;
|
||||
}
|
||||
.tag-filter-exclude { text-decoration:line-through; }
|
||||
.mtt-filter-header { font-weight:bold; margin-right:.33rem; }
|
||||
.tag-filter-btn { margin-left:3px; display:inline-block; width:1em; height:1em; /* em! */
|
||||
background:url(images/closetag.svg) no-repeat; background-size:1em 1em; background-position:bottom center;
|
||||
opacity:0.45; transition:opacity .1s ease-in; }
|
||||
.tag-filter:hover .tag-filter-btn { opacity:0.7; }
|
||||
#mtt-tag-toolbar-close span { background:url(images/close.svg) no-repeat; }
|
||||
|
||||
|
||||
.task-toggle { visibility:hidden; cursor:pointer; width:1rem; height:1rem; display:inline-block; margin-right:2px;
|
||||
background:url(images/note-toggle.svg) no-repeat; background-size:cover; opacity:0.45;
|
||||
transition:transform .1s linear, opacity .1s ease-in;
|
||||
}
|
||||
.task-toggle::after { content:'0'; color:transparent; } /* for baseline */
|
||||
.task-toggle:hover { opacity:0.7; }
|
||||
li.task-has-note .task-toggle { visibility:visible; }
|
||||
li.task-expanded .task-toggle { transform:rotate(90deg); }
|
||||
|
||||
/* #tasklist input[type="checkbox"] { vertical-align:-1px; } /* Chrome */
|
||||
|
||||
#tasklist { list-style-type: none; margin: 0; padding: 0;}
|
||||
#tasklist li { padding:0px 2px; border-bottom:1px solid #DEDEDE; min-height:18px; margin-bottom:1px; background-color:#fff; }
|
||||
#tasklist .task-container { display:flex; justify-content:flex-start; align-items:baseline; }
|
||||
#tasklist li:hover, #tasklist li.menu-active { background-color:#f6f6f6; }
|
||||
.task-left { display:inline-block; }
|
||||
.task-middle { flex-grow:1; margin:0.6rem 0px; margin-left:5px; min-width:0; /*for long text*/ flex-basis:0; /* IE11 */}
|
||||
.task-middle-top { display:flex; align-items:baseline; }
|
||||
.task-actions { flex:0 0 1rem; margin-left:5px; }
|
||||
|
||||
.task-left label { min-width:18px; text-align:center; } /* Safari has small checkboxes */
|
||||
.task-date { color:#999999; font-size:0.8rem; margin-left:4px; display:none; }
|
||||
.task-date-completed { color:#999999; display:none; margin-left:5px; }
|
||||
.show-inline-date .task-date { display:inline; }
|
||||
.show-inline-date li.task-completed .task-date-completed { display:inline; }
|
||||
.show-inline-date li.task-completed .task-date { display:none; }
|
||||
.task-through { overflow:hidden; flex-grow:1; }
|
||||
.task-through-right { }
|
||||
.task-title a { color:#000000; }
|
||||
.task-title a:hover { color:#af0000; }
|
||||
#mtt_body.readonly #tasklist li .task-actions { display:none; }
|
||||
.task-listname { background-color:#eee; color:#555; padding:0px 3px; }
|
||||
.task-tags { padding:0px 2px; }
|
||||
.task-tags .tag { font-size:0.9rem; font-weight:bold; color:#333333; text-decoration:underline; }
|
||||
.task-tags .tag:hover { }
|
||||
.duedate { color:#333333; padding:0px; padding-left:1px; margin-left:5px; white-space:nowrap; }
|
||||
.duedate:before { content:'\2192\20'; }
|
||||
li.task-completed .duedate { /*font-size:0.8rem;*/ display:none; }
|
||||
#tasklist li.soon .duedate { color:#008000; }
|
||||
#tasklist li.today .duedate { color:#FF0000; }
|
||||
#tasklist li.past .duedate { color:#A52A2A; }
|
||||
li.task-completed .task-middle { color:#777777;}
|
||||
li.task-completed .task-through { text-decoration:line-through; }
|
||||
li.task-completed .task-title a { color:#777777; }
|
||||
#tasklist li.task-completed { opacity:0.6; }
|
||||
#tasklist li.task-completed:hover { opacity:1.0; }
|
||||
#tasklist li.not-in-tagpreview { opacity:0.1; }
|
||||
#tasklist .mtt-task-placeholder {
|
||||
min-height:0px; padding:0px; height:18px; line-height:18px;
|
||||
background-color:#ddd; border:1px solid #aaa;
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.taskactionbtn { height:1rem; width:1rem; background:url(images/task-menu2.svg) center no-repeat; background-size:1rem; visibility:hidden; /* allocate space */
|
||||
opacity:0.45; transition:opacity .1s ease-in; }
|
||||
.taskactionbtn::after { content:'0'; color:transparent; } /* for baseline */
|
||||
li:hover .taskactionbtn { visibility:visible; }
|
||||
.taskactionbtn:hover, .taskactionbtn.mtt-menu-button-active { opacity:0.7; cursor:pointer; visibility:visible; }
|
||||
|
||||
#tasklist.filter-past li, #tasklist.filter-today li, #tasklist.filter-soon li { display:none; }
|
||||
#tasklist.filter-past li.past, #tasklist.filter-today li.today, #tasklist.filter-soon li.soon { display:block; }
|
||||
#tasklist.filter-past li.task-completed, #tasklist.filter-today li.task-completed, #tasklist.filter-soon li.task-completed { display:none; }
|
||||
|
||||
.task-note-block { margin-left:2px; color:#777777; background:url(images/note.svg) left 0px no-repeat; background-size:16px 16px;
|
||||
padding-left:19px; min-height:16px; margin-top:6px; display:none; white-space:normal; word-wrap:break-word; }
|
||||
li.task-expanded .task-note-block { display:block; }
|
||||
li.task-completed .task-note-block .task-note { text-decoration:line-through; }
|
||||
.task-note-area { display:none; margin-bottom:5px; }
|
||||
.task-note-area textarea { color:#999999; width:100%; display:block; height:65px; }
|
||||
.task-note-actions { font-size:0.8rem; }
|
||||
.hidden { display:none; }
|
||||
.invisible { visibility:hidden; }
|
||||
.in500 { width:500px; color:#444444; }
|
||||
.in100 { width:100px; color:#444444; }
|
||||
.task-note span a { color:#777777; }
|
||||
.task-note span a:hover { color:#af0000; }
|
||||
|
||||
.task-prio { padding-left:2px; padding-right:2px; margin-left:0px; margin-right:5px; cursor:default; }
|
||||
.prio-neg { background-color:#3377ff; color:#ffffff; }
|
||||
.prio-pos { background-color:#ff3333; color:#ffffff; }
|
||||
.prio-pos-1 { background-color:#ff7700; color:#ffffff; }
|
||||
.prio-zero { /*background-color:#dedede;*/ }
|
||||
.task-prio.prio-zero { display:none; }
|
||||
|
||||
.form-row { margin-top:0.6rem; }
|
||||
.form-row .h { font-weight:bold; color:#333333; }
|
||||
.form-row div.h { margin-bottom:3px; }
|
||||
.form-row-short-end { clear:both; }
|
||||
#page_taskedit .form-input { padding:3px; border:1px solid #ccc; border-radius:2px; }
|
||||
#page_taskedit select.form-input { padding:2px; }
|
||||
#page_taskedit .form-bottom-buttons input { padding:4px; border:1px solid #ccc; border-radius:3px; background-color:#efefef; margin:2px; }
|
||||
#page_taskedit .form-row .in500 { width:100%; box-sizing:border-box; }
|
||||
#page_taskedit .form-row textarea.in500 { height:200px; /*resize:none;*/ }
|
||||
#page_taskedit .form-row-short { float:left; margin-right:12px; }
|
||||
#page_taskedit .form-bottom-buttons { text-align:center; margin-top:1rem; }
|
||||
#alltags .tag { font-weight:bold; color:#333333; }
|
||||
#alltags .tag:hover { background-color:#999988; color:white; }
|
||||
.alltags-cell { width:1%; white-space:nowrap; padding-left:5px; }
|
||||
#page_taskedit.mtt-inadd .mtt-inedit { display:none; }
|
||||
#page_taskedit.mtt-inedit .mtt-inadd { display:none; }
|
||||
#taskedit-date { font-size:1rem; font-weight:normal; display:inline; color:#777; margin-left:8px; }
|
||||
|
||||
a.mtt-back-button { font-size:1rem; }
|
||||
|
||||
/* autocomplete */
|
||||
.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
|
||||
.ui-autocomplete { position: absolute; padding:0px; border:1px solid #cccccc; background-color:#f9f9f9; overflow:hidden; z-index:99999; box-shadow:1px 2px 5px rgba(0,0,0,0.5); }
|
||||
.ui-autocomplete .ui-menu-item { margin: 0px; cursor:default; overflow: hidden; }
|
||||
.ui-autocomplete .ui-menu-item-wrapper { position: relative; padding:0.3rem 4px; }
|
||||
.ui-autocomplete .ui-menu-item-wrapper.ui-state-active { background-color:#5a8df0; color:white; }
|
||||
|
||||
#priopopup { overflow: hidden; z-index:100; background-color:#f9f9f9; border:1px solid #cccccc; padding:5px; }
|
||||
#priopopup span { cursor:pointer; border:1px solid #f9f9f9; padding:1px; }
|
||||
#priopopup .prio-zero:hover { border-color:#dedede; }
|
||||
#priopopup .prio-neg:hover { border-color:#3377ff; }
|
||||
#priopopup .prio-pos:hover { border-color:#ff3333; }
|
||||
#priopopup .prio-pos-1:hover { border-color:#ff7700; }
|
||||
|
||||
#tagcloudbtn { font-size:1rem; font-weight:normal; margin-left:auto; }
|
||||
#mtt_body.show-all-tasks #tagcloudbtn { display:none; }
|
||||
#tagcloudload { display:none; height:24px; background:url(images/loading48.gif) center no-repeat; background-size:24px 24px; }
|
||||
#tagcloud {
|
||||
overflow: hidden; z-index:100; background-color:#fff; border:1px solid #cccccc; padding:5px;
|
||||
width:100%; max-width:450px; text-align:center;
|
||||
box-shadow:1px 2px 5px rgba(0,0,0,0.5);
|
||||
}
|
||||
#tagcloud.mtt-left-adjusted { margin-left:5px; }
|
||||
#tagcloud.mtt-right-adjusted { margin-right:5px; }
|
||||
#tagcloud.mtt-left-adjusted.mtt-right-adjusted { margin-bottom:5px; }
|
||||
#tagcloud .tag { margin:1px 0px; padding:2px; line-height:140%; color:black; }
|
||||
#tagcloud .tag:hover { background-color:#999988; color:white; }
|
||||
#tagcloud .w0 { font-size:80%; }
|
||||
#tagcloud .w1 { font-size:90%; }
|
||||
#tagcloud .w2 { font-size:100%; }
|
||||
#tagcloud .w3 { font-size:110%; }
|
||||
#tagcloud .w4 { font-size:120%; }
|
||||
#tagcloud .w5 { font-size:130%; }
|
||||
#tagcloud .w6 { font-size:140%; }
|
||||
#tagcloud .w7 { font-size:150%; }
|
||||
#tagcloud .w8 { font-size:160%; }
|
||||
#tagcloud .w9 { font-size:170%; }
|
||||
|
||||
#tagcloudcancel { float:right; }
|
||||
#tagcloudcancel span { background:url(images/close.svg) no-repeat; }
|
||||
|
||||
.ui-datepicker { width:220px; z-index:202; border: 1px solid #cccccc; background: #ffffff; display:none; padding:2px; box-shadow:1px 2px 5px rgba(0,0,0,0.5); border-radius:5px; }
|
||||
.ui-datepicker-trigger { cursor:pointer; vertical-align:text-bottom; margin-left:4px; margin-right:4px; width:16px; height:16px; }
|
||||
.ui-datepicker-calendar { width:100%; border-collapse:collapse; }
|
||||
.ui-datepicker-calendar thead th { text-align:center; padding:0px; font-size:0.9rem; }
|
||||
.ui-datepicker-calendar tbody td { text-align:right; padding:1px; }
|
||||
.ui-datepicker-calendar td a { display:block; text-decoration:none; color:#444444; border:1px solid #cccccc; background-color:#f9f9f9; color:#111; padding:2px; }
|
||||
.ui-datepicker-calendar td.ui-datepicker-current-day a { background-color:#EAF5FF; color:#222222; border-color:#5980FF; }
|
||||
.ui-datepicker-calendar td.ui-datepicker-today a { color:#fff; background-color:#ccc; }
|
||||
.ui-datepicker-calendar td a:hover { border-color:#5a8df0; }
|
||||
.ui-datepicker-header { padding:3px 0px; }
|
||||
.ui-datepicker-prev { position:absolute; left:2px; height:20px; text-decoration:none; }
|
||||
.ui-datepicker-next { position:absolute; right:2px; height:20px; text-decoration:none; }
|
||||
.ui-datepicker-title { text-align:center; line-height:20px; }
|
||||
.ui-icon { width:16px; height:16px; text-indent:-99999px; overflow:hidden; }
|
||||
.ui-datepicker .ui-icon-circle-triangle-w { display:block; position:absolute; top:50%; margin-top:-8px; left:50%; background:url(images/arr-left.svg) no-repeat; }
|
||||
.ui-datepicker .ui-icon-circle-triangle-e { display:block; position:absolute; top:50%; margin-top:-8px; right:50%; background:url(images/arr-right.svg) no-repeat; }
|
||||
|
||||
.mtt-menu-button {
|
||||
user-select: none;
|
||||
cursor:pointer;
|
||||
padding:4px;
|
||||
transition:background-color 0.1s ease-in;
|
||||
}
|
||||
.mtt-menu-button:hover, .mtt-menu-button.mtt-menu-button-active {
|
||||
background-color:#efefef; border-radius:4px;
|
||||
}
|
||||
|
||||
.mtt-menu-container {
|
||||
overflow:hidden; z-index:100;
|
||||
background-color:#f9f9f9; border:1px solid #cccccc; padding:2px 0px;
|
||||
box-shadow:1px 2px 5px rgba(0,0,0,0.5);
|
||||
border-radius:5px;
|
||||
user-select:none;
|
||||
}
|
||||
.mtt-menu-container.mtt-left-adjusted { margin-left:5px; }
|
||||
.mtt-menu-container.mtt-right-adjusted { margin-right:5px; }
|
||||
.mtt-menu-container.mtt-right-adjusted.mtt-left-adjusted { margin-bottom:5px; }
|
||||
.mtt-menu-container ul { list-style: none; padding:0; margin:0; }
|
||||
.mtt-menu-container li { margin:1px 0px; cursor:default; color:#000; white-space:nowrap; padding-top:0.20rem; padding-bottom:0.20rem; padding-left:28px; padding-right:28px; position:relative; }
|
||||
.mtt-menu-container li:hover, .mtt-menu-container li.mtt-menu-item-active {
|
||||
background-color:#5a8df0; color:white;
|
||||
}
|
||||
.mtt-menu-container li.mtt-item-disabled, .mtt-menu-container li.mtt-item-disabled a { color:#ACA899; }
|
||||
.mtt-menu-container a { display:block; cursor:default; text-decoration:none; outline:none; color:#000; }
|
||||
.mtt-menu-container li:hover a { color:white; }
|
||||
.mtt-menu-container li.mtt-menu-delimiter { height:0px; line-height:0; border-bottom:1px solid #cccccc; margin:2px -1px; padding:0px; font-size:0px; }
|
||||
.mtt-menu-container .menu-icon { width:16px; height:16px; position:absolute; left:6px; top:50%; margin-top:-8px; }
|
||||
li.mtt-item-checked .menu-icon { background:url(images/checkmark.svg) no-repeat; }
|
||||
li.mtt-menu-indicator .submenu-icon {
|
||||
position:absolute; right:6px; top:50%; margin-top:-8px;
|
||||
width:16px; height:16px; background:url(images/arr-right.svg) no-repeat;
|
||||
}
|
||||
li.mtt-item-hidden { display:none; }
|
||||
|
||||
#slmenucontainer li.mtt-list-hidden a { font-style:italic; }
|
||||
#cmenulistscontainer li.mtt-list-hidden { font-style:italic; }
|
||||
#mtt_body.readonly .mtt-need-list { display:none; }
|
||||
|
||||
#btnRssFeed .menu-icon { background:url(images/rss.svg) no-repeat; }
|
||||
#btnRssFeed.mtt-item-disabled .menu-icon { background:url(images/rss-disabled.svg) no-repeat; }
|
||||
|
||||
#task, #search, #page_taskedit .form-input, #page_taskedit .form-bottom-buttons input { transition: box-shadow .15s ease-in-out; }
|
||||
#task:focus, #search:focus, #page_taskedit .form-input:focus,
|
||||
#page_taskedit .form-bottom-buttons input:focus { outline:none; border-color:#5a8df0; box-shadow:0 0 0 2px rgba(90,141,240,0.7); }
|
||||
|
||||
.mtt-settings-table { width:100%; border-collapse:collapse; }
|
||||
.mtt-settings-table th, .mtt-settings-table td { border-bottom:1px solid #dedede; padding:8px; vertical-align:top; }
|
||||
.mtt-settings-table .form-bottom-buttons { border-bottom:none; text-align:center; }
|
||||
.mtt-settings-table th { text-align:left; width:210px; padding-left:8px; }
|
||||
.mtt-settings-table .descr { font-size:0.8rem; font-weight:normal; color:#222; }
|
||||
.mtt-settings-table .in350 { min-width:350px; }
|
||||
.mtt-settings-table input { padding:3px; border:1px solid #ccc; border-radius:2px; }
|
||||
.mtt-settings-table select { padding:2px; border:1px solid #ccc; border-radius:2px; }
|
||||
.mtt-settings-table .form-bottom-buttons input { padding:4px; border:1px solid #ccc; border-radius:3px; background-color:#efefef; margin:2px; }
|
||||
.mtt-settings-table input:focus, .mtt-settings-table select:focus { outline:none; border-color:#5a8df0; box-shadow:0 0 0 2px rgba(90,141,240,0.7); }
|
||||
|
||||
|
||||
/* bel post 165 */
|
||||
|
||||
.task-actions .taskactionbtn {
|
||||
width: 2.5em;
|
||||
}
|
||||
|
||||
.task-note {
|
||||
white-space: pre;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,3 +135,46 @@ h2 {
|
|||
padding-left: 0;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/* 165 */
|
||||
|
||||
body { direction:rtl; }
|
||||
h2 { padding-left:10px; padding-right:0px; }
|
||||
#loading { margin-left:6px; margin-right:0px; }
|
||||
.mtt-tabs li { margin-left:3px; margin-right:0px; }
|
||||
.mtt-tab { border-top-right-radius:0px; border-top-left-radius:8px; }
|
||||
.mtt-tabs-add-button { border-top-right-radius:0px; border-top-left-radius:8px; }
|
||||
.mtt-tabs-select-button>span { transform:rotateY(180deg); }
|
||||
|
||||
#task { padding-left:20px; padding-right:4px; }
|
||||
.mtt-taskbox-icon { left:2px; right:auto; transform:rotateY(180deg); }
|
||||
#newtask_adv { margin-left:0; margin-right:0.5rem; }
|
||||
.mtt-searchbox-icon.mtt-icon-search { right:4px; left:auto; }
|
||||
.mtt-searchbox-icon.mtt-icon-cancelsearch { left:4px; right:auto; }
|
||||
|
||||
#tagcloudbtn { margin-left:0; margin-right:auto; }
|
||||
|
||||
.task-toggle { margin-left:2px; margin-right:0; transform:rotate(180deg); }
|
||||
.task-middle { margin-left:0; margin-right:5px; }
|
||||
.task-actions { margin-left:0; margin-right:5px; }
|
||||
|
||||
.task-prio, .task-title, .task-date, .task-tags { display:inline-block; } /* TODO: fix this */
|
||||
|
||||
.task-prio { margin-left:5px; margin-right:0; }
|
||||
.task-note-block { margin-left:0; margin-right:2px; padding-left:0; padding-right:19px; background-position:right 0px;}
|
||||
.task-date { margin-left:0; margin-right:4px; }
|
||||
.duedate { margin-left:0; margin-right:5px; }
|
||||
.duedate-arrow { display:none; }
|
||||
.duedate:before { content:'\20\2190\20'; }
|
||||
.task-date-completed { margin-left:0; margin-right:5px; }
|
||||
|
||||
#tagcloud { box-shadow:-1px 2px 5px rgba(0,0,0,0.5); }
|
||||
#tagcloudcancel { float:left; }
|
||||
|
||||
#taskedit-date { float:left; }
|
||||
#page_taskedit .form-row-short { float:right; margin-left:12px; margin-right:0; }
|
||||
.alltags-cell { padding-left:0; padding-right:5px; }
|
||||
|
||||
.mtt-menu-container { box-shadow:-1px 2px 5px rgba(0,0,0,0.5); }
|
||||
.mtt-menu-container .menu-icon { left:auto; right:6px; }
|
||||
li.mtt-menu-indicator .submenu-icon { left:6px; right:auto; transform:rotate(180deg); }
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
package ajax
|
||||
|
||||
import (
|
||||
"local/storage"
|
||||
"local/todo-server/config"
|
||||
"gogs.inhome.blapointe.com/local/storage"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/config"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/task"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Ajax struct {
|
||||
|
|
@ -82,3 +85,78 @@ func has(params url.Values, k string) bool {
|
|||
_, ok := params[k]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (a *Ajax) Async() {
|
||||
var err error
|
||||
nextDue := time.Now().Add(config.Loop)
|
||||
c := time.NewTicker(config.Loop)
|
||||
c2 := time.NewTicker(config.Loop)
|
||||
for {
|
||||
c.Stop()
|
||||
c.Reset(config.Loop)
|
||||
c2.Stop()
|
||||
c2.Reset(time.Until(nextDue))
|
||||
log.Println("next loop at", time.Until(nextDue), "or", config.Loop)
|
||||
select {
|
||||
case <-c.C:
|
||||
case <-c2.C:
|
||||
}
|
||||
nextDue, err = a.loopTasks()
|
||||
if err != nil {
|
||||
log.Println("failed to loop tasks", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Ajax) loopTasks() (time.Time, error) {
|
||||
nextDue := time.Now().Add(time.Hour * 240)
|
||||
lists, err := a.storageListLists()
|
||||
if err != nil {
|
||||
return nextDue, err
|
||||
}
|
||||
for _, list := range lists {
|
||||
tasks, err := a.storageListTasks(list.UUID, func(t *task.Task) bool {
|
||||
return t.Complete
|
||||
})
|
||||
if err != nil {
|
||||
return nextDue, err
|
||||
}
|
||||
for _, task := range tasks {
|
||||
if !task.Complete {
|
||||
continue
|
||||
}
|
||||
if task.Loop == 0 && task.Cron == "" {
|
||||
continue
|
||||
}
|
||||
var nextTask time.Time
|
||||
if task.Loop > 0 {
|
||||
nextTask = task.Completed.Add(task.Loop)
|
||||
}
|
||||
if string(task.Cron) != "" {
|
||||
nextTask2 := task.Cron.Next(task.Completed)
|
||||
if nextTask2 != (time.Time{}) && (nextTask == (time.Time{}) || nextTask2.Before(nextTask)) {
|
||||
nextTask = nextTask2
|
||||
}
|
||||
}
|
||||
if time.Now().After(nextTask) {
|
||||
task.Complete = false
|
||||
task.Completed = time.Time{}
|
||||
if nextTask == (time.Time{}) {
|
||||
task.Title += " !!!INVALID CRON/LOOP!!!"
|
||||
}
|
||||
task.Index = list.NextIndex()
|
||||
if err := a.storageSetTask(list.UUID, task); err != nil {
|
||||
return nextDue, err
|
||||
}
|
||||
if err := a.storageSetList(list); err != nil {
|
||||
return nextDue, err
|
||||
}
|
||||
} else {
|
||||
if nextTask.Before(nextDue) {
|
||||
nextDue = nextTask
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextDue, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package ajax
|
||||
|
||||
import (
|
||||
"local/todo-server/config"
|
||||
"local/todo-server/server/ajax/list"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/config"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/list"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package form
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
type Cron string
|
||||
|
||||
func (c Cron) Next(since time.Time) time.Time {
|
||||
schedule, err := cron.ParseStandard(string(c))
|
||||
if err != nil {
|
||||
log.Printf("failed to parse cron %q: %v", string(c), err)
|
||||
return time.Time{}
|
||||
}
|
||||
return schedule.Next(since)
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -60,6 +61,38 @@ func ToStrArr(k string) []string {
|
|||
return outArr
|
||||
}
|
||||
|
||||
func ToDuration(s string) time.Duration {
|
||||
var d time.Duration
|
||||
for _, c := range []struct {
|
||||
key string
|
||||
d time.Duration
|
||||
}{
|
||||
{"d", time.Hour * 24},
|
||||
{"w", time.Hour * 24 * 7},
|
||||
} {
|
||||
daysPattern := regexp.MustCompile(`(^|[a-z])[0-9]+` + c.key + `($|[0-9])`)
|
||||
idxes := daysPattern.FindAllStringIndex(s, -1)
|
||||
if len(idxes) > 1 {
|
||||
return 0
|
||||
}
|
||||
for _, idx := range idxes {
|
||||
substr := s[idx[0]:idx[1]]
|
||||
for len(substr) > 0 && (substr[0] < '0' || substr[0] > '9') {
|
||||
substr = substr[1:]
|
||||
}
|
||||
for len(substr) > 0 && (substr[len(substr)-1] >= '0' && substr[len(substr)-1] <= '9') {
|
||||
substr = substr[:len(substr)-1]
|
||||
}
|
||||
s = strings.ReplaceAll(s, substr, "")
|
||||
substr = strings.TrimSuffix(substr, c.key)
|
||||
n, _ := strconv.Atoi(substr)
|
||||
d += c.d * time.Duration(n)
|
||||
}
|
||||
}
|
||||
d2, _ := time.ParseDuration(s)
|
||||
return d2 + d
|
||||
}
|
||||
|
||||
func ToTime(s string) time.Time {
|
||||
v, err := time.Parse("2006-01-02 15:04:05", s)
|
||||
if err != nil || v.IsZero() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
|
|
@ -142,3 +143,29 @@ func testReq() *http.Request {
|
|||
"d": "e, f,g"
|
||||
}`))
|
||||
}
|
||||
|
||||
func TestToDuration(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
input string
|
||||
want time.Duration
|
||||
}{
|
||||
"invalid": {},
|
||||
"simple": {input: "1s", want: time.Second},
|
||||
"compound": {input: "1m1s", want: time.Minute + time.Second},
|
||||
"compound:unsorted": {input: "1s1m", want: time.Minute + time.Second},
|
||||
"compound:extension": {input: "1d1m", want: time.Minute + time.Hour*24},
|
||||
"extension:day": {input: "1d", want: 24 * time.Hour},
|
||||
"extension:week": {input: "1w", want: 24 * 7 * time.Hour},
|
||||
"extension:week,day": {input: "1w1d", want: 24 * 8 * time.Hour},
|
||||
}
|
||||
|
||||
for name, d := range cases {
|
||||
c := d
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got := ToDuration(c.input)
|
||||
if got != c.want {
|
||||
t.Fatal(c.input, c.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package ajax
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/list"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/list"
|
||||
"net/http"
|
||||
"sort"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,20 +2,21 @@ package list
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type List struct {
|
||||
Name string `json:"name"`
|
||||
UUID string `json:"id"`
|
||||
Sort int `json:"sort"`
|
||||
Published int `json:"published"`
|
||||
ShowCompl int `json:"showCompl"`
|
||||
ShowNotes int `json:"showNotes"`
|
||||
Hidden int `json:"hidden"`
|
||||
Max int `json:"max"`
|
||||
Index int `json:"index"`
|
||||
Name string `json:"name"`
|
||||
UUID string `json:"id"`
|
||||
Sort int `json:"sort"`
|
||||
Published int `json:"published"`
|
||||
ShowCompl int `json:"showCompl"`
|
||||
ShowLooping int `json:"showLooping"`
|
||||
ShowNotes int `json:"showNotes"`
|
||||
Hidden int `json:"hidden"`
|
||||
Max int `json:"max"`
|
||||
Index int `json:"index"`
|
||||
}
|
||||
|
||||
func New(r *http.Request) (*List, error) {
|
||||
|
|
@ -41,6 +42,10 @@ func (l *List) SetShowCompl(state bool) {
|
|||
set(state, &l.ShowCompl)
|
||||
}
|
||||
|
||||
func (l *List) SetShowLooping(state bool) {
|
||||
set(state, &l.ShowLooping)
|
||||
}
|
||||
|
||||
func (l *List) SetShowNotes(state bool) {
|
||||
set(state, &l.ShowNotes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/list"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/list"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ package ajax
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"local/storage"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/list"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"gogs.inhome.blapointe.com/local/storage"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/list"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/task"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
|
|
@ -62,11 +62,11 @@ func (a *Ajax) storageListTasks(listID string, filters ...func(t *task.Task) boo
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
includeComplete := true
|
||||
includeComplete := false
|
||||
for _, f := range filters {
|
||||
t := &task.Task{Complete: true}
|
||||
if !f(t) {
|
||||
includeComplete = false
|
||||
if f(t) {
|
||||
includeComplete = true
|
||||
}
|
||||
}
|
||||
if includeComplete {
|
||||
|
|
@ -77,11 +77,16 @@ func (a *Ajax) storageListTasks(listID string, filters ...func(t *task.Task) boo
|
|||
results = append(results, completeResults...)
|
||||
}
|
||||
tasks := []*task.Task{}
|
||||
uuids := map[string]struct{}{}
|
||||
for _, result := range results {
|
||||
taskID := path.Base(result)
|
||||
if taskID == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := uuids[taskID]; ok {
|
||||
continue
|
||||
}
|
||||
uuids[taskID] = struct{}{}
|
||||
task, err := a.storageGetTask(taskID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package ajax
|
||||
|
||||
import (
|
||||
"local/todo-server/server/ajax/list"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/list"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/task"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/task"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
|
@ -20,15 +20,24 @@ type taskWithDelta struct {
|
|||
func (a *Ajax) loadTasks(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, _, _ := a.Cur(r)
|
||||
filterComplete := filterComplete(form.Get(r, "compl"))
|
||||
filterLooping := filterLooping(form.Get(r, "looping"))
|
||||
filterTags := filterTags(form.ToStrArr(form.Get(r, "t")))
|
||||
filterSubstr := filterSubstr(form.Get(r, "s"))
|
||||
tasks, err := a.storageListTasks(listID, filterComplete, filterTags, filterSubstr)
|
||||
tasks, err := a.storageListTasks(listID, filterComplete, filterTags, filterSubstr, filterLooping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"list": tasks})
|
||||
}
|
||||
|
||||
func filterLooping(looping string) func(t *task.Task) bool {
|
||||
return func(t *task.Task) bool {
|
||||
hasLoop := t.Loop > 0 || t.Cron != ""
|
||||
onlyLooping := looping == "1"
|
||||
return !onlyLooping || hasLoop
|
||||
}
|
||||
}
|
||||
|
||||
func filterComplete(compl string) func(t *task.Task) bool {
|
||||
return func(t *task.Task) bool {
|
||||
return compl == "" || !t.Complete || (compl == "1" && t.Complete)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
|
@ -23,6 +23,8 @@ type Task struct {
|
|||
Complete bool
|
||||
Note []string
|
||||
Due time.Time
|
||||
Loop time.Duration
|
||||
Cron form.Cron
|
||||
|
||||
Index int
|
||||
}
|
||||
|
|
@ -42,8 +44,9 @@ func New(r *http.Request) (*Task, error) {
|
|||
Tags: append(StrList(form.ToStrArr(form.Get(r, "tag"))), StrList(form.ToStrArr(form.Get(r, "tags")))...),
|
||||
Created: time.Now(),
|
||||
Edited: time.Now(),
|
||||
|
||||
Due: form.ToTime(form.Get(r, "duedate")),
|
||||
Due: form.ToTime(form.Get(r, "duedate")),
|
||||
Loop: form.ToDuration(form.Get(r, "loop")),
|
||||
Cron: form.Cron(form.Get(r, "cron")),
|
||||
}
|
||||
task.SetNote(form.Get(r, "note"))
|
||||
return task, task.validate()
|
||||
|
|
@ -73,7 +76,9 @@ func (t *Task) MarshalJSON() ([]byte, error) {
|
|||
// "dueClass":"",
|
||||
// "dueStr":"",
|
||||
// "dueInt":33330000,
|
||||
// "dueTitle":"Due "}
|
||||
// "dueTitle":"Due ",
|
||||
// "loop": "1m",
|
||||
// "cron": "* * * * *"}
|
||||
// ]}
|
||||
fullFormat := "02 Jan 2006 03:04 PM"
|
||||
shortFormat := "02 Jan"
|
||||
|
|
@ -109,6 +114,8 @@ func (t *Task) MarshalJSON() ([]byte, error) {
|
|||
"dueStr": t.Due.Format(shortFormat),
|
||||
"dueInt": t.Due.Unix(),
|
||||
"dueTitle": "Due ",
|
||||
"loop": t.Loop.String(),
|
||||
"cron": t.Cron,
|
||||
}
|
||||
if t.Due.IsZero() {
|
||||
for k := range m {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package ajax
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/form"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax/task"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@ package server
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"local/gziphttp"
|
||||
"local/router"
|
||||
"local/todo-server/config"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -13,6 +10,11 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gogs.inhome.blapointe.com/local/gziphttp"
|
||||
"gogs.inhome.blapointe.com/local/oauth2/oauth2client"
|
||||
"gogs.inhome.blapointe.com/local/router"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/config"
|
||||
)
|
||||
|
||||
func (s *Server) Routes() error {
|
||||
|
|
@ -22,28 +24,31 @@ func (s *Server) Routes() error {
|
|||
}{
|
||||
{
|
||||
path: "/",
|
||||
handler: s.gzip(s.index),
|
||||
handler: s.index,
|
||||
},
|
||||
{
|
||||
path: "/mytinytodo_lang.php",
|
||||
handler: s.gzip(s.lang),
|
||||
handler: s.lang,
|
||||
},
|
||||
{
|
||||
path: fmt.Sprintf("/themes/%s%s", router.Wildcard, router.Wildcard),
|
||||
handler: s.gzip(s.handleDeviceCSS),
|
||||
handler: s.handleDeviceCSS,
|
||||
},
|
||||
{
|
||||
path: fmt.Sprintf("%s%s", router.Wildcard, router.Wildcard),
|
||||
handler: s.gzip(s.phpProxy),
|
||||
handler: s.phpProxy,
|
||||
},
|
||||
{
|
||||
path: "/ajax.php",
|
||||
handler: s.gzip(s.HandleAjax),
|
||||
handler: s.HandleAjax,
|
||||
},
|
||||
}
|
||||
|
||||
for _, route := range routes {
|
||||
if err := s.Add(route.path, route.handler); err != nil {
|
||||
handler := route.handler
|
||||
handler = s.gzip(handler)
|
||||
handler = s.oauth(handler)
|
||||
if err := s.Add(route.path, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -79,6 +84,10 @@ func (s *Server) lang(w http.ResponseWriter, r *http.Request) {
|
|||
`)
|
||||
}
|
||||
|
||||
func (s *Server) toindex(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (s *Server) index(w http.ResponseWriter, r *http.Request) {
|
||||
f, err := os.Open(path.Join(config.Root, "index.html"))
|
||||
if err != nil {
|
||||
|
|
@ -96,19 +105,61 @@ func (s *Server) phpProxy(w http.ResponseWriter, r *http.Request) {
|
|||
s.static(w, r)
|
||||
return
|
||||
}
|
||||
url, err := url.Parse(config.MyTinyTodo)
|
||||
url, err := url.Parse("http://127.0.0.1:64123")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
} else {
|
||||
log.Println("WOULD proxy", url.String(), r.URL.Path)
|
||||
s.index(w, r)
|
||||
s.toindex(w, r)
|
||||
//proxy := httputil.NewSingleHostReverseProxy(url)
|
||||
//proxy.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) static(w http.ResponseWriter, r *http.Request) {
|
||||
s.fileServer.ServeHTTP(w, r)
|
||||
if err := s._static(w, r); err != nil {
|
||||
s.toindex(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) _static(w http.ResponseWriter, r *http.Request) error {
|
||||
if r.Method != http.MethodGet {
|
||||
http.FileServer(s.fileDir).ServeHTTP(w, r)
|
||||
return nil
|
||||
}
|
||||
f, err := s.fileDir.Open(path.Clean(r.URL.Path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
info, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
r.URL.Path = path.Join(r.URL.Path, "index.html")
|
||||
f, err = s.fileDir.Open(r.URL.Path)
|
||||
defer f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
gziphttp.SetContentTypeIfMedia(w, r)
|
||||
_, err = io.Copy(w, f)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Server) oauth(h http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if config.OAuth != "" {
|
||||
err := oauth2client.Authenticate(config.OAuth, r.Host, w, r)
|
||||
if err != nil {
|
||||
log.Println("oauth failure", r.Host, ":", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
h(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) gzip(h http.HandlerFunc) http.HandlerFunc {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"local/router"
|
||||
"local/todo-server/config"
|
||||
"local/todo-server/server/ajax"
|
||||
"gogs.inhome.blapointe.com/local/router"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/config"
|
||||
"gogs.inhome.blapointe.com/local/todo-server/server/ajax"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
*ajax.Ajax
|
||||
*router.Router
|
||||
fileServer http.Handler
|
||||
fileDir http.Dir
|
||||
}
|
||||
|
||||
func New() *Server {
|
||||
|
|
@ -18,10 +18,10 @@ func New() *Server {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileServer := http.FileServer(http.Dir(config.Root))
|
||||
fileDir := http.Dir(config.Root)
|
||||
return &Server{
|
||||
Ajax: ajax,
|
||||
Router: router.New(),
|
||||
fileServer: fileServer,
|
||||
Ajax: ajax,
|
||||
Router: router.New(),
|
||||
fileDir: fileDir,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit e21afea391ecac5c5f5b47639e5ce8cb8b7eb693
|
||||