Map and photo view skeleton
This commit is contained in:
parent
d2059240dd
commit
e10ff6b2c5
153
package-lock.json
generated
153
package-lock.json
generated
@ -11,7 +11,6 @@
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"fast-deep-equal": "^1.0.0",
|
||||
@ -55,14 +54,12 @@
|
||||
"asap": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
|
||||
"optional": true
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
@ -80,20 +77,17 @@
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"optional": true
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"optional": true
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||
"optional": true
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
@ -104,7 +98,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
@ -156,8 +149,7 @@
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||
"optional": true
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.1",
|
||||
@ -192,8 +184,7 @@
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
|
||||
"optional": true
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
},
|
||||
"coffeescript": {
|
||||
"version": "1.10.0",
|
||||
@ -239,8 +230,7 @@
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"optional": true
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"currently-unhandled": {
|
||||
"version": "0.4.1",
|
||||
@ -254,7 +244,6 @@
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
@ -295,7 +284,6 @@
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
@ -305,7 +293,6 @@
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
|
||||
"integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"prr": "~1.0.1"
|
||||
}
|
||||
@ -350,8 +337,7 @@
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"optional": true
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
@ -361,14 +347,12 @@
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
|
||||
"optional": true
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
|
||||
"optional": true
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"faye-websocket": {
|
||||
"version": "0.10.0",
|
||||
@ -421,14 +405,12 @@
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
|
||||
"optional": true
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
@ -462,7 +444,6 @@
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
@ -704,14 +685,12 @@
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"optional": true
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
|
||||
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ajv": "^5.3.0",
|
||||
"har-schema": "^2.0.0"
|
||||
@ -749,7 +728,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
@ -764,11 +742,15 @@
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
|
||||
"integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="
|
||||
},
|
||||
"image-size": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
|
||||
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
|
||||
"optional": true
|
||||
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w="
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "2.1.0",
|
||||
@ -816,8 +798,7 @@
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
||||
"optional": true
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"is-utf8": {
|
||||
"version": "0.2.1",
|
||||
@ -832,8 +813,7 @@
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"optional": true
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.5.5",
|
||||
@ -847,32 +827,27 @@
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
|
||||
"optional": true
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"optional": true
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
@ -995,8 +970,7 @@
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"optional": true
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.36.0",
|
||||
@ -1071,14 +1045,23 @@
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"optional": true
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"ol": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ol/-/ol-5.2.0.tgz",
|
||||
"integrity": "sha512-/sXlXKMT7W/4txYmEJiqZousQ5GScDoqVrltyQDl0himUD1oEV460bH74eD49AMm0OmQL9+TIn6DXKqOYzjTLw==",
|
||||
"requires": {
|
||||
"pbf": "3.1.0",
|
||||
"pixelworks": "1.1.0",
|
||||
"rbush": "2.0.2"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@ -1118,11 +1101,19 @@
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pbf": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pbf/-/pbf-3.1.0.tgz",
|
||||
"integrity": "sha512-/hYJmIsTmh7fMkHAWWXJ5b8IKLWdjdlAFb3IHkRBn1XUhIYBChVGfVwmHEAV3UfXTxsP/AKfYTXTS/dCPxJd5w==",
|
||||
"requires": {
|
||||
"ieee754": "^1.1.6",
|
||||
"resolve-protobuf-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"optional": true
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
@ -1142,6 +1133,11 @@
|
||||
"pinkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pixelworks": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pixelworks/-/pixelworks-1.1.0.tgz",
|
||||
"integrity": "sha1-Hwla1I3Ki/ihyCWOAJIDGkTyLKU="
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz",
|
||||
@ -1154,28 +1150,29 @@
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asap": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"protocol-buffers-schema": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz",
|
||||
"integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w=="
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
||||
"optional": true
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.29",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
|
||||
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
|
||||
"optional": true
|
||||
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
||||
"optional": true
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
},
|
||||
"purecss": {
|
||||
"version": "1.0.0",
|
||||
@ -1187,6 +1184,11 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"quickselect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-1.1.1.tgz",
|
||||
"integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz",
|
||||
@ -1196,6 +1198,14 @@
|
||||
"string_decoder": "0.10"
|
||||
}
|
||||
},
|
||||
"rbush": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rbush/-/rbush-2.0.2.tgz",
|
||||
"integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==",
|
||||
"requires": {
|
||||
"quickselect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
@ -1236,7 +1246,6 @@
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
@ -1265,6 +1274,14 @@
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="
|
||||
},
|
||||
"resolve-protobuf-schema": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
|
||||
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
|
||||
"requires": {
|
||||
"protocol-buffers-schema": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||
@ -1340,7 +1357,6 @@
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
@ -1412,7 +1428,6 @@
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
@ -1427,7 +1442,6 @@
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
@ -1435,8 +1449,7 @@
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"underscore.string": {
|
||||
"version": "3.3.4",
|
||||
@ -1455,8 +1468,7 @@
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
|
||||
"optional": true
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
@ -1471,7 +1483,6 @@
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
|
@ -13,6 +13,7 @@ class PhotosWeb(object):
|
||||
self.tpl = Environment(loader=FileSystemLoader('templates'),
|
||||
autoescape=select_autoescape(['html', 'xml']))
|
||||
self.tpl.globals.update(mime2ext=self.mime2ext)
|
||||
self.tpl.filters['basename'] = os.path.basename
|
||||
self.thumb = ThumbnailView(self)
|
||||
self.photo = PhotoView(self)
|
||||
self.download = DownloadView(self)
|
||||
@ -50,6 +51,14 @@ class PhotosWeb(object):
|
||||
|
||||
yield self.tpl.get_template("monthly.html").render(images=images)
|
||||
|
||||
@cherrypy.expose
|
||||
def map(self, i=None, zoom=3):
|
||||
s = self.session()
|
||||
query = s.query(PhotoSet).filter(PhotoSet.lat != 0, PhotoSet.lon != 0)
|
||||
if i:
|
||||
query = query.filter(PhotoSet.uuid == i)
|
||||
yield self.tpl.get_template("map.html").render(images=query.all(), zoom=int(zoom))
|
||||
|
||||
|
||||
@cherrypy.popargs('item_type', 'thumb_size', 'uuid')
|
||||
class ThumbnailView(object):
|
||||
@ -81,9 +90,9 @@ class ThumbnailView(object):
|
||||
# TODO some lock around calls to this based on uuid
|
||||
thumb_path = self.master.library.make_thumb(thumb_from, thumb_size)
|
||||
if thumb_path:
|
||||
return cherrypy.lib.static.serve_file(thumb_path, 'image/jpeg')
|
||||
return cherrypy.lib.static.serve_file(thumb_path, "image/jpeg")
|
||||
else:
|
||||
return "No thumbnail available" # TODO generic svg icon
|
||||
return cherrypy.lib.static.serve_file(os.path.abspath("styles/dist/unknown.svg"), "image/svg+xml")
|
||||
|
||||
|
||||
@cherrypy.popargs('item_type', 'uuid')
|
||||
@ -164,17 +173,17 @@ def main():
|
||||
"tools.staticdir.dir": os.path.abspath("./styles/dist")}})
|
||||
|
||||
cherrypy.config.update({
|
||||
'sessionFilter.on': True,
|
||||
'tools.sessions.on': True,
|
||||
'tools.sessions.locking': 'explicit',
|
||||
'tools.sessions.timeout': 525600,
|
||||
'tools.gzip.on': True,
|
||||
# 'sessionFilter.on': True,
|
||||
# 'tools.sessions.on': True,
|
||||
# 'tools.sessions.locking': 'explicit',
|
||||
# 'tools.sessions.timeout': 525600,
|
||||
# 'tools.gzip.on': True,
|
||||
'request.show_tracebacks': True,
|
||||
'server.socket_port': args.port,
|
||||
'server.thread_pool': 25,
|
||||
'server.socket_host': '0.0.0.0',
|
||||
'server.show_tracebacks': True,
|
||||
'server.socket_timeout': 5,
|
||||
# 'server.socket_timeout': 5,
|
||||
'log.screen': False,
|
||||
'engine.autoreload.on': args.debug
|
||||
})
|
||||
|
@ -11,7 +11,7 @@ def get_jpg_info(fpath):
|
||||
"""
|
||||
Given the path to a jpg, return a dict describing it
|
||||
"""
|
||||
date, gps, dimensions = get_exif_data(fpath)
|
||||
date, gps, dimensions, orientation = get_exif_data(fpath)
|
||||
|
||||
if date is None:
|
||||
import pdb
|
||||
@ -24,7 +24,8 @@ def get_jpg_info(fpath):
|
||||
mime = magic.from_file(fpath, mime=True)
|
||||
size = os.path.getsize(fpath)
|
||||
|
||||
photo = Photo(hash=get_hash(fpath), path=fpath, format=mime, size=size, width=dimensions[0], height=dimensions[1])
|
||||
photo = Photo(hash=get_hash(fpath), path=fpath, format=mime, size=size,
|
||||
width=dimensions[0], height=dimensions[1], orientation=orientation)
|
||||
return PhotoSet(date=date, lat=lat, lon=lon, files=[photo])
|
||||
|
||||
|
||||
@ -45,13 +46,14 @@ def get_hash(path):
|
||||
|
||||
def get_exif_data(path):
|
||||
"""
|
||||
Return a (datetime, (decimal, decimal)) tuple describing the photo's exif date and gps coordinates
|
||||
Return a (datetime, (decimal, decimal), (width, height), rotation) tuple describing the photo's exif date and gps coordinates
|
||||
"""
|
||||
img = Image.open(path)
|
||||
|
||||
datestr = None
|
||||
gpsinfo = None
|
||||
dateinfo = None
|
||||
orientationinfo = 0
|
||||
sizeinfo = (img.width, img.height)
|
||||
|
||||
if img.format in ["JPEG", "PNG", "GIF"]:
|
||||
@ -74,6 +76,10 @@ def get_exif_data(path):
|
||||
raise Exception("{} has no DateTime".format(path)) # TODO how often do we hit this
|
||||
dateinfo = datetime.strptime(datestr, "%Y:%m:%d %H:%M:%S")
|
||||
|
||||
orien = exif.get("Orientation")
|
||||
if orien:
|
||||
orientationinfo = {0: 0, 8: 1, 3: 2, 6: 3}.get(int(orien), 0)
|
||||
|
||||
gps = exif.get("GPSInfo")
|
||||
if gps:
|
||||
# see https://gis.stackexchange.com/a/273402
|
||||
@ -84,16 +90,11 @@ def get_exif_data(path):
|
||||
if gps[3] == 'W':
|
||||
gps_x *= -1
|
||||
gpsinfo = (gps_y, gps_x)
|
||||
import pdb
|
||||
pdb.set_trace()
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
|
||||
if dateinfo is None:
|
||||
dateinfo = get_mtime(path)
|
||||
|
||||
return dateinfo, gpsinfo, sizeinfo
|
||||
return dateinfo, gpsinfo, sizeinfo, orientationinfo
|
||||
|
||||
|
||||
def rational64u_to_hms(values):
|
||||
|
@ -70,16 +70,20 @@ class PhotoLibrary(object):
|
||||
Create a thumbnail of the given photo, scaled/cropped to the given named style
|
||||
:return: local path to thumbnail file or None if creation failed or was blocked
|
||||
"""
|
||||
styles = {"feed": (250, 250),
|
||||
styles = {"tiny": (80, 80),
|
||||
"small": (100, 100),
|
||||
"feed": (250, 250),
|
||||
"preview": (1024, 768),
|
||||
"big": (2048, 1536)}
|
||||
dest = os.path.join(self.cache_path, "thumbs", style, "{}.jpg".format(photo.uuid))
|
||||
if os.path.exists(dest):
|
||||
return os.path.abspath(dest)
|
||||
if photo.width is None: # todo better detection of images that PIL can't open
|
||||
return None
|
||||
if photo.uuid not in self._failed_thumbs_cache[style]:
|
||||
width = min(styles[style][0], photo.width if photo.width > 0 else 999999999)
|
||||
height = min(styles[style][1], photo.height if photo.height > 0 else 999999999) # TODO this is bad.
|
||||
p = Process(target=self.gen_thumb, args=(os.path.join(self.path, photo.path), dest, width, height))
|
||||
p = Process(target=self.gen_thumb, args=(os.path.join(self.path, photo.path), dest, width, height, photo.orientation))
|
||||
p.start()
|
||||
p.join()
|
||||
if p.exitcode != 0:
|
||||
@ -89,13 +93,13 @@ class PhotoLibrary(object):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def gen_thumb(src_img, dest_img, width, height):
|
||||
def gen_thumb(src_img, dest_img, width, height, rotation):
|
||||
try:
|
||||
start = time()
|
||||
# TODO lock around the dir creation
|
||||
os.makedirs(os.path.split(dest_img)[0], exist_ok=True)
|
||||
|
||||
image = Image.open(src_img)
|
||||
image = image.rotate(90 * rotation, expand=True)
|
||||
thumb = ImageOps.fit(image, (width, height), Image.ANTIALIAS)
|
||||
thumb.save(dest_img, 'JPEG')
|
||||
print("Generated {} in {}s".format(dest_img, round(time() - start, 4)))
|
||||
|
@ -32,6 +32,7 @@ class Photo(Base):
|
||||
size = Column(Integer)
|
||||
width = Column(Integer)
|
||||
height = Column(Integer)
|
||||
orientation = Column(Integer, default=0)
|
||||
hash = Column(String(length=64), unique=True)
|
||||
path = Column(Unicode)
|
||||
format = Column(String(length=64)) # TODO how long can a mime string be
|
||||
|
4
styles/dist/unknown.svg
vendored
Normal file
4
styles/dist/unknown.svg
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-20 -20 240 240">
|
||||
<path stroke="none" d="M 200,100 100,200 0,100 100,0 200,100 z M 135.64709,74.70585 q 0,-13.52935 -10.00006,-22.52943 -9.99999,-8.99999 -24.35289,-8.99999 -17.29415,0 -30.117661,5.29409 L 69.05879,69.52938 q 9.764731,-6.23528 21.52944,-6.23528 8.82356,0 14.58824,4.82351 5.76469,4.82351 5.76469,12.70589 0,8.5883 -9.94117,21.70588 -9.94117,13.11766 -9.94117,26.76473 l 17.88236,0 q 0,-6.3529 6.9412,-14.9412 11.76471,-14.58816 12.82351,-16.35289 6.9412,-11.05887 6.9412,-23.29417 z m -22.00003,92.11771 0,-24.70585 -27.29412,0 0,24.70585 27.29412,0 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 688 B |
@ -130,7 +130,7 @@ a {
|
||||
}
|
||||
.nav-inner {
|
||||
display: block;
|
||||
padding: 2em 0;
|
||||
padding: 1.5em 0;
|
||||
}
|
||||
#nav .nav-menu-button {
|
||||
display: none;
|
||||
@ -183,7 +183,7 @@ a {
|
||||
}
|
||||
|
||||
.photo-view {
|
||||
img {
|
||||
.photo-preview img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
@ -192,4 +192,16 @@ a {
|
||||
.photo-info {
|
||||
padding: 0px 0px 0px 25px;
|
||||
}
|
||||
.photo-formats {
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
img {
|
||||
// float: left;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{% set title = "All photos" %}
|
||||
{% set subtitle = "By date, descending" %}
|
||||
|
||||
{% include "page-top.html" %}
|
||||
|
||||
|
33
templates/map.html
Normal file
33
templates/map.html
Normal file
@ -0,0 +1,33 @@
|
||||
{% set title = "Photo map" %}
|
||||
{% set subtitle = "GPS data" %}
|
||||
|
||||
{% include "page-top.html" %}
|
||||
|
||||
<div class="photo-map">
|
||||
<div id="mapdiv" style="height: 900px"></div>
|
||||
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
|
||||
<script>
|
||||
<!-- https://wiki.openstreetmap.org/wiki/OpenLayers_Marker_Example -->
|
||||
var points = [
|
||||
{%- for item in images %}
|
||||
[{{item.lon}}, {{item.lat}}],
|
||||
{%- endfor %}
|
||||
]
|
||||
var map = new OpenLayers.Map("mapdiv");
|
||||
map.addLayer(new OpenLayers.Layer.OSM());
|
||||
var markers = new OpenLayers.Layer.Markers( "Markers" );
|
||||
for(var i=0;i<points.length;i++) {
|
||||
var point = points[i]
|
||||
var lonLat = new OpenLayers.LonLat(point[0], point[1])
|
||||
.transform(new OpenLayers.Projection("EPSG:4326"),
|
||||
map.getProjectionObject());
|
||||
var marker = new OpenLayers.Marker(lonLat)
|
||||
markers.addMarker(marker);
|
||||
}
|
||||
map.addLayer(markers);
|
||||
var zoom={{ zoom or 3 }};
|
||||
map.setCenter(lonLat, zoom);
|
||||
</script>
|
||||
</div>
|
||||
|
||||
{% include "page-bottom.html" %}
|
@ -1,4 +1,5 @@
|
||||
{% set title = "Server statistics" %}
|
||||
{% set subtitle = "Placeholder" %}
|
||||
|
||||
{% include "page-top.html" %}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
<div class="pure-u-1-2">
|
||||
<h1 class="email-content-title">{{ title }}</h1>
|
||||
<p class="email-content-subtitle">
|
||||
The subheading
|
||||
{{ subtitle }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="email-content-controls pure-u-1-2">
|
||||
|
54
templates/photo.html
Normal file
54
templates/photo.html
Normal file
@ -0,0 +1,54 @@
|
||||
{% set title = "Placeholder Title" %}
|
||||
{% set subtitle = image.uuid %}
|
||||
|
||||
{% include "page-top.html" %}
|
||||
|
||||
<div class="photo-view pure-g">
|
||||
<div class="photo-preview pure-u-2-3">
|
||||
<a href="/thumb/set/big/{{ image.uuid }}.jpg">
|
||||
<img src="/thumb/set/preview/{{ image.uuid }}.jpg" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="photo-info pure-u-1-3">
|
||||
<div class="photo-metadata">
|
||||
<h2>Information</h2>
|
||||
<ul>
|
||||
<li><strong>Date:</strong> {{ image.date }} </li>
|
||||
<li><strong>Versions:</strong> {{ image.files|length }}</li>
|
||||
{% if image.lat != 0 %}
|
||||
<li><strong>Coordinates:</strong> <a href="/map?zoom=13&i={{ image.uuid }}">{{ image.lat }}, {{ image.lon }}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="photo-formats">
|
||||
<h2>Versions</h2>
|
||||
<ul class="pure-g">
|
||||
{% for img in image.files %}
|
||||
<li class="pure-u-1 pure-g">
|
||||
<a href="/thumb/one/big/{{ img.uuid }}.jpg" class="pure-g-1-4">
|
||||
<img src="/thumb/one/small/{{ img.uuid }}.jpg" />
|
||||
</a>
|
||||
<div class="pure-u-3-4">
|
||||
<div>
|
||||
{{ img.uuid }}
|
||||
</div>
|
||||
<div>
|
||||
{{ img.path | basename }}
|
||||
</div>
|
||||
<div>
|
||||
{{ img.size | filesizeformat }} - {{ img.format }}
|
||||
</div>
|
||||
<div>
|
||||
<a href="/download/one/{{ img.uuid }}">download</a>
|
||||
<a href="/download/one/{{ img.uuid }}.{{ mime2ext(img.format) }}?preview=true">preview</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% include "page-bottom.html" %}
|
Loading…
Reference in New Issue
Block a user