Config: Add CDN URL option #425 #1351

This commit is contained in:
Michael Mayer 2021-07-05 16:41:43 +02:00
parent 50560004aa
commit c87d5da2e3
59 changed files with 662 additions and 324 deletions

View file

@ -1,22 +1,22 @@
<link rel="shortcut icon" sizes="512x512" type="image/png" href="/static/img/favicon-512.png">
<link rel="shortcut icon" sizes="256x256" type="image/png" href="/static/img/favicon-256.png">
<link rel="shortcut icon" sizes="196x196" type="image/png" href="/static/img/favicon-196.png">
<link rel="shortcut icon" sizes="192x192" type="image/png" href="/static/img/favicon-192.png">
<link rel="shortcut icon" sizes="160x160" type="image/png" href="/static/img/favicon-160.png">
<link rel="shortcut icon" sizes="144x144" type="image/png" href="/static/img/favicon-144.png">
<link rel="shortcut icon" sizes="128x128" type="image/png" href="/static/img/favicon-128.png">
<link rel="shortcut icon" sizes="114x114" type="image/png" href="/static/img/favicon-114.png">
<link rel="shortcut icon" sizes="72x72" type="image/png" href="/static/img/favicon-72.png">
<link rel="shortcut icon" sizes="32x32" type="image/png" href="/static/img/favicon-32.png">
<link rel="shortcut icon" sizes="16x16" type="image/png" href="/static/img/favicon-16.png">
<link rel="apple-touch-icon" sizes="1024x1024" type="image/png" href="/static/img/logo-square-1024.png">
<link rel="apple-touch-icon" sizes="512x512" type="image/png" href="/static/img/logo-square-512.png">
<link rel="apple-touch-icon" sizes="256x256" type="image/png" href="/static/img/logo-square-256.png">
<link rel="apple-touch-icon" sizes="175x175" type="image/png" href="/static/img/logo-square-175.png">
<link rel="apple-touch-icon" sizes="128x128" type="image/png" href="/static/img/logo-square-128.png">
<link rel="apple-touch-icon" sizes="56x56" type="image/png" href="/static/img/logo-square-56.png">
<link rel="apple-touch-icon" sizes="16x16" type="image/png" href="/static/img/logo-square-16.png">
<link rel="icon" type="image/png" href="/static/img/favicon-16.png">
<link rel="shortcut icon" sizes="512x512" type="image/png" href="{{ .config.StaticUri }}/img/favicon-512.png">
<link rel="shortcut icon" sizes="256x256" type="image/png" href="{{ .config.StaticUri }}/img/favicon-256.png">
<link rel="shortcut icon" sizes="196x196" type="image/png" href="{{ .config.StaticUri }}/img/favicon-196.png">
<link rel="shortcut icon" sizes="192x192" type="image/png" href="{{ .config.StaticUri }}/img/favicon-192.png">
<link rel="shortcut icon" sizes="160x160" type="image/png" href="{{ .config.StaticUri }}/img/favicon-160.png">
<link rel="shortcut icon" sizes="144x144" type="image/png" href="{{ .config.StaticUri }}/img/favicon-144.png">
<link rel="shortcut icon" sizes="128x128" type="image/png" href="{{ .config.StaticUri }}/img/favicon-128.png">
<link rel="shortcut icon" sizes="114x114" type="image/png" href="{{ .config.StaticUri }}/img/favicon-114.png">
<link rel="shortcut icon" sizes="72x72" type="image/png" href="{{ .config.StaticUri }}/img/favicon-72.png">
<link rel="shortcut icon" sizes="32x32" type="image/png" href="{{ .config.StaticUri }}/img/favicon-32.png">
<link rel="shortcut icon" sizes="16x16" type="image/png" href="{{ .config.StaticUri }}/img/favicon-16.png">
<link rel="apple-touch-icon" sizes="1024x1024" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-1024.png">
<link rel="apple-touch-icon" sizes="512x512" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-512.png">
<link rel="apple-touch-icon" sizes="256x256" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-256.png">
<link rel="apple-touch-icon" sizes="175x175" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-175.png">
<link rel="apple-touch-icon" sizes="128x128" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-128.png">
<link rel="apple-touch-icon" sizes="56x56" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-56.png">
<link rel="apple-touch-icon" sizes="16x16" type="image/png" href="{{ .config.StaticUri }}/img/logo-square-16.png">
<link rel="icon" type="image/png" href="{{ .config.StaticUri }}/img/favicon-16.png">
<meta name="msapplication-square72x72logo" content="/static/img/favicon-72.png">
<meta name="msapplication-square160x160logo" content="/static/img/favicon-160.png">
<meta name="msapplication-square72x72logo" content="{{ .config.StaticUri }}/img/favicon-72.png">
<meta name="msapplication-square160x160logo" content="{{ .config.StaticUri }}/img/favicon-160.png">

View file

@ -26,8 +26,8 @@
{{template "favicons.tmpl" .}}
<link rel="stylesheet" href="/static/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="/static/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<link rel="stylesheet" href="{{ .config.StaticUri }}/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="{{ .config.BaseUri }}/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<script>
window.__CONFIG__ = {{ .config }};
@ -41,6 +41,6 @@
{{template "app.tmpl" .}}
<script src="/static/build/app.js?{{ .config.JSHash }}"></script>
<script src="{{ .config.StaticUri }}/build/app.js?{{ .config.JSHash }}"></script>
</body>
</html>

View file

@ -0,0 +1,92 @@
{
"short_name": "PhotoPrism",
"name": "PhotoPrism",
"description": "Browse Your Life in Pictures",
"icons": [
{
"src": "{{ .config.StaticUri }}/img/favicon-16.png",
"sizes": "16x16",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-114.png",
"sizes": "114x114",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-160.png",
"sizes": "160x160",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-167.png",
"sizes": "167x167",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-180.png",
"sizes": "180x180",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-196.png",
"sizes": "196x196",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-400.png",
"sizes": "400x400",
"type": "image/png"
},
{
"src": "{{ .config.StaticUri }}/img/favicon-512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"scope": "{{ .config.BaseUri }}/",
"start_url": "{{ .config.BaseUri }}/",
"display": "standalone",
"theme_color": "#333333",
"background_color": "#333333",
"permissions": [
"geolocation",
"downloads",
"storage"
]
}

View file

@ -9,8 +9,8 @@
{{template "favicons.tmpl" .}}
<link rel="stylesheet" href="/static/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="/static/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<link rel="stylesheet" href="{{ .config.StaticUri }}/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="{{ .config.BaseUri }}/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<script>
window.__CONFIG__ = {{ .config }};
@ -24,6 +24,6 @@
{{template "app.tmpl" .}}
<script src="/static/build/app.js?{{ .config.JSHash }}"></script>
<script src="{{ .config.StaticUri }}/build/app.js?{{ .config.JSHash }}"></script>
</body>
</html>

View file

@ -12,7 +12,7 @@
{{template "favicons.tmpl" .}}
<link rel="stylesheet" href="/static/build/app.css?{{ .config.CSSHash }}">
<link rel="stylesheet" href="{{ .config.StaticUri }}/build/app.css?{{ .config.CSSHash }}">
</head>
<body>
<div id="photoprism" class="container">

View file

@ -23,8 +23,8 @@
{{template "favicons.tmpl" .}}
<link rel="stylesheet" href="/static/build/share.css?{{ .config.CSSHash }}">
<link rel="manifest" href="/static/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<link rel="stylesheet" href="{{ .config.StaticUri }}/build/share.css?{{ .config.CSSHash }}">
<link rel="manifest" href="{{ .config.BaseUri }}/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<script>
window.__CONFIG__ = {{ .config }};
@ -38,6 +38,6 @@
{{template "app.tmpl" .}}
<script src="/static/build/share.js?{{ .config.JSHash }}"></script>
<script src="{{ .config.StaticUri }}/build/share.js?{{ .config.JSHash }}"></script>
</body>
</html>

View file

@ -28,8 +28,8 @@
{{template "favicons.tmpl" .}}
<link rel="stylesheet" href="/static/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="/static/manifest.json?{{ .config.ManifestHash }}">
<link rel="stylesheet" href="{{ .config.StaticUri }}/build/app.css?{{ .config.CSSHash }}">
<link rel="manifest" href="{{ .config.BaseUri }}/manifest.json?{{ .config.ManifestHash }}" crossorigin="use-credentials">
<script>
window.__CONFIG__ = {{ .config }};
@ -45,6 +45,6 @@
{{template "app.tmpl" .}}
<script src="/static/build/app.js?{{ .config.JSHash }}"></script>
<script src="{{ .config.StaticUri }}/build/app.js?{{ .config.JSHash }}"></script>
</body>
</html>

View file

@ -1688,6 +1688,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
"integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
"dependencies": {
"@humanwhocodes/object-schema": "^1.2.0",
"debug": "^4.1.1",
"minimatch": "^3.0.4"
},
"engines": {
"node": ">=10.10.0"
}
},
"node_modules/@humanwhocodes/object-schema": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz",
"integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w=="
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -1850,9 +1868,9 @@
}
},
"node_modules/@types/estree": {
"version": "0.0.48",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
"integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew=="
"version": "0.0.49",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.49.tgz",
"integrity": "sha512-K1AFuMe8a+pXmfHTtnwBvqoEylNKVeaiKYkjmcEAdytMQVJ/i9Fu7sc13GxgXdO49gkE7Hy8SyJonUZUn+eVaw=="
},
"node_modules/@types/json-schema": {
"version": "7.0.7",
@ -1865,9 +1883,9 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
},
"node_modules/@types/node": {
"version": "15.12.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz",
"integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg=="
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz",
"integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg=="
},
"node_modules/@types/q": {
"version": "1.5.4",
@ -1880,14 +1898,14 @@
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q=="
},
"node_modules/@vue/compiler-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.2.tgz",
"integrity": "sha512-nHmq7vLjq/XM2IMbZUcKWoH5sPXa2uR/nIKZtjbK5F3TcbnYE/zKsrSUR9WZJ03unlwotNBX1OyxVt9HbWD7/Q==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.4.tgz",
"integrity": "sha512-TnUz+1z0y74O/A4YKAbzsdUfamyHV73MihrEfvettWpm9bQKVoZd1nEmR1cGN9LsXWlwAvVQBetBlWdOjmQO5Q==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"@vue/shared": "3.1.2",
"@vue/shared": "3.1.4",
"estree-walker": "^2.0.1",
"source-map": "^0.6.1"
}
@ -1902,23 +1920,23 @@
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.2.tgz",
"integrity": "sha512-k2+SWcWH0jL6WQAX7Or2ONqu5MbtTgTO0dJrvebQYzgqaKMXNI90RNeWeCxS4BnNFMDONpHBeFgbwbnDWIkmRg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.4.tgz",
"integrity": "sha512-3tG2ScHkghhUBuFwl9KgyZhrS8CPFZsO7hUDekJgIp5b1OMkROr4AvxHu6rRMl4WkyvYkvidFNBS2VfOnwa6Kw==",
"optional": true,
"dependencies": {
"@vue/compiler-core": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-core": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.2.tgz",
"integrity": "sha512-BwXo9LFk5OSWdMyZQ4bX1ELHX0Z/9F+ld/OaVnpUPzAZCHslBYLvyKUVDwv2C/lpLjRffpC2DOUEdl1+RP1aGg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.4.tgz",
"integrity": "sha512-Box8fCuCFPp0FuimIswjDkjwiSDCBkHvt/xVALyFkYCiIMWv2eR53fIjmlsnEHhcBuZ+VgRC+UanCTcKvSA1gA==",
"optional": true,
"dependencies": {
"@vue/compiler-dom": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-dom": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"node_modules/@vue/component-compiler-utils": {
@ -1960,42 +1978,42 @@
}
},
"node_modules/@vue/reactivity": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.2.tgz",
"integrity": "sha512-glJzJoN2xE7I2lRvwKM5u1BHRPTd1yc8iaf//Lai/78/uYAvE5DXp5HzWRFOwMlbRvMGJHIQjOqoxj87cDAaag==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.4.tgz",
"integrity": "sha512-YDlgii2Cr9yAoKVZFzgY4j0mYlVT73986X3e5SPp6ifqckSEoFSUWXZK2Tb53TB/9qO29BEEbspnKD3m3wAwkA==",
"optional": true,
"peer": true,
"dependencies": {
"@vue/shared": "3.1.2"
"@vue/shared": "3.1.4"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.2.tgz",
"integrity": "sha512-gsPZG4dRIkixuuKmoj4P9IHgfT0yaFLcqWOM5F/bCk0nxQn1XtxH8oUehWuET726KhbukvDoJfe9G2CKviy80w==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.4.tgz",
"integrity": "sha512-qmVJgJuFxfT7M4qHQ4M6KqhKC66fjuswK+aBivE8dWiZ2rtIGl9gtJGpwqwjQEcKEBTOfvvrtrwBncYArJUO8Q==",
"optional": true,
"peer": true,
"dependencies": {
"@vue/reactivity": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/reactivity": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.2.tgz",
"integrity": "sha512-QvINxjLucEZFzp5f0NVu7JqWYCv5TKQfkH2FDs/N6QNE4iKcYtKrWdT0HKfABnVXG28Znqv6rIH0dH4ZAOwxpA==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.4.tgz",
"integrity": "sha512-vbmwgTxku1BU87Kw7r29adv0OIrDXCW0PslOPQT0O/9R5SqcXgS94Yj6zsztDjvghegenwIAPNLlDR1Auh5s+w==",
"optional": true,
"peer": true,
"dependencies": {
"@vue/runtime-core": "3.1.2",
"@vue/shared": "3.1.2",
"@vue/runtime-core": "3.1.4",
"@vue/shared": "3.1.4",
"csstype": "^2.6.8"
}
},
"node_modules/@vue/shared": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.2.tgz",
"integrity": "sha512-EmH/poaDWBPJaPILXNI/1fvUbArJQmmTyVCwvvyDYDFnkPoTclAbHRAtyIvqfez7jybTDn077HTNILpxlsoWhg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.4.tgz",
"integrity": "sha512-6O45kZAmkLvzGLToBxEz4lR2W6kXohCtebV2UxjH9GXjd8X9AhEn68FN9eNanFtWNzvgw1hqd6HkPRVQalqf7Q==",
"optional": true
},
"node_modules/@vvo/tzdb": {
@ -3291,9 +3309,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001241",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz",
"integrity": "sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ==",
"version": "1.0.30001242",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001242.tgz",
"integrity": "sha512-KvNuZ/duufelMB3w2xtf9gEWCSxJwUgoxOx5b6ScLXC4kPc9xsczUVCPrQU26j5kOsHM4pSUL54tAZt5THQKug==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
@ -4441,9 +4459,9 @@
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
},
"node_modules/debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dependencies": {
"ms": "2.1.2"
},
@ -4729,19 +4747,25 @@
"pug": "^3.0.2"
}
},
"node_modules/easygettext/node_modules/@types/estree": {
"version": "0.0.48",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
"integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==",
"optional": true
},
"node_modules/easygettext/node_modules/@vue/compiler-sfc": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.2.tgz",
"integrity": "sha512-SeG/2+DvwejQ7oAiSx8BrDh5qOdqCYHGClPiTvVIHTfSIHiS2JjMbCANdDCjHkTOh/O7WZzo2JhdKm98bRBxTw==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.4.tgz",
"integrity": "sha512-4KDQg60Khy3SgnF+V/TB2NZqzmM4TyGRmzsxqG1SebGdMSecCweFDSlI/F1vDYk6dKiCHgmpoT9A1sLxswkJ0A==",
"optional": true,
"dependencies": {
"@babel/parser": "^7.13.9",
"@babel/types": "^7.13.0",
"@types/estree": "^0.0.48",
"@vue/compiler-core": "3.1.2",
"@vue/compiler-dom": "3.1.2",
"@vue/compiler-ssr": "3.1.2",
"@vue/shared": "3.1.2",
"@vue/compiler-core": "3.1.4",
"@vue/compiler-dom": "3.1.4",
"@vue/compiler-ssr": "3.1.4",
"@vue/shared": "3.1.4",
"consolidate": "^0.16.0",
"estree-walker": "^2.0.1",
"hash-sum": "^2.0.0",
@ -4754,7 +4778,7 @@
"source-map": "^0.6.1"
},
"peerDependencies": {
"vue": "3.1.2"
"vue": "3.1.4"
}
},
"node_modules/easygettext/node_modules/consolidate": {
@ -4920,15 +4944,15 @@
}
},
"node_modules/easygettext/node_modules/vue": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.1.2.tgz",
"integrity": "sha512-q/rbKpb7aofax4ugqu2k/uj7BYuNPcd6Z5/qJtfkJQsE0NkwVoCyeSh7IZGH61hChwYn3CEkh4bHolvUPxlQ+w==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.1.4.tgz",
"integrity": "sha512-p8dcdyeCgmaAiZsbLyDkmOLcFGZb/jEVdCLW65V68LRCXTNX8jKsgah2F7OZ/v/Ai2V0Fb1MNO0vz/GFqsPVMA==",
"optional": true,
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.1.2",
"@vue/runtime-dom": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-dom": "3.1.4",
"@vue/runtime-dom": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"node_modules/easygettext/node_modules/yallist": {
@ -4952,9 +4976,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.3.763",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.763.tgz",
"integrity": "sha512-UyvEPae0wvzsyNJhVfGeFSOlUkHEze8xSIiExO5tZQ8QTr7obFiJWGk3U4e7afFOJMQJDszqU/3Pk5jtKiaSEg=="
"version": "1.3.766",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.766.tgz",
"integrity": "sha512-u2quJ862q9reRKh/je3GXis3w38+RoXH1J9N3XjtsS6NzmUAosNsyZgUVFZPN/ZlJ3v6T0rTyZR3q/J5c6Sy5w=="
},
"node_modules/elliptic": {
"version": "6.5.4",
@ -5196,12 +5220,13 @@
}
},
"node_modules/eslint": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz",
"integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==",
"version": "7.30.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz",
"integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==",
"dependencies": {
"@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.4.2",
"@humanwhocodes/config-array": "^0.5.0",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@ -5829,9 +5854,9 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/eslint-rule-docs": {
"version": "1.1.229",
"resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.229.tgz",
"integrity": "sha512-blQpqOoFiGr9wcH+MEgfMHcxizaXUaXXEc07R0avaZeivVmoPhvepHsh1UfdbtvC/KNZPcLzdpPIEpZIdgUSdQ=="
"version": "1.1.230",
"resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.230.tgz",
"integrity": "sha512-dT3rxxc3TmP57RHm9OYTQhT0N4Yu7bjkBW0hvrGRO5sUhB2ron8KPxMDE6pgO44oHvccrsB6TYlCCM5jccdPHw=="
},
"node_modules/eslint-scope": {
"version": "5.1.1",
@ -6641,9 +6666,9 @@
}
},
"node_modules/flatted": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA=="
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz",
"integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A=="
},
"node_modules/flatten": {
"version": "1.0.3",
@ -9117,6 +9142,27 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/mocha/node_modules/debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/mocha/node_modules/debug/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/mocha/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -13574,9 +13620,9 @@
}
},
"node_modules/table/node_modules/ajv": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
"integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
"version": "8.6.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz",
"integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@ -14331,16 +14377,17 @@
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
},
"node_modules/vue-eslint-parser": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz",
"integrity": "sha512-QXxqH8ZevBrtiZMZK0LpwaMfevQi9UL7lY6Kcp+ogWHC88AuwUPwwCIzkOUc1LR4XsYAt/F9yHXAB/QoD17QXA==",
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.7.2.tgz",
"integrity": "sha512-zkfxSttpwBW9SQEa+rLR+j6sFHGGhanVH3VuzHQwybCQWJsg/Yi1W619gXOW01U/zekN4D+J4/S4Zufd1sClZg==",
"dependencies": {
"debug": "^4.1.1",
"eslint-scope": "^5.0.0",
"eslint-scope": "^5.1.1",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.2.1",
"esquery": "^1.4.0",
"lodash": "^4.17.15"
"lodash": "^4.17.21",
"semver": "^6.3.0"
},
"engines": {
"node": ">=8.10"
@ -16504,6 +16551,21 @@
}
}
},
"@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
"integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
"requires": {
"@humanwhocodes/object-schema": "^1.2.0",
"debug": "^4.1.1",
"minimatch": "^3.0.4"
}
},
"@humanwhocodes/object-schema": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz",
"integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w=="
},
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -16649,9 +16711,9 @@
}
},
"@types/estree": {
"version": "0.0.48",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
"integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew=="
"version": "0.0.49",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.49.tgz",
"integrity": "sha512-K1AFuMe8a+pXmfHTtnwBvqoEylNKVeaiKYkjmcEAdytMQVJ/i9Fu7sc13GxgXdO49gkE7Hy8SyJonUZUn+eVaw=="
},
"@types/json-schema": {
"version": "7.0.7",
@ -16664,9 +16726,9 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
},
"@types/node": {
"version": "15.12.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz",
"integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg=="
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.0.tgz",
"integrity": "sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg=="
},
"@types/q": {
"version": "1.5.4",
@ -16679,14 +16741,14 @@
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q=="
},
"@vue/compiler-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.2.tgz",
"integrity": "sha512-nHmq7vLjq/XM2IMbZUcKWoH5sPXa2uR/nIKZtjbK5F3TcbnYE/zKsrSUR9WZJ03unlwotNBX1OyxVt9HbWD7/Q==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.4.tgz",
"integrity": "sha512-TnUz+1z0y74O/A4YKAbzsdUfamyHV73MihrEfvettWpm9bQKVoZd1nEmR1cGN9LsXWlwAvVQBetBlWdOjmQO5Q==",
"optional": true,
"requires": {
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"@vue/shared": "3.1.2",
"@vue/shared": "3.1.4",
"estree-walker": "^2.0.1",
"source-map": "^0.6.1"
},
@ -16700,23 +16762,23 @@
}
},
"@vue/compiler-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.2.tgz",
"integrity": "sha512-k2+SWcWH0jL6WQAX7Or2ONqu5MbtTgTO0dJrvebQYzgqaKMXNI90RNeWeCxS4BnNFMDONpHBeFgbwbnDWIkmRg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.4.tgz",
"integrity": "sha512-3tG2ScHkghhUBuFwl9KgyZhrS8CPFZsO7hUDekJgIp5b1OMkROr4AvxHu6rRMl4WkyvYkvidFNBS2VfOnwa6Kw==",
"optional": true,
"requires": {
"@vue/compiler-core": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-core": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"@vue/compiler-ssr": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.2.tgz",
"integrity": "sha512-BwXo9LFk5OSWdMyZQ4bX1ELHX0Z/9F+ld/OaVnpUPzAZCHslBYLvyKUVDwv2C/lpLjRffpC2DOUEdl1+RP1aGg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.4.tgz",
"integrity": "sha512-Box8fCuCFPp0FuimIswjDkjwiSDCBkHvt/xVALyFkYCiIMWv2eR53fIjmlsnEHhcBuZ+VgRC+UanCTcKvSA1gA==",
"optional": true,
"requires": {
"@vue/compiler-dom": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-dom": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"@vue/component-compiler-utils": {
@ -16749,42 +16811,42 @@
}
},
"@vue/reactivity": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.2.tgz",
"integrity": "sha512-glJzJoN2xE7I2lRvwKM5u1BHRPTd1yc8iaf//Lai/78/uYAvE5DXp5HzWRFOwMlbRvMGJHIQjOqoxj87cDAaag==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.4.tgz",
"integrity": "sha512-YDlgii2Cr9yAoKVZFzgY4j0mYlVT73986X3e5SPp6ifqckSEoFSUWXZK2Tb53TB/9qO29BEEbspnKD3m3wAwkA==",
"optional": true,
"peer": true,
"requires": {
"@vue/shared": "3.1.2"
"@vue/shared": "3.1.4"
}
},
"@vue/runtime-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.2.tgz",
"integrity": "sha512-gsPZG4dRIkixuuKmoj4P9IHgfT0yaFLcqWOM5F/bCk0nxQn1XtxH8oUehWuET726KhbukvDoJfe9G2CKviy80w==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.4.tgz",
"integrity": "sha512-qmVJgJuFxfT7M4qHQ4M6KqhKC66fjuswK+aBivE8dWiZ2rtIGl9gtJGpwqwjQEcKEBTOfvvrtrwBncYArJUO8Q==",
"optional": true,
"peer": true,
"requires": {
"@vue/reactivity": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/reactivity": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"@vue/runtime-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.2.tgz",
"integrity": "sha512-QvINxjLucEZFzp5f0NVu7JqWYCv5TKQfkH2FDs/N6QNE4iKcYtKrWdT0HKfABnVXG28Znqv6rIH0dH4ZAOwxpA==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.4.tgz",
"integrity": "sha512-vbmwgTxku1BU87Kw7r29adv0OIrDXCW0PslOPQT0O/9R5SqcXgS94Yj6zsztDjvghegenwIAPNLlDR1Auh5s+w==",
"optional": true,
"peer": true,
"requires": {
"@vue/runtime-core": "3.1.2",
"@vue/shared": "3.1.2",
"@vue/runtime-core": "3.1.4",
"@vue/shared": "3.1.4",
"csstype": "^2.6.8"
}
},
"@vue/shared": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.2.tgz",
"integrity": "sha512-EmH/poaDWBPJaPILXNI/1fvUbArJQmmTyVCwvvyDYDFnkPoTclAbHRAtyIvqfez7jybTDn077HTNILpxlsoWhg==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.4.tgz",
"integrity": "sha512-6O45kZAmkLvzGLToBxEz4lR2W6kXohCtebV2UxjH9GXjd8X9AhEn68FN9eNanFtWNzvgw1hqd6HkPRVQalqf7Q==",
"optional": true
},
"@vvo/tzdb": {
@ -17833,9 +17895,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001241",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz",
"integrity": "sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ=="
"version": "1.0.30001242",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001242.tgz",
"integrity": "sha512-KvNuZ/duufelMB3w2xtf9gEWCSxJwUgoxOx5b6ScLXC4kPc9xsczUVCPrQU26j5kOsHM4pSUL54tAZt5THQKug=="
},
"chai": {
"version": "4.3.4",
@ -18751,9 +18813,9 @@
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"requires": {
"ms": "2.1.2"
}
@ -18965,19 +19027,25 @@
"pug": "^3.0.2"
},
"dependencies": {
"@types/estree": {
"version": "0.0.48",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
"integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==",
"optional": true
},
"@vue/compiler-sfc": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.2.tgz",
"integrity": "sha512-SeG/2+DvwejQ7oAiSx8BrDh5qOdqCYHGClPiTvVIHTfSIHiS2JjMbCANdDCjHkTOh/O7WZzo2JhdKm98bRBxTw==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.4.tgz",
"integrity": "sha512-4KDQg60Khy3SgnF+V/TB2NZqzmM4TyGRmzsxqG1SebGdMSecCweFDSlI/F1vDYk6dKiCHgmpoT9A1sLxswkJ0A==",
"optional": true,
"requires": {
"@babel/parser": "^7.13.9",
"@babel/types": "^7.13.0",
"@types/estree": "^0.0.48",
"@vue/compiler-core": "3.1.2",
"@vue/compiler-dom": "3.1.2",
"@vue/compiler-ssr": "3.1.2",
"@vue/shared": "3.1.2",
"@vue/compiler-core": "3.1.4",
"@vue/compiler-dom": "3.1.4",
"@vue/compiler-ssr": "3.1.4",
"@vue/shared": "3.1.4",
"consolidate": "^0.16.0",
"estree-walker": "^2.0.1",
"hash-sum": "^2.0.0",
@ -19103,15 +19171,15 @@
"optional": true
},
"vue": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.1.2.tgz",
"integrity": "sha512-q/rbKpb7aofax4ugqu2k/uj7BYuNPcd6Z5/qJtfkJQsE0NkwVoCyeSh7IZGH61hChwYn3CEkh4bHolvUPxlQ+w==",
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.1.4.tgz",
"integrity": "sha512-p8dcdyeCgmaAiZsbLyDkmOLcFGZb/jEVdCLW65V68LRCXTNX8jKsgah2F7OZ/v/Ai2V0Fb1MNO0vz/GFqsPVMA==",
"optional": true,
"peer": true,
"requires": {
"@vue/compiler-dom": "3.1.2",
"@vue/runtime-dom": "3.1.2",
"@vue/shared": "3.1.2"
"@vue/compiler-dom": "3.1.4",
"@vue/runtime-dom": "3.1.4",
"@vue/shared": "3.1.4"
}
},
"yallist": {
@ -19133,9 +19201,9 @@
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
},
"electron-to-chromium": {
"version": "1.3.763",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.763.tgz",
"integrity": "sha512-UyvEPae0wvzsyNJhVfGeFSOlUkHEze8xSIiExO5tZQ8QTr7obFiJWGk3U4e7afFOJMQJDszqU/3Pk5jtKiaSEg=="
"version": "1.3.766",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.766.tgz",
"integrity": "sha512-u2quJ862q9reRKh/je3GXis3w38+RoXH1J9N3XjtsS6NzmUAosNsyZgUVFZPN/ZlJ3v6T0rTyZR3q/J5c6Sy5w=="
},
"elliptic": {
"version": "6.5.4",
@ -19336,12 +19404,13 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"eslint": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.29.0.tgz",
"integrity": "sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==",
"version": "7.30.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz",
"integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==",
"requires": {
"@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.4.2",
"@humanwhocodes/config-array": "^0.5.0",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@ -19913,9 +19982,9 @@
}
},
"eslint-rule-docs": {
"version": "1.1.229",
"resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.229.tgz",
"integrity": "sha512-blQpqOoFiGr9wcH+MEgfMHcxizaXUaXXEc07R0avaZeivVmoPhvepHsh1UfdbtvC/KNZPcLzdpPIEpZIdgUSdQ=="
"version": "1.1.230",
"resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.230.tgz",
"integrity": "sha512-dT3rxxc3TmP57RHm9OYTQhT0N4Yu7bjkBW0hvrGRO5sUhB2ron8KPxMDE6pgO44oHvccrsB6TYlCCM5jccdPHw=="
},
"eslint-scope": {
"version": "5.1.1",
@ -20439,9 +20508,9 @@
}
},
"flatted": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz",
"integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA=="
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.0.tgz",
"integrity": "sha512-XprP7lDrVT+kE2c2YlfiV+IfS9zxukiIOvNamPNsImNhXadSsQEbosItdL9bUQlCZXR13SvPk20BjWSWLA7m4A=="
},
"flatten": {
"version": "1.0.3",
@ -22320,6 +22389,21 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"requires": {
"ms": "2.1.2"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -25892,9 +25976,9 @@
},
"dependencies": {
"ajv": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz",
"integrity": "sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==",
"version": "8.6.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz",
"integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@ -26499,16 +26583,17 @@
"integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
},
"vue-eslint-parser": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz",
"integrity": "sha512-QXxqH8ZevBrtiZMZK0LpwaMfevQi9UL7lY6Kcp+ogWHC88AuwUPwwCIzkOUc1LR4XsYAt/F9yHXAB/QoD17QXA==",
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.7.2.tgz",
"integrity": "sha512-zkfxSttpwBW9SQEa+rLR+j6sFHGGhanVH3VuzHQwybCQWJsg/Yi1W619gXOW01U/zekN4D+J4/S4Zufd1sClZg==",
"requires": {
"debug": "^4.1.1",
"eslint-scope": "^5.0.0",
"eslint-scope": "^5.1.1",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.2.1",
"esquery": "^1.4.0",
"lodash": "^4.17.15"
"lodash": "^4.17.21",
"semver": "^6.3.0"
},
"dependencies": {
"espree": {

View file

@ -114,6 +114,7 @@ Vue.use(Router);
const router = new Router({
routes: Routes,
mode: "history",
base: config.baseUri + "/",
saveScrollPosition: true,
scrollBehavior: (to, from, savedPosition) => {
if (savedPosition) {

View file

@ -37,7 +37,7 @@ const testConfig = { jsHash: "48019917", cssHash: "2b327230", version: "test" };
const config = window.__CONFIG__ ? window.__CONFIG__ : testConfig;
const Api = Axios.create({
baseURL: "/api/v1",
baseURL: config.apiUri,
headers: {
common: {
"X-Session-ID": window.localStorage.getItem("session_id"),

View file

@ -47,17 +47,26 @@ export default class Config {
this.translations = translations;
if (!values || !values.siteTitle) {
console.warn("config: values are empty");
console.warn("config: values missing");
this.debug = true;
this.test = true;
this.demo = false;
this.themeName = "";
this.baseUri = "";
this.staticUri = "/static";
this.apiUri = "/api/v1";
this.contentUri = this.apiUri;
this.values = {};
this.page = {
title: "PhotoPrism",
caption: "Browse Your Life",
};
return;
} else {
this.baseUri = values.baseUri ? values.baseUri : "";
this.staticUri = values.staticUri ? values.staticUri : this.baseUri + "/static";
this.apiUri = values.apiUri ? values.apiUri : this.baseUri + "/api/v1";
this.contentUri = values.contentUri ? values.contentUri : this.apiUri;
}
this.page = {

View file

@ -30,11 +30,11 @@ https://docs.photoprism.org/developer-guide/
import Sockette from "sockette";
import Event from "pubsub-js";
import { config } from "session";
import { config } from "../session";
const host = window.location.host;
const prot = "https:" === document.location.protocol ? "wss://" : "ws://";
const url = prot + host + "/api/v1/ws";
const url = prot + host + window.__CONFIG__.apiUri + "/ws";
const Socket = new Sockette(url, {
timeout: 5e3,

View file

@ -176,7 +176,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
this.onDownload(`/api/v1/albums/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/albums/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.expanded = false;
},

View file

@ -161,7 +161,7 @@ export default {
this.filterChange();
},
download() {
this.onDownload(`/api/v1/albums/${this.album.UID}/dl?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/albums/${this.album.UID}/dl?t=${this.$config.downloadToken()}`);
},
onDownload(path) {
Notify.success(this.$gettext("Downloading…"));

View file

@ -98,7 +98,7 @@ export default {
},
download() {
Api.post("zip", {"files": this.selection}).then(r => {
this.onDownload("/api/v1/zip/" + r.data.filename + "?t=" + this.$config.downloadToken());
this.onDownload(`${this.$config.apiUri}/zip/${r.data.filename}?t=${this.$config.downloadToken()}`);
});
this.expanded = false;

View file

@ -124,7 +124,7 @@ export default {
return;
}
this.onDownload(`/api/v1/labels/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/labels/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.expanded = false;
},

View file

@ -34,7 +34,7 @@
<v-list class="navigation-home">
<v-list-tile class="nav-logo">
<v-list-tile-avatar class="clickable" @click.stop.prevent="goHome">
<img src="/static/img/logo-avatar.svg" alt="Logo">
<img :src="$config.staticUri + '/img/logo-avatar.svg'" alt="Logo">
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title class="title">

View file

@ -247,7 +247,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
const photo = this.photos[index];
download(`/api/v1/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
download(`${this.$config.apiUri}/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
},
toggleLike(ev, index) {
const inputType = this.input.eval(ev, index);

View file

@ -263,7 +263,7 @@ export default {
case 0: return;
case 1: new Photo().find(this.selection[0]).then(p => p.downloadAll()); break;
default: Api.post("zip", {"photos": this.selection}).then(r => {
this.onDownload(`/api/v1/zip/${r.data.filename}?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/zip/${r.data.filename}?t=${this.$config.downloadToken()}`);
});
}

View file

@ -168,7 +168,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
const photo = this.photos[index];
download(`/api/v1/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
download(`${this.$config.apiUri}/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
},
onSelect(ev, index) {
if (ev.shiftKey) {

View file

@ -13,7 +13,7 @@ export default {
return {
show: false,
source: "",
poster: "/api/v1/svg/video",
poster: `${this.$config.contentUri}/svg/video`,
defaultWidth: 640,
defaultHeight: 480,
width: 640,

View file

@ -91,7 +91,7 @@ export class Album extends RestModel {
}
thumbnailUrl(size) {
return `/api/v1/albums/${this.getId()}/t/${config.previewToken()}/${size}`;
return `${config.contentUri}/albums/${this.getId()}/t/${config.previewToken()}/${size}`;
}
dayString() {

View file

@ -114,18 +114,18 @@ export class File extends RestModel {
thumbnailUrl(size) {
if (this.Error || this.Missing) {
return "/api/v1/svg/broken";
return `${config.contentUri}/svg/broken`;
} else if (this.Type === "raw") {
return "/api/v1/svg/raw";
return `${config.contentUri}/svg/raw`;
} else if (this.Sidecar) {
return "/api/v1/svg/file";
return `${config.contentUri}/svg/file`;
}
return `/api/v1/t/${this.Hash}/${config.previewToken()}/${size}`;
return `${config.contentUri}/t/${this.Hash}/${config.previewToken()}/${size}`;
}
getDownloadUrl() {
return "/api/v1/dl/" + this.Hash + "?t=" + config.downloadToken();
return `${config.apiUri}/dl/${this.Hash}?t=${config.downloadToken()}`;
}
download() {

View file

@ -98,7 +98,7 @@ export class Folder extends RestModel {
}
thumbnailUrl(size) {
return `/api/v1/folders/t/${this.UID}/${config.previewToken()}/${size}`;
return `${config.contentUri}/folders/t/${this.UID}/${config.previewToken()}/${size}`;
}
getDateString() {

View file

@ -75,7 +75,7 @@ export class Label extends RestModel {
}
thumbnailUrl(size) {
return `/api/v1/labels/${this.getId()}/t/${config.previewToken()}/${size}`;
return `${config.contentUri}/labels/${this.getId()}/t/${config.previewToken()}/${size}`;
}
getDateString() {

View file

@ -380,10 +380,10 @@ export class Photo extends RestModel {
const file = this.videoFile();
if (file) {
return `/api/v1/videos/${file.Hash}/${config.previewToken()}/${FormatAvc}`;
return `${config.contentUri}/videos/${file.Hash}/${config.previewToken()}/${FormatAvc}`;
}
return `/api/v1/videos/${this.Hash}/${config.previewToken()}/${FormatAvc}`;
return `${config.contentUri}/videos/${this.Hash}/${config.previewToken()}/${FormatAvc}`;
}
mainFile() {
@ -453,17 +453,17 @@ export class Photo extends RestModel {
let video = this.videoFile();
if (video && video.Hash) {
return `/api/v1/t/${video.Hash}/${config.previewToken()}/${size}`;
return `${config.contentUri}/t/${video.Hash}/${config.previewToken()}/${size}`;
}
return "/api/v1/svg/photo";
return `${config.contentUri}/svg/photo`;
}
return `/api/v1/t/${hash}/${config.previewToken()}/${size}`;
return `${config.contentUri}/t/${hash}/${config.previewToken()}/${size}`;
}
getDownloadUrl() {
return `/api/v1/dl/${this.mainFileHash()}?t=${config.downloadToken()}`;
return `${config.apiUri}/dl/${this.mainFileHash()}?t=${config.downloadToken()}`;
}
downloadAll() {
@ -473,7 +473,7 @@ export class Photo extends RestModel {
const hash = this.mainFileHash();
if (hash) {
download(`/api/v1/dl/${hash}?t=${token}`, this.baseName(false));
download(`/${config.apiUri}/dl/${hash}?t=${token}`, this.baseName(false));
} else if (config.debug) {
console.log("download: failed, empty file hash", this);
}
@ -488,7 +488,7 @@ export class Photo extends RestModel {
return;
}
download(`/api/v1/dl/${file.Hash}?t=${token}`, this.fileBase(file.Name));
download(`${config.apiUri}/dl/${file.Hash}?t=${token}`, this.fileBase(file.Name));
});
}

View file

@ -85,7 +85,7 @@ export class Thumb extends Model {
let t = thumbs[i];
result[t.size] = {
src: "/api/v1/svg/photo",
src: `${config.contentUri}/svg/photo`,
w: t.w,
h: t.h,
};
@ -229,10 +229,10 @@ export class Thumb extends Model {
static thumbnailUrl(file, size) {
if (!file.Hash) {
return "/api/v1/svg/photo";
return `${config.contentUri}/svg/photo`;
}
return `/api/v1/t/${file.Hash}/${config.previewToken()}/${size}`;
return `${config.contentUri}/t/${file.Hash}/${config.previewToken()}/${size}`;
}
static downloadUrl(file) {
@ -240,7 +240,7 @@ export class Thumb extends Model {
return "";
}
return `/api/v1/dl/${file.Hash}?t=${config.downloadToken()}`;
return `${config.apiUri}/dl/${file.Hash}?t=${config.downloadToken()}`;
}
}

View file

@ -54,15 +54,15 @@
<p class="text-xs-center pt-3 mb-2">
<router-link to="/about/license">
<img src="/static/img/badge-agpl.svg" alt="License AGPL v3" style="max-width:100%;"/>
<img :src="$config.staticUri + '/img/badge-agpl.svg'" alt="License AGPL v3" style="max-width:100%;"/>
</router-link>
<a target="_blank" href="https://docs.photoprism.org/" rel="nofollow"><img src="/static/img/badge-docs.svg"
<a target="_blank" href="https://docs.photoprism.org/" rel="nofollow"><img :src="$config.staticUri + '/img/badge-docs.svg'"
alt="Documentation"
style="max-width:100%;"></a>
<a target="_blank" href="https://gitter.im/browseyourlife/community" rel="nofollow"><img
src="/static/img/badge-chat.svg" alt="Community Chat" style="max-width:100%;"></a>
:src="$config.staticUri + '/img/badge-chat.svg'" alt="Community Chat" style="max-width:100%;"></a>
<a target="_blank" href="https://twitter.com/photoprism_app" rel="nofollow"><img
src="/static/img/badge-twitter.svg" alt="Twitter" style="max-width:100%;"></a>
:src="$config.staticUri + '/img/badge-twitter.svg'" alt="Twitter" style="max-width:100%;"></a>
</p>
</v-container>

View file

@ -7,33 +7,22 @@
<v-toolbar-title v-else>
<translate>Contact Us</translate>
</v-toolbar-title>
<!-- v-spacer></v-spacer>
<v-btn icon href="https://github.com/photoprism/photoprism" target="_blank" class="action-github" title="GitHub">
<img src="/static/brands/github.svg" width="24" alt="GitHub">
</v-btn -->
</v-toolbar>
<v-container fluid class="pa-4" v-if="sent">
<v-container v-if="sent" fluid class="pa-4">
<p class="body-1">We'll get back to you as soon as possible!</p>
</v-container>
<v-form autocomplete="off" class="pa-3" ref="form"
v-model="valid"
lazy-validation v-else>
<v-form v-else ref="form" v-model="valid"
autocomplete="off"
class="pa-3" lazy-validation>
<v-layout row wrap>
<!-- v-flex xs12 sm6 lg4 xl2 grow class="pa-2">
<v-text-field :required="true" hide-details
v-model="form.Subject" browser-autocomplete="off"
:label="$gettext('Subject')"></v-text-field>
</v-flex -->
<v-flex xs12 class="pa-2">
<v-select
v-model="form.Category"
:disabled="busy"
:items="options.FeedbackCategories()"
:label="$gettext('Category')"
color="secondary-dark"
background-color="secondary-light"
v-model="form.Category"
flat solo hide-details required
browser-autocomplete="off"
class="input-category"
@ -42,24 +31,24 @@
</v-flex>
<v-flex xs12 class="pa-2">
<v-textarea required auto-grow flat solo hide-details browser-autocomplete="off"
v-model="form.Message" rows="10" :rules="[v => !!v || $gettext('Required')]"
<v-textarea v-model="form.Message" required auto-grow flat solo hide-details
browser-autocomplete="off" rows="10" :rules="[v => !!v || $gettext('Required')]"
:label="$gettext('How can we help?')"></v-textarea>
</v-flex>
<v-flex xs12 sm6 class="pa-2">
<v-text-field flat solo hide-details browser-autocomplete="off"
<v-text-field v-model="form.UserName" flat solo hide-details
browser-autocomplete="off"
color="secondary-dark"
background-color="secondary-light"
:label="$gettext('Name')" type="text" v-model="form.UserName">
background-color="secondary-light" :label="$gettext('Name')" type="text">
</v-text-field>
</v-flex>
<v-flex xs12 sm6 class="pa-2">
<v-text-field flat solo hide-details required browser-autocomplete="off"
color="secondary-dark" :rules="[v => !!v || $gettext('Required')]"
background-color="secondary-light"
:label="$gettext('E-Mail')" type="email" v-model="form.UserEmail">
<v-text-field v-model="form.UserEmail" flat solo hide-details required
browser-autocomplete="off" color="secondary-dark"
:rules="[v => !!v || $gettext('Required')]"
background-color="secondary-light" :label="$gettext('E-Mail')" type="email">
</v-text-field>
</v-flex>
@ -87,7 +76,7 @@ import * as options from "options/options";
import Api from "../../common/api";
export default {
name: 'p-page-support',
name: 'PPageSupport',
data() {
return {
sent: false,

View file

@ -8,7 +8,7 @@
<v-spacer></v-spacer>
<a target="_blank" href="https://www.gnu.org/licenses/agpl-3.0.en.html">
<img src="/static/img/agplv3-small.png" alt="AGPLv3 Logo">
<img :src="$config.staticUri + '/img/agplv3-small.png'" alt="AGPLv3 Logo">
</a>
</v-toolbar>
<v-container fluid class="pa-4">

View file

@ -216,7 +216,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
const model = this.results[index];
download(`/api/v1/dl/${model.Hash}?t=${this.$config.downloadToken()}`, model.Name);
download(`${this.$config.apiUri}/dl/${model.Hash}?t=${this.$config.downloadToken()}`, model.Name);
},
selectRange(rangeEnd, models) {
if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) {

View file

@ -71,11 +71,11 @@ export default {
"sources": {
"world": {
"type": "geojson",
"data": "/static/geo/world.json",
"data": `${this.$config.staticUri}/geo/world.json`,
"maxzoom": 6
}
},
"glyphs": "/static/font/{fontstack}/{range}.pbf",
"glyphs": `${this.$config.staticUri}/font/{fontstack}/{range}.pbf`,
"layers": [
{
"id": "background",
@ -275,7 +275,7 @@ export default {
// In case of facing RTL language on the map, this plugin will be fetched (only by lazy!) and will set RTL properly support.
// See mapbox documentation here https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-rtl-text/
mapboxgl.setRTLTextPlugin(
'/static/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js',
`${this.$config.staticUri}/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js`,
null,
true // Lazy load the plugin
);
@ -310,7 +310,7 @@ export default {
let el = document.createElement('div');
el.className = 'marker';
el.title = props.Title;
el.style.backgroundImage = `url(/api/v1/t/${props.Hash}/${token}/tile_50)`;
el.style.backgroundImage = `url(${this.$config.contentUri}/t/${props.Hash}/${token}/tile_50)`;
el.style.width = '50px';
el.style.height = '50px';

View file

@ -113,6 +113,7 @@ Vue.use(Router);
const router = new Router({
routes: Routes,
mode: "history",
base: config.baseUri + "/",
saveScrollPosition: true,
scrollBehavior: (to, from, savedPosition) => {
if (savedPosition) {

View file

@ -82,7 +82,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
this.onDownload(`/api/v1/albums/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/albums/${this.selection[0]}/dl?t=${this.$config.downloadToken()}`);
this.expanded = false;
},

View file

@ -13,7 +13,7 @@
class="clickable"
@click.stop.prevent="openSite"
>
<img src="/static/img/logo-white.svg" alt="Logo">
<img :src="$config.staticUri + '/img/logo-white.svg'" alt="Logo">
</v-avatar>
</v-toolbar>
<v-toolbar dark flat :dense="$vuetify.breakpoint.smAndDown" color="#fafafa">

View file

@ -196,7 +196,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
const photo = this.photos[index];
download(`/api/v1/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
download(`${this.$config.apiUri}/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
},
onSelect(ev, index) {
const inputType = this.input.eval(ev, index);

View file

@ -80,7 +80,7 @@ export default {
case 0: return;
case 1: new Photo().find(this.selection[0]).then(p => p.downloadAll()); break;
default: Api.post("zip", {"photos": this.selection}).then(r => {
this.onDownload(`/api/v1/zip/${r.data.filename}?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/zip/${r.data.filename}?t=${this.$config.downloadToken()}`);
});
}

View file

@ -147,7 +147,7 @@ export default {
Notify.success(this.$gettext("Downloading…"));
const photo = this.photos[index];
download(`/api/v1/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
download(`${this.$config.apiUri}/dl/${photo.Hash}?t=${this.$config.downloadToken()}`, photo.FileName);
},
onSelect(ev, index) {
if (ev.shiftKey) {

View file

@ -572,7 +572,7 @@ export default {
this.$forceUpdate();
},
download() {
this.onDownload(`/api/v1/albums/${this.uid}/dl?t=${this.$config.downloadToken()}`);
this.onDownload(`${this.$config.apiUri}/albums/${this.uid}/dl?t=${this.$config.downloadToken()}`);
},
onDownload(path) {
Notify.success(this.$gettext("Downloading…"));

View file

@ -6,6 +6,9 @@ window.__CONFIG__ = {
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

View file

@ -8,6 +8,9 @@ window.__CONFIG__ = {
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

View file

@ -8,6 +8,9 @@ window.__CONFIG__ = {
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

View file

@ -4,6 +4,9 @@ window.__CONFIG__ = {
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

View file

@ -6,6 +6,9 @@ window.__CONFIG__ = {
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

File diff suppressed because one or more lines are too long

View file

@ -1,13 +1,15 @@
import Photo from "model/photo";
import { Photo, FormatJpeg } from "model/photo";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import {FormatJpeg} from "../../../src/model/photo";
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",

View file

@ -197,7 +197,7 @@ const config = {
loader: "file-loader",
options: {
name: "[hash].[ext]",
publicPath: "/static/build/img",
publicPath: "./static/build/img",
outputPath: "img",
},
},
@ -206,7 +206,7 @@ const config = {
loader: "file-loader",
options: {
name: "[hash].[ext]",
publicPath: "/static/build/fonts",
publicPath: "./fonts",
outputPath: "fonts",
},
},

21
go.mod
View file

@ -6,7 +6,7 @@ require (
github.com/disintegration/imaging v1.6.2
github.com/djherbis/times v1.5.0
github.com/dsoprea/go-exif/v2 v2.0.0-20210428042052-dca55bf8ca15 // indirect
github.com/dsoprea/go-exif/v3 v3.0.0-20210512055020-8213cfabc61b
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20210512044107-62067e44c235
github.com/dsoprea/go-iptc v0.0.0-20200610044640-bc9ca208b413 // indirect
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20210512043942-b434301c6836
@ -16,10 +16,10 @@ require (
github.com/dsoprea/go-tiff-image-structure v0.0.0-20210512044046-dc78da6a809b
github.com/dsoprea/go-utility v0.0.0-20200717064901-2fccff4aa15e // indirect
github.com/dustin/go-humanize v1.0.0
github.com/esimov/pigo v1.4.3
github.com/esimov/pigo v1.4.4
github.com/gin-contrib/gzip v0.0.3
github.com/gin-gonic/gin v1.7.2
github.com/go-errors/errors v1.2.0 // indirect
github.com/go-errors/errors v1.4.0 // indirect
github.com/go-playground/validator/v10 v10.6.1 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551
github.com/golang/protobuf v1.5.2 // indirect
@ -32,7 +32,7 @@ require (
github.com/json-iterator/go v1.1.11 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/karrick/godirwalk v1.16.1
github.com/klauspost/cpuid/v2 v2.0.6
github.com/klauspost/cpuid/v2 v2.0.7
github.com/leandro-lugaresi/hub v1.1.1
github.com/leodido/go-urn v1.2.1 // indirect
github.com/leonelquinteros/gotext v1.5.0
@ -53,16 +53,17 @@ require (
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
github.com/studio-b12/gowebdav v0.0.0-20210427212133-86f8378cf140
github.com/studio-b12/gowebdav v0.0.0-20210630100626-7ff61aa87be8
github.com/tensorflow/tensorflow v1.15.2
github.com/tidwall/gjson v1.8.0
github.com/tidwall/gjson v1.8.1
github.com/tidwall/pretty v1.2.0 // indirect
github.com/ugorji/go v1.2.6 // indirect
github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6
github.com/urfave/cli v1.22.5
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
golang.org/x/image v0.0.0-20200618115811-c13761719519 // indirect
golang.org/x/net v0.0.0-20210525063256-abc453219eb5
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 // indirect
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
gopkg.in/ugjka/go-tz.v2 v2.0.12
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect

50
go.sum
View file

@ -37,7 +37,6 @@ 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/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/disintegration/imaging v1.6.1/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/djherbis/times v1.5.0 h1:79myA211VwPhFTqUk8xehWrsEO+zcIZj0zT8mXPVARU=
@ -49,8 +48,8 @@ github.com/dsoprea/go-exif/v2 v2.0.0-20210428042052-dca55bf8ca15 h1:a73ubT6QCaR0
github.com/dsoprea/go-exif/v2 v2.0.0-20210428042052-dca55bf8ca15/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210512043655-120bcdb2a55e/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210512055020-8213cfabc61b h1:Ry/3m2rXSlKtTTfjfzf6JHmCfVQlR2Kp+hg/sLMDv9M=
github.com/dsoprea/go-exif/v3 v3.0.0-20210512055020-8213cfabc61b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20210512044107-62067e44c235 h1:d0y1e2IDPw/Mt4SkiznYCojvUsw6Vz1adAiEt9LeGd8=
github.com/dsoprea/go-heic-exif-extractor v0.0.0-20210512044107-62067e44c235/go.mod h1:ySpXG3oRl/vqgmHakRU2A9P7Xcl4hd7y5k37F7MEDxc=
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb/go.mod h1:kYIdx9N9NaOyD7U6D+YtExN7QhRm+5kq7//yOsRXQtM=
@ -80,9 +79,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/esimov/pigo v1.4.3 h1:xl098Z9CHmouywvyRZepuKx8aSWHBs/0lZtp7Yt5g28=
github.com/esimov/pigo v1.4.3/go.mod h1:aOTYpOWsqniACzXKdSOGkqI6CnWQpP8tFjgtUOARoEs=
github.com/fogleman/gg v1.0.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/esimov/pigo v1.4.4 h1:Ab9uYXw0F0Y7OyZQQGwJjktl5LlHdL3ovdXe/T0juK8=
github.com/esimov/pigo v1.4.4/go.mod h1:SGkOUpm4wlEmQQJKlaymAkThY8/8iP+XE0gFo7g8G6w=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/gin-contrib/gzip v0.0.3 h1:etUaeesHhEORpZMp18zoOhepboiWnFtXrBZxszWUn4k=
github.com/gin-contrib/gzip v0.0.3/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@ -93,8 +92,8 @@ github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjX
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.2.0 h1:g5NHvR3mlTvaIa23r4xj7JAHlIhdVhOK8rEOGauEMCY=
github.com/go-errors/errors v1.2.0/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
github.com/go-errors/errors v1.4.0 h1:2OA7MFw38+e9na72T1xgkomPb6GzZzzxvJ5U630FoRM=
github.com/go-errors/errors v1.4.0/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
@ -179,8 +178,8 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALr
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.0.6 h1:dQ5ueTiftKxp0gyjKSx5+8BtPWkyQbd95m8Gys/RarI=
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.7 h1:U89pAFid7wpIWvTFJnMKgU+Sabb7DLEgHI7Xt8apo3Y=
github.com/klauspost/cpuid/v2 v2.0.7/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
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=
@ -256,16 +255,17 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/studio-b12/gowebdav v0.0.0-20210427212133-86f8378cf140 h1:JCSn/2k3AQ0aJGs5Yx2xv6qrW0CAULc1E+xtSxeeQ/E=
github.com/studio-b12/gowebdav v0.0.0-20210427212133-86f8378cf140/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s=
github.com/studio-b12/gowebdav v0.0.0-20210630100626-7ff61aa87be8 h1:ipNUBPHSUmHhhcLhvqC2vGZsJPzVuJap8rJx3uGAEco=
github.com/studio-b12/gowebdav v0.0.0-20210630100626-7ff61aa87be8/go.mod h1:gCcfDlA1Y7GqOaeEKw5l9dOGx1VLdc/HuQSlQAaZ30s=
github.com/tensorflow/tensorflow v1.15.2 h1:7/f/A664Tml/nRJg04+p3StcrsT53mkcvmxYHXI21Qo=
github.com/tensorflow/tensorflow v1.15.2/go.mod h1:itOSERT4trABok4UOoG+X4BoKds9F3rIsySdn+Lvu90=
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU=
github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
@ -289,8 +289,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -299,12 +299,12 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -341,8 +341,8 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -371,10 +371,12 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1 h1:lCnv+lfrU9FRPGf8NeRuWAAPjNnema5WtBinMgs1fD8=
golang.org/x/sys v0.0.0-20210521203332-0cec03c779c1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View file

@ -85,6 +85,11 @@ func configAction(ctx *cli.Context) error {
fmt.Printf("%-25s %s\n", "site-caption", conf.SiteCaption())
fmt.Printf("%-25s %s\n", "site-description", conf.SiteDescription())
fmt.Printf("%-25s %s\n", "site-author", conf.SiteAuthor())
fmt.Printf("%-25s %s\n", "cdn-url", conf.CdnUrl("/"))
fmt.Printf("%-25s %s\n", "content-uri", conf.ContentUri())
fmt.Printf("%-25s %s\n", "static-uri", conf.StaticUri())
fmt.Printf("%-25s %s\n", "api-uri", conf.ApiUri())
fmt.Printf("%-25s %s\n", "base-uri", conf.BaseUri("/"))
// Logging.
fmt.Printf("%-25s %s\n", "log-level", conf.LogLevel())

View file

@ -17,6 +17,10 @@ type ClientConfig struct {
Version string `json:"version"`
Copyright string `json:"copyright"`
Flags string `json:"flags"`
BaseUri string `json:"baseUri"`
StaticUri string `json:"staticUri"`
ApiUri string `json:"apiUri"`
ContentUri string `json:"contentUri"`
SiteUrl string `json:"siteUrl"`
SitePreview string `json:"sitePreview"`
SiteTitle string `json:"siteTitle"`
@ -168,6 +172,10 @@ func (c *Config) PublicConfig() ClientConfig {
Flags: strings.Join(c.Flags(), " "),
Mode: "public",
Name: c.Name(),
BaseUri: c.BaseUri(""),
StaticUri: c.StaticUri(),
ApiUri: c.ApiUri(),
ContentUri: c.ContentUri(),
SiteUrl: c.SiteUrl(),
SitePreview: c.SitePreview(),
SiteTitle: c.SiteTitle(),
@ -225,6 +233,10 @@ func (c *Config) GuestConfig() ClientConfig {
Flags: "readonly public shared",
Mode: "guest",
Name: c.Name(),
BaseUri: c.BaseUri(""),
StaticUri: c.StaticUri(),
ApiUri: c.ApiUri(),
ContentUri: c.ContentUri(),
SiteUrl: c.SiteUrl(),
SitePreview: c.SitePreview(),
SiteTitle: c.SiteTitle(),
@ -276,6 +288,10 @@ func (c *Config) UserConfig() ClientConfig {
Flags: strings.Join(c.Flags(), " "),
Mode: "user",
Name: c.Name(),
BaseUri: c.BaseUri(""),
StaticUri: c.StaticUri(),
ApiUri: c.ApiUri(),
ContentUri: c.ContentUri(),
SiteUrl: c.SiteUrl(),
SitePreview: c.SitePreview(),
SiteTitle: c.SiteTitle(),

View file

@ -5,6 +5,7 @@ import (
"fmt"
"hash/crc32"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"runtime"
@ -34,6 +35,9 @@ import (
var log = event.Log
var once sync.Once
const ApiUri = "/api/v1"
const StaticUri = "/static"
// Config holds database, cache and all parameters of photoprism
type Config struct {
once sync.Once
@ -214,13 +218,48 @@ func (c *Config) Copyright() string {
return c.options.Copyright
}
// BaseUri returns the site base URI for a given resource.
func (c *Config) BaseUri(res string) string {
if c.SiteUrl() == "" {
return res
}
u, err := url.Parse(c.SiteUrl())
if err != nil {
return res
}
return strings.TrimRight(u.Path, "/") + res
}
// ApiUri returns the api URI.
func (c *Config) ApiUri() string {
return c.BaseUri(ApiUri)
}
// CdnUrl returns the optional content delivery network URI without trailing slash.
func (c *Config) CdnUrl(res string) string {
return strings.TrimRight(c.options.CdnUrl, "/") + res
}
// ContentUri returns the content delivery URI.
func (c *Config) ContentUri() string {
return c.CdnUrl(c.ApiUri())
}
// StaticUri returns the static content URI.
func (c *Config) StaticUri() string {
return c.CdnUrl(c.BaseUri(StaticUri))
}
// SiteUrl returns the public server URL (default is "http://localhost:2342/").
func (c *Config) SiteUrl() string {
if c.options.SiteUrl == "" {
return "http://localhost:2342/"
}
return c.options.SiteUrl
return strings.TrimRight(c.options.SiteUrl, "/") + "/"
}
// SitePreview returns the site preview image URL for sharing.

View file

@ -292,12 +292,68 @@ func TestConfig_OriginalsLimit(t *testing.T) {
assert.Equal(t, int64(838860800), c.OriginalsLimit())
}
func TestConfig_BaseUri(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "", c.BaseUri(""))
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, "", c.BaseUri(""))
c.options.SiteUrl = "http://foo:2342/foo/"
assert.Equal(t, "/foo", c.BaseUri(""))
assert.Equal(t, "/foo/bar", c.BaseUri("/bar"))
}
func TestConfig_StaticUri(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "/static", c.StaticUri())
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, "/static", c.StaticUri())
c.options.SiteUrl = "http://foo:2342/foo/"
assert.Equal(t, "/foo/static", c.StaticUri())
c.options.CdnUrl = "http://foo:2342/bar"
assert.Equal(t, "http://foo:2342/bar/foo"+StaticUri, c.StaticUri())
}
func TestConfig_ApiUri(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, ApiUri, c.ApiUri())
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, ApiUri, c.ApiUri())
c.options.SiteUrl = "http://foo:2342/foo/"
assert.Equal(t, "/foo"+ApiUri, c.ApiUri())
}
func TestConfig_CdnUrl(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "", c.CdnUrl(""))
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, "/", c.CdnUrl("/"))
c.options.CdnUrl = "http://foo:2342/foo/"
assert.Equal(t, "http://foo:2342/foo", c.CdnUrl(""))
assert.Equal(t, "http://foo:2342/foo/", c.CdnUrl("/"))
}
func TestConfig_ContentUri(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, ApiUri, c.ContentUri())
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, ApiUri, c.ContentUri())
c.options.CdnUrl = "http://foo:2342//"
assert.Equal(t, "http://foo:2342"+ApiUri, c.ContentUri())
}
func TestConfig_SiteUrl(t *testing.T) {
c := NewConfig(CliTestContext())
assert.Equal(t, "http://localhost:2342/", c.SiteUrl())
c.options.SiteUrl = "http://superhost:2342/"
assert.Equal(t, "http://superhost:2342/", c.SiteUrl())
c.options.SiteUrl = "http://superhost"
assert.Equal(t, "http://superhost/", c.SiteUrl())
}
func TestConfig_SitePreview(t *testing.T) {

View file

@ -208,6 +208,11 @@ var GlobalFlags = []cli.Flag{
Usage: "server process id `FILENAME`",
EnvVar: "PHOTOPRISM_PID_FILENAME",
},
cli.StringFlag{
Name: "cdn-url",
Usage: "content delivery network `URL` (optional)",
EnvVar: "PHOTOPRISM_CDN_URL",
},
cli.StringFlag{
Name: "site-url",
Usage: "public site `URL`",

View file

@ -72,6 +72,7 @@ type Options struct {
LogLevel string `yaml:"LogLevel" json:"-" flag:"log-level"`
LogFilename string `yaml:"LogFilename" json:"-" flag:"log-filename"`
PIDFilename string `yaml:"PIDFilename" json:"-" flag:"pid-filename"`
CdnUrl string `yaml:"CdnUrl" json:"CdnUrl" flag:"cdn-url"`
SiteUrl string `yaml:"SiteUrl" json:"SiteUrl" flag:"site-url"`
SitePreview string `yaml:"SitePreview" json:"SitePreview" flag:"site-preview"`
SiteTitle string `yaml:"SiteTitle" json:"SiteTitle" flag:"site-title"`

View file

@ -1,8 +1,9 @@
package entity
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestMarkerMap_Get(t *testing.T) {

View file

@ -43,7 +43,7 @@ func TestNewAccount(t *testing.T) {
func TestAccount_ServiceDiscovery(t *testing.T) {
t.Run("error = nil", func(t *testing.T) {
account := Account{AccName: "Foo", AccOwner: "bar", AccURL: "test.com", AccType: "test", SyncDownload: false, AccShare: true}
account := Account{AccName: "Foo", AccOwner: "bar", AccURL: "photoprism.app", AccType: "test", SyncDownload: false, AccShare: true}
err := account.ServiceDiscovery()
assert.Equal(t, nil, err)

View file

@ -15,23 +15,32 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
router.RedirectTrailingSlash = true
// Static assets like js, css and font files.
router.Static("/static", conf.StaticPath())
router.StaticFile("/favicon.ico", filepath.Join(conf.ImgPath(), "favicon.ico"))
router.Static(conf.BaseUri(config.StaticUri), conf.StaticPath())
router.StaticFile(conf.BaseUri("/favicon.ico"), filepath.Join(conf.ImgPath(), "favicon.ico"))
// PWA service worker.
router.GET("/sw.js", func(c *gin.Context) {
// PWA Manifest.
router.GET(conf.BaseUri("/manifest.json"), func(c *gin.Context) {
c.Header("Cache-Control", "no-store")
c.Header("Content-Type", "application/json")
clientConfig := conf.PublicConfig()
c.HTML(http.StatusOK, "manifest.json", gin.H{"config": clientConfig})
})
// PWA Service Worker.
router.GET(conf.BaseUri("/sw.js"), func(c *gin.Context) {
c.Header("Cache-Control", "no-store")
c.File(filepath.Join(conf.BuildPath(), "sw.js"))
})
// Rainbow page.
router.GET("/rainbow", func(c *gin.Context) {
// Rainbow Page.
router.GET(conf.BaseUri("/rainbow"), func(c *gin.Context) {
clientConfig := conf.PublicConfig()
c.HTML(http.StatusOK, "rainbow.tmpl", gin.H{"config": clientConfig})
})
// JSON-REST API Version 1
v1 := router.Group("/api/v1")
v1 := router.Group(conf.BaseUri(config.ApiUri))
{
api.GetStatus(v1)
api.GetErrors(v1)
@ -137,7 +146,7 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
}
// Configure link sharing.
s := router.Group("/s")
s := router.Group(conf.BaseUri("/s"))
{
api.Shares(s)
api.SharePreview(s)
@ -147,12 +156,12 @@ func registerRoutes(router *gin.Engine, conf *config.Config) {
if conf.DisableWebDAV() {
log.Info("webdav: server disabled")
} else {
WebDAV(conf.OriginalsPath(), router.Group(WebDAVOriginals, BasicAuth()), conf)
log.Infof("webdav: %s/ enabled, waiting for requests", WebDAVOriginals)
WebDAV(conf.OriginalsPath(), router.Group(conf.BaseUri(WebDAVOriginals), BasicAuth()), conf)
log.Infof("webdav: %s/ enabled, waiting for requests", conf.BaseUri(WebDAVOriginals))
if conf.ImportPath() != "" {
WebDAV(conf.ImportPath(), router.Group(WebDAVImport, BasicAuth()), conf)
log.Infof("webdav: %s/ enabled, waiting for requests", WebDAVImport)
WebDAV(conf.ImportPath(), router.Group(conf.BaseUri(WebDAVImport), BasicAuth()), conf)
log.Infof("webdav: %s/ enabled, waiting for requests", conf.BaseUri(WebDAVImport))
}
}

View file

@ -39,11 +39,11 @@ func Start(ctx context.Context, conf *config.Config) {
router.Use(gzip.Gzip(
gzip.DefaultCompression,
gzip.WithExcludedPaths([]string{
"/api/v1/t",
"/api/v1/folders/t",
"/api/v1/zip",
"/api/v1/albums",
"/api/v1/labels",
conf.BaseUri(config.ApiUri + "/t"),
conf.BaseUri(config.ApiUri + "/folders/t"),
conf.BaseUri(config.ApiUri + "/zip"),
conf.BaseUri(config.ApiUri + "/albums"),
conf.BaseUri(config.ApiUri + "/labels"),
})))
}