Frontend: Reformat JS code

This commit is contained in:
Michael Mayer
2020-12-18 14:42:36 +01:00
parent 29145e77b6
commit 003412736e
37 changed files with 3715 additions and 3420 deletions

View File

@@ -6,18 +6,62 @@ module.exports = {
node: true,
mocha: true,
},
extends: 'eslint:recommended',
extends: [
"eslint:recommended",
"plugin:vue/recommended",
"plugin:prettier-vue/recommended",
// Do not add `'prettier/vue'` if you don't want to use prettier for `<template>` blocks
"prettier/vue",
],
settings: {
"prettier-vue": {
// Settings for how to process Vue SFC Blocks
SFCBlocks: {
template: false,
script: true,
style: true,
},
// Use prettierrc for prettier options or not (default: `true`)
usePrettierrc: true,
// Set the options for `prettier.getFileInfo`.
// @see https://prettier.io/docs/en/api.html#prettiergetfileinfofilepath-options
fileInfoOptions: {
// Path to ignore file (default: `'.prettierignore'`)
// Notice that the ignore file is only used for this plugin
ignorePath: ".testignore",
// Process the files in `node_modules` or not (default: `false`)
withNodeModules: false,
},
},
},
parserOptions: {
sourceType: 'module',
sourceType: "module",
},
rules: {
'comma-dangle': ['error', 'always-multiline'],
indent: ['error', 4, { "SwitchCase": 1 }],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'double'], // Easier for Go developers!
semi: ['error', 'always'],
'no-unused-vars': ['warn'],
'no-console': 0,
'no-prototype-builtins': 0,
// 'comma-dangle': ['error', 'always-multiline'],
indent: ["error", 2, { SwitchCase: 1 }],
"linebreak-style": ["error", "unix"],
quotes: ["off", "double"], // Easier for Go developers!
semi: ["error", "always"],
"no-unused-vars": ["warn"],
"no-console": 0,
"no-prototype-builtins": 0,
"prettier-vue/prettier": [
"error",
{
// Override all options of `prettier` here
// @see https://prettier.io/docs/en/options.html
printWidth: 100,
singleQuote: false,
semi: true,
trailingComma: "es5",
htmlWhitespaceSensitivity: "strict",
},
],
},
};

View File

@@ -48,14 +48,20 @@ module.exports = (config) => {
customLaunchers: {
LocalChrome: {
base: "ChromeHeadless",
flags: ["--disable-translate", "--disable-extensions", "--no-sandbox", "--disable-web-security", "--disable-dev-shm-usage"],
flags: [
"--disable-translate",
"--disable-extensions",
"--no-sandbox",
"--disable-web-security",
"--disable-dev-shm-usage",
],
},
},
files: [
"node_modules/@babel/polyfill/dist/polyfill.js",
"node_modules/regenerator-runtime/runtime/runtime.js",
{pattern: "tests/unit/**/*_test.js", watched: false},
{ pattern: "tests/unit/**/*_test.js", watched: false },
],
// Preprocess through webpack
@@ -142,9 +148,7 @@ module.exports = (config) => {
{
test: /\.js$/,
loader: "babel-loader",
exclude: file => (
/node_modules/.test(file)
),
exclude: (file) => /node_modules/.test(file),
query: {
presets: ["@babel/preset-env"],
compact: false,

View File

@@ -1926,6 +1926,62 @@
"@vue/shared": "3.0.2"
}
},
"@vue/component-compiler-utils": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz",
"integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==",
"requires": {
"consolidate": "^0.15.1",
"hash-sum": "^1.0.2",
"lru-cache": "^4.1.2",
"merge-source-map": "^1.1.0",
"postcss": "^7.0.14",
"postcss-selector-parser": "^6.0.2",
"prettier": "^1.18.2",
"source-map": "~0.6.1",
"vue-template-es2015-compiler": "^1.9.0"
},
"dependencies": {
"consolidate": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
"integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
"requires": {
"bluebird": "^3.1.1"
}
},
"hash-sum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ="
},
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
"optional": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
}
}
},
"@vue/shared": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.2.tgz",
@@ -5040,6 +5096,11 @@
}
}
},
"eslint-config-prettier": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz",
"integrity": "sha512-8Y8lGLVPPZdaNA7JXqnvETVC7IiVRgAP6afQu9gOQRn90YY3otMNh+x7Vr2vMePQntF+5erdSUBqSzCmU/AxaQ=="
},
"eslint-config-standard": {
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz",
@@ -5381,6 +5442,18 @@
}
}
},
"eslint-plugin-prettier-vue": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier-vue/-/eslint-plugin-prettier-vue-2.1.1.tgz",
"integrity": "sha512-B9nYJCwf6508tc36fBU6a7QRwmp688Z8q6BPDvHLftR5KccqVNRkCUwPYjHXouw1m6NzdcRZraJ0A0jXwtNCTQ==",
"requires": {
"@vue/component-compiler-utils": "^3.1.2",
"chalk": "^4.0.0",
"prettier": "^1.18.2 || ^2.0.0",
"prettier-linter-helpers": "^1.0.0",
"vue-template-compiler": "^2.0.0"
}
},
"eslint-plugin-promise": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz",
@@ -5391,6 +5464,27 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz",
"integrity": "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ=="
},
"eslint-plugin-vue": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.3.0.tgz",
"integrity": "sha512-4rc9xrZgwT4aLz3XE6lrHu+FZtDLWennYvtzVvvS81kW9c65U4DUzQQWAFjDCgCFvN6HYWxi7ueEtxZVSB+f0g==",
"requires": {
"eslint-utils": "^2.1.0",
"natural-compare": "^1.4.0",
"semver": "^7.3.2",
"vue-eslint-parser": "^7.3.0"
},
"dependencies": {
"semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
"eslint-rule-docs": {
"version": "1.1.213",
"resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.213.tgz",
@@ -5708,6 +5802,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w=="
},
"fast-glob": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz",
@@ -8026,7 +8125,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
"integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
"optional": true,
"requires": {
"source-map": "^0.6.1"
},
@@ -8034,8 +8132,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
@@ -10597,9 +10694,17 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
},
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew=="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q=="
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"requires": {
"fast-diff": "^1.1.2"
}
},
"pretty-error": {
"version": "2.1.2",
@@ -13473,6 +13578,36 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
"integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg=="
},
"vue-eslint-parser": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.3.0.tgz",
"integrity": "sha512-n5PJKZbyspD0+8LnaZgpEvNCrjQx1DyDHw8JdWwoxhhC+yRip4TAvSDpXGf9SWX6b0umeB5aR61gwUo6NVvFxw==",
"requires": {
"debug": "^4.1.1",
"eslint-scope": "^5.0.0",
"eslint-visitor-keys": "^1.1.0",
"espree": "^6.2.1",
"esquery": "^1.0.1",
"lodash": "^4.17.15"
},
"dependencies": {
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="
},
"espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
"integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
"requires": {
"acorn": "^7.1.1",
"acorn-jsx": "^5.2.0",
"eslint-visitor-keys": "^1.1.0"
}
}
}
},
"vue-fullscreen": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/vue-fullscreen/-/vue-fullscreen-2.1.6.tgz",
@@ -13637,6 +13772,11 @@
"uniq": "^1.0.1"
}
},
"prettier": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
"integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",

View File

@@ -9,7 +9,7 @@
"watch": "webpack --watch",
"build": "webpack --optimize-minimize",
"lint": "eslint --cache src/ *.js",
"fmt": "eslint --cache --fix src/ *.js",
"fmt": "eslint --cache --fix src/ *.js .eslintrc.js",
"test": "karma start",
"upgrade": "npm --depth 10 update && npm audit fix",
"acceptance": "testcafe \"chromium:headless --disable-dev-shm-usage\" --skip-js-errors --selector-timeout 5000 -S -s tests/screenshots tests/acceptance",
@@ -50,6 +50,7 @@
"cssnano": "^4.1.10",
"easygettext": "^2.16.1",
"eslint": "^7.15.0",
"eslint-config-prettier": "^7.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-formatter-pretty": "^4.0.0",
"eslint-friendly-formatter": "^4.0.1",
@@ -57,8 +58,10 @@
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier-vue": "^2.1.1",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^7.3.0",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^3.0.1",
"friendly-errors-webpack-plugin": "^1.7.0",
@@ -94,6 +97,7 @@
"postcss-preset-env": "^6.7.0",
"postcss-reporter": "^6.0.1",
"postcss-url": "^8.0.0",
"prettier": "^2.2.1",
"pubsub-js": "^1.9.2",
"puppeteer-core": "^5.5.0",
"regenerator-runtime": "^0.13.7",

View File

@@ -2,6 +2,6 @@ module.exports = {
plugins: {
"postcss-import": {},
"postcss-preset-env": {},
"cssnano": {},
cssnano: {},
},
};

View File

@@ -41,8 +41,8 @@ import Log from "common/log";
import PhotoPrism from "app.vue";
import Router from "vue-router";
import Routes from "routes";
import {config, session} from "session";
import {Settings} from "luxon";
import { config, session } from "session";
import { Settings } from "luxon";
import Socket from "common/websocket";
import Viewer from "common/viewer";
import Vue from "vue";
@@ -53,13 +53,15 @@ import VueFullscreen from "vue-fullscreen";
import VueInfiniteScroll from "vue-infinite-scroll";
import VueModal from "vue-js-modal";
import Hls from "hls.js";
import {$gettext, Mount} from "common/vm";
import { $gettext, Mount } from "common/vm";
// Initialize helpers
const viewer = new Viewer();
const clipboard = new Clipboard(window.localStorage, "photo_clipboard");
const isPublic = config.get("public");
const isMobile = (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
);
// HTTP Live Streaming (video support)
window.Hls = Hls;
@@ -77,7 +79,7 @@ Vue.prototype.$clipboard = clipboard;
Vue.prototype.$isMobile = isMobile;
// Register Vuetify
Vue.use(Vuetify, {"theme": config.theme});
Vue.use(Vuetify, { theme: config.theme });
Vue.config.language = config.values.settings.ui.language;
Settings.defaultLocale = Vue.config.language.substring(0, 2);
@@ -93,7 +95,7 @@ Vue.use(GetTextPlugin, {
Vue.use(VueLuxon);
Vue.use(VueInfiniteScroll);
Vue.use(VueFullscreen);
Vue.use(VueModal, {dynamic: true, dynamicDefaults: {clickToClose: true}});
Vue.use(VueModal, { dynamic: true, dynamicDefaults: { clickToClose: true } });
Vue.use(VueFilters);
Vue.use(Components);
Vue.use(Dialogs);
@@ -107,24 +109,24 @@ const router = new Router({
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.settings) && config.values.disable.settings) {
next({name: "home"});
} else if (to.matched.some(record => record.meta.admin)) {
if (to.matched.some((record) => record.meta.settings) && config.values.disable.settings) {
next({ name: "home" });
} else if (to.matched.some((record) => record.meta.admin)) {
if (isPublic || session.isAdmin()) {
next();
} else {
next({
name: "login",
params: {nextUrl: to.fullPath},
params: { nextUrl: to.fullPath },
});
}
} else if (to.matched.some(record => record.meta.auth)) {
} else if (to.matched.some((record) => record.meta.auth)) {
if (isPublic || session.isUser()) {
next();
} else {
next({
name: "login",
params: {nextUrl: to.fullPath},
params: { nextUrl: to.fullPath },
});
}
} else {

View File

@@ -30,53 +30,60 @@ https://docs.photoprism.org/developer-guide/
import Axios from "axios";
import Notify from "common/notify";
import {$gettext} from "./vm";
import { $gettext } from "./vm";
const testConfig = {"jsHash":"48019917", "cssHash":"2b327230", "version": "test"};
const testConfig = { jsHash: "48019917", cssHash: "2b327230", version: "test" };
const config = window.__CONFIG__ ? window.__CONFIG__ : testConfig;
const Api = Axios.create({
baseURL: "/api/v1",
headers: {common: {
headers: {
common: {
"X-Session-ID": window.localStorage.getItem("session_id"),
"X-Client-Hash": config.jsHash,
"X-Client-Version": config.version,
}},
},
},
});
Api.interceptors.request.use(function (config) {
Api.interceptors.request.use(
function (config) {
// Do something before request is sent
Notify.ajaxStart();
return config;
}, function (error) {
},
function (error) {
// Do something with request error
return Promise.reject(error);
});
}
);
Api.interceptors.response.use(function (response) {
Api.interceptors.response.use(
function (response) {
Notify.ajaxEnd();
if(typeof response.data == "string") {
if (typeof response.data == "string") {
Notify.error($gettext("Request failed - invalid response"));
console.warn("WARNING: Server returned HTML instead of JSON - API not implemented?");
}
return response;
}, function (error) {
},
function (error) {
Notify.ajaxEnd();
if (Axios.isCancel(error)) {
return Promise.reject(error);
}
if(console && console.log) {
if (console && console.log) {
console.log(error);
}
let errorMessage = $gettext("An error occurred - are you offline?");
let code = error.code;
if(error.response && error.response.data) {
if (error.response && error.response.data) {
let data = error.response.data;
code = data.code;
errorMessage = data.message ? data.message : data.error;
@@ -89,6 +96,7 @@ Api.interceptors.response.use(function (response) {
}
return Promise.reject(error);
});
}
);
export default Api;

View File

@@ -30,7 +30,7 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Notify from "common/notify";
import {$gettext} from "./vm";
import { $gettext } from "./vm";
export const MaxItems = 999;
@@ -157,7 +157,7 @@ export default class Clipboard {
this.add(models[i]);
}
return (rangeEnd - rangeStart) + 1;
return rangeEnd - rangeStart + 1;
}
has(model) {

View File

@@ -92,7 +92,7 @@ export default class Config {
}
if (values.jsHash && this.values.jsHash !== values.jsHash) {
Event.publish("dialog.reload", {values});
Event.publish("dialog.reload", { values });
}
for (let key in values) {

View File

@@ -33,7 +33,7 @@ import Event from "pubsub-js";
class Log {
constructor() {
this.cap = 150;
this.created = new Date;
this.created = new Date();
this.logs = [
/* EXAMPLE LOG MESSAGE
{
@@ -54,12 +54,12 @@ class Log {
this.logs.unshift(data);
if(this.logs.length > this.cap) {
if (this.logs.length > this.cap) {
this.logs.splice(this.cap);
}
}
}
const log = new Log;
const log = new Log();
export default log;

View File

@@ -29,42 +29,42 @@ https://docs.photoprism.org/developer-guide/
*/
import Event from "pubsub-js";
import {$gettext} from "./vm";
import { $gettext } from "./vm";
const Notify = {
info: function (message) {
Event.publish("notify.info", {message});
Event.publish("notify.info", { message });
},
warn: function (message) {
Event.publish("notify.warning", {message});
Event.publish("notify.warning", { message });
},
error: function (message) {
Event.publish("notify.error", {message});
Event.publish("notify.error", { message });
},
success: function (message) {
Event.publish("notify.success", {message});
Event.publish("notify.success", { message });
},
logout: function (message) {
Event.publish("notify.error", {message});
Event.publish("session.logout", {message});
Event.publish("notify.error", { message });
Event.publish("session.logout", { message });
},
ajaxStart: function() {
ajaxStart: function () {
Event.publish("ajax.start");
},
ajaxEnd: function() {
ajaxEnd: function () {
Event.publish("ajax.end");
},
blockUI: function() {
blockUI: function () {
const el = document.getElementById("busy-overlay");
if(el) {
if (el) {
el.style.display = "block";
}
},
unblockUI: function() {
unblockUI: function () {
const el = document.getElementById("busy-overlay");
if(el) {
if (el) {
el.style.display = "none";
}
},

View File

@@ -180,17 +180,17 @@ export default class Session {
deleteData() {
this.auth = false;
this.user = new User;
this.user = new User();
this.data = null;
this.storage.removeItem("data");
}
sendClientInfo() {
const clientInfo = {
"session": this.getId(),
"js": window.__CONFIG__.jsHash,
"css": window.__CONFIG__.cssHash,
"version": window.__CONFIG__.version,
session: this.getId(),
js: window.__CONFIG__.jsHash,
css: window.__CONFIG__.cssHash,
version: window.__CONFIG__.version,
};
try {
@@ -205,25 +205,21 @@ export default class Session {
login(username, password, token) {
this.deleteId();
return Api.post("session", {username, password, token}).then(
(resp) => {
return Api.post("session", { username, password, token }).then((resp) => {
this.setConfig(resp.data.config);
this.setId(resp.data.id);
this.setData(resp.data.data);
this.sendClientInfo();
}
);
});
}
redeemToken(token) {
return Api.post("session", {token}).then(
(resp) => {
return Api.post("session", { token }).then((resp) => {
this.setConfig(resp.data.config);
this.setId(resp.data.id);
this.setData(resp.data.data);
this.sendClientInfo();
}
);
});
}
onLogout(noRedirect) {

View File

@@ -66,8 +66,8 @@ export default class Util {
let result = [];
let h = Math.floor(u / Hour);
let min = Math.floor(u / Minute)%60;
let sec = Math.ceil(u / Second)%60;
let min = Math.floor(u / Minute) % 60;
let sec = Math.ceil(u / Second) % 60;
result.push(h.toString().padStart(2, "0"));
result.push(min.toString().padStart(2, "0"));
@@ -96,8 +96,7 @@ export default class Util {
I: 1,
};
let a;
if (number < 1 || number > 3999)
return "";
if (number < 1 || number > 3999) return "";
else {
for (let key in romanNumList) {
a = Math.floor(number / romanNumList[key]);

View File

@@ -62,11 +62,41 @@ class Viewer {
}
const shareButtons = [
{id: "fit_720", template: "Tiny (size)", label: "Tiny", url: "{{raw_image_url}}", download: true},
{id: "fit_1280", template: "Small (size)", label: "Small", url: "{{raw_image_url}}", download: true},
{id: "fit_2048", template: "Medium (size)", label: "Medium", url: "{{raw_image_url}}", download: true},
{id: "fit_2560", template: "Large (size)", label: "Large", url: "{{raw_image_url}}", download: true},
{id: "original", template: "Original (size)", label: "Original", url: "{{raw_image_url}}", download: true},
{
id: "fit_720",
template: "Tiny (size)",
label: "Tiny",
url: "{{raw_image_url}}",
download: true,
},
{
id: "fit_1280",
template: "Small (size)",
label: "Small",
url: "{{raw_image_url}}",
download: true,
},
{
id: "fit_2048",
template: "Medium (size)",
label: "Medium",
url: "{{raw_image_url}}",
download: true,
},
{
id: "fit_2560",
template: "Large (size)",
label: "Large",
url: "{{raw_image_url}}",
download: true,
},
{
id: "original",
template: "Original (size)",
label: "Original",
url: "{{raw_image_url}}",
download: true,
},
];
const options = {
@@ -84,29 +114,32 @@ class Viewer {
counterEl: false,
arrowEl: true,
preloaderEl: true,
addCaptionHTMLFn: function(item, captionEl /*, isFake */) {
addCaptionHTMLFn: function (item, captionEl /*, isFake */) {
// item - slide object
// captionEl - caption DOM element
// isFake - true when content is added to fake caption container
// (used to get size of next or previous caption)
if(!item.title) {
if (!item.title) {
captionEl.children[0].innerHTML = "";
return false;
}
captionEl.children[0].innerHTML = stripHtml(item.title);
if(item.playable) {
captionEl.children[0].innerHTML += " <i aria-hidden=\"true\" class=\"v-icon material-icons theme--dark\">movie_creation</i>";
if (item.playable) {
captionEl.children[0].innerHTML +=
' <i aria-hidden="true" class="v-icon material-icons theme--dark">movie_creation</i>';
}
if(item.description) {
captionEl.children[0].innerHTML += "<br><span class=\"description\">" + stripHtml(item.description) + "</span>";
if (item.description) {
captionEl.children[0].innerHTML +=
'<br><span class="description">' + stripHtml(item.description) + "</span>";
}
if(item.playable) {
captionEl.children[0].innerHTML = "<button>" + captionEl.children[0].innerHTML + "</button>";
if (item.playable) {
captionEl.children[0].innerHTML =
"<button>" + captionEl.children[0].innerHTML + "</button>";
}
return true;
@@ -133,7 +166,9 @@ class Viewer {
gallery.listen("initialZoomIn", () => Event.publish("viewer.pause"));
gallery.listen("initialZoomOut", () => Event.publish("viewer.pause"));
gallery.listen("beforeChange", () => Event.publish("viewer.change", {gallery: gallery, item: gallery.currItem}));
gallery.listen("beforeChange", () =>
Event.publish("viewer.change", { gallery: gallery, item: gallery.currItem })
);
gallery.listen("beforeResize", () => {
realViewportWidth = gallery.viewportSize.x * window.devicePixelRatio;

View File

@@ -1,21 +1,23 @@
export let vm = {
$gettext: (msgid) => msgid,
$ngettext: (msgid, plural, n) => { return n > 1 ? plural : msgid; },
$pgettext:(context, msgid) => msgid,
$ngettext: (msgid, plural, n) => {
return n > 1 ? plural : msgid;
},
$pgettext: (context, msgid) => msgid,
$npgettext: (context, msgid) => msgid,
};
export function $gettext (msgid) {
export function $gettext(msgid) {
return vm.$gettext(msgid);
}
export function $ngettext (msgid, plural, n) {
export function $ngettext(msgid, plural, n) {
return vm.$ngettext(msgid, plural, n);
}
export function Mount (Vue, app, router) {
export function Mount(Vue, app, router) {
vm = new Vue({
router,
render: h => h(app),
render: (h) => h(app),
}).$mount("#photoprism");
}

View File

@@ -30,21 +30,21 @@ 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 prot = "https:" === document.location.protocol ? "wss://" : "ws://";
const url = prot + host + "/api/v1/ws";
const Socket = new Sockette(url, {
timeout: 5e3,
onopen: e => {
onopen: (e) => {
console.log("websocket: connected");
config.disconnected = false;
document.body.classList.remove("disconnected");
Event.publish("websocket.connected", e);
},
onmessage: e => {
onmessage: (e) => {
const m = JSON.parse(e.data);
Event.publish(m.event, m.data);
},

View File

@@ -48,22 +48,22 @@ import PAboutFooter from "./footer.vue";
const components = {};
components.install = (Vue) => {
Vue.component("p-notify", PNotify);
Vue.component("p-navigation", PNavigation);
Vue.component("p-scroll-top", PScrollTop);
Vue.component("p-loading-bar", PLoadingBar);
Vue.component("p-video-player", PVideoPlayer);
Vue.component("p-photo-viewer", PPhotoViewer);
Vue.component("p-photo-toolbar", PPhotoToolbar);
Vue.component("p-photo-cards", PPhotoCards);
Vue.component("p-photo-mosaic", PPhotoMosaic);
Vue.component("p-photo-list", PPhotoList);
Vue.component("p-photo-clipboard", PPhotoClipboard);
Vue.component("p-album-clipboard", PAlbumClipboard);
Vue.component("p-album-toolbar", PAlbumToolbar);
Vue.component("p-label-clipboard", PLabelClipboard);
Vue.component("p-file-clipboard", PFileClipboard);
Vue.component("p-about-footer", PAboutFooter);
Vue.component("PNotify", PNotify);
Vue.component("PNavigation", PNavigation);
Vue.component("PScrollTop", PScrollTop);
Vue.component("PLoadingBar", PLoadingBar);
Vue.component("PVideoPlayer", PVideoPlayer);
Vue.component("PPhotoViewer", PPhotoViewer);
Vue.component("PPhotoToolbar", PPhotoToolbar);
Vue.component("PPhotoCards", PPhotoCards);
Vue.component("PPhotoMosaic", PPhotoMosaic);
Vue.component("PPhotoList", PPhotoList);
Vue.component("PPhotoClipboard", PPhotoClipboard);
Vue.component("PAlbumClipboard", PAlbumClipboard);
Vue.component("PAlbumToolbar", PAlbumToolbar);
Vue.component("PLabelClipboard", PLabelClipboard);
Vue.component("PFileClipboard", PFileClipboard);
Vue.component("PAboutFooter", PAboutFooter);
};
export default components;

View File

@@ -48,22 +48,22 @@ import PReloadDialog from "./reload.vue";
const dialogs = {};
dialogs.install = (Vue) => {
Vue.component("p-account-add-dialog", PAccountAddDialog);
Vue.component("p-account-remove-dialog", PAccountRemoveDialog);
Vue.component("p-account-edit-dialog", PAccountEditDialog);
Vue.component("p-photo-archive-dialog", PPhotoArchiveDialog);
Vue.component("p-photo-album-dialog", PPhotoAlbumDialog);
Vue.component("p-photo-edit-dialog", PPhotoEditDialog);
Vue.component("p-file-delete-dialog", PFileDeleteDialog);
Vue.component("p-album-edit-dialog", PAlbumEditDialog);
Vue.component("p-album-delete-dialog", PAlbumDeleteDialog);
Vue.component("p-label-delete-dialog", PLabelDeleteDialog);
Vue.component("p-upload-dialog", PUploadDialog);
Vue.component("p-video-dialog", PVideoDialog);
Vue.component("p-share-dialog", PShareDialog);
Vue.component("p-share-upload-dialog", PShareUploadDialog);
Vue.component("p-webdav-dialog", PWebdavDialog);
Vue.component("p-reload-dialog", PReloadDialog);
Vue.component("PAccountAddDialog", PAccountAddDialog);
Vue.component("PAccountRemoveDialog", PAccountRemoveDialog);
Vue.component("PAccountEditDialog", PAccountEditDialog);
Vue.component("PPhotoArchiveDialog", PPhotoArchiveDialog);
Vue.component("PPhotoAlbumDialog", PPhotoAlbumDialog);
Vue.component("PPhotoEditDialog", PPhotoEditDialog);
Vue.component("PFileDeleteDialog", PFileDeleteDialog);
Vue.component("PAlbumEditDialog", PAlbumEditDialog);
Vue.component("PAlbumDeleteDialog", PAlbumDeleteDialog);
Vue.component("PLabelDeleteDialog", PLabelDeleteDialog);
Vue.component("PUploadDialog", PUploadDialog);
Vue.component("PVideoDialog", PVideoDialog);
Vue.component("PShareDialog", PShareDialog);
Vue.component("PShareUploadDialog", PShareUploadDialog);
Vue.component("PWebdavDialog", PWebdavDialog);
Vue.component("PReloadDialog", PReloadDialog);
};
export default dialogs;

View File

@@ -30,8 +30,8 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Api from "common/api";
import {$gettext} from "common/vm";
import {config} from "../session";
import { $gettext } from "common/vm";
import { config } from "../session";
export class Account extends RestModel {
getDefaults() {
@@ -75,13 +75,17 @@ export class Account extends RestModel {
}
Folders() {
return Api.get(this.getEntityResource() + "/folders").then((response) => Promise.resolve(response.data));
return Api.get(this.getEntityResource() + "/folders").then((response) =>
Promise.resolve(response.data)
);
}
Share(photos, dest) {
const values = {Photos: photos, Destination: dest};
const values = { Photos: photos, Destination: dest };
return Api.post(this.getEntityResource() + "/share", values).then((response) => Promise.resolve(response.data));
return Api.post(this.getEntityResource() + "/share", values).then((response) =>
Promise.resolve(response.data)
);
}
static getCollectionResource() {

View File

@@ -30,9 +30,9 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Api from "common/api";
import {DateTime} from "luxon";
import {config} from "../session";
import {$gettext} from "common/vm";
import { DateTime } from "luxon";
import { config } from "../session";
import { $gettext } from "common/vm";
export class Album extends RestModel {
getDefaults() {
@@ -108,13 +108,13 @@ export class Album extends RestModel {
}
localDate(time) {
if(!this.TakenAtLocal) {
if (!this.TakenAtLocal) {
return this.utcDate();
}
let zone = this.getTimeZone();
return DateTime.fromISO(this.localDateString(time), {zone});
return DateTime.fromISO(this.localDateString(time), { zone });
}
getDateString() {
@@ -123,7 +123,7 @@ export class Album extends RestModel {
} else if (!this.Month || this.Month <= 0) {
return this.localYearString();
} else if (!this.Day || this.Day <= 0) {
return this.getDate().toLocaleString({month: "long", year: "numeric"});
return this.getDate().toLocaleString({ month: "long", year: "numeric" });
}
return this.localDate().toLocaleString(DateTime.DATE_HUGE);

View File

@@ -30,10 +30,10 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Api from "common/api";
import {DateTime} from "luxon";
import { DateTime } from "luxon";
import Util from "common/util";
import {config} from "../session";
import {$gettext} from "common/vm";
import { config } from "../session";
import { $gettext } from "common/vm";
export class File extends RestModel {
getDefaults() {
@@ -126,8 +126,9 @@ export class File extends RestModel {
}
calculateSize(width, height) {
if (width >= this.Width && height >= this.Height) { // Smaller
return {width: this.Width, height: this.Height};
if (width >= this.Width && height >= this.Height) {
// Smaller
return { width: this.Width, height: this.Height };
}
const srcAspectRatio = this.Width / this.Height;
@@ -138,13 +139,12 @@ export class File extends RestModel {
if (srcAspectRatio > maxAspectRatio) {
newW = width;
newH = Math.round(newW / srcAspectRatio);
} else {
newH = height;
newW = Math.round(newH * srcAspectRatio);
}
return {width: newW, height: newH};
return { width: newW, height: newH };
}
getDateString() {

View File

@@ -30,10 +30,10 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Api from "common/api";
import {DateTime} from "luxon";
import { DateTime } from "luxon";
import File from "model/file";
import Util from "common/util";
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
export const RootImport = "import";
export const RootOriginals = "originals";
@@ -71,7 +71,7 @@ export class Folder extends RestModel {
result = this.Path.substring(slash + 1);
}
if(truncate) {
if (truncate) {
result = Util.truncate(result, truncate, "…");
}
@@ -115,15 +115,15 @@ export class Folder extends RestModel {
}
static findAll(path) {
return this.search(path, {recursive: true});
return this.search(path, { recursive: true });
}
static findAllUncached(path) {
return this.search(path, {recursive: true, uncached: true});
return this.search(path, { recursive: true, uncached: true });
}
static originals(path, params) {
if(!path || path[0] !== "/") {
if (!path || path[0] !== "/") {
path = "/" + path;
}
return this.search(RootOriginals + path, params);

View File

@@ -30,9 +30,9 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Api from "common/api";
import {DateTime} from "luxon";
import {config} from "../session";
import {$gettext} from "common/vm";
import { DateTime } from "luxon";
import { config } from "../session";
import { $gettext } from "common/vm";
export class Label extends RestModel {
getDefaults() {

View File

@@ -29,8 +29,8 @@ https://docs.photoprism.org/developer-guide/
*/
import Model from "./model";
import {DateTime} from "luxon";
import {$gettext} from "common/vm";
import { DateTime } from "luxon";
import { $gettext } from "common/vm";
export default class Link extends Model {
getDefaults() {
@@ -58,11 +58,11 @@ export default class Link extends Model {
url() {
let token = this.getToken();
if(!token) {
if (!token) {
token = "…";
}
if(this.hasSlug()) {
if (this.hasSlug()) {
return `${window.location.origin}/s/${token}/${this.Slug}`;
}
@@ -94,7 +94,9 @@ export default class Link extends Model {
}
expires() {
return DateTime.fromISO(this.UpdatedAt).plus({ seconds: this.Expires }).toLocaleString(DateTime.DATE_SHORT);
return DateTime.fromISO(this.UpdatedAt)
.plus({ seconds: this.Expires })
.toLocaleString(DateTime.DATE_SHORT);
}
static getCollectionResource() {

View File

@@ -51,7 +51,6 @@ export class Model {
} else if (!scalarOnly) {
this.__originalValues[key] = JSON.parse(JSON.stringify(values[key]));
}
}
}
@@ -68,7 +67,7 @@ export class Model {
if (defaults.hasOwnProperty(key)) {
switch (typeof defaults[key]) {
case "string":
if(this[key] === null || this[key] === undefined) {
if (this[key] === null || this[key] === undefined) {
val = "";
} else {
val = this[key];
@@ -100,7 +99,7 @@ export class Model {
wasChanged() {
const changed = this.getValues(true);
if(!changed) {
if (!changed) {
return false;
}

View File

@@ -31,11 +31,11 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import File from "model/file";
import Api from "common/api";
import {DateTime} from "luxon";
import { DateTime } from "luxon";
import Util from "common/util";
import {config} from "../session";
import { config } from "../session";
import countries from "options/countries.json";
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
export const SrcManual = "manual";
export const CodecAvc1 = "avc1";
@@ -197,7 +197,7 @@ export class Photo extends RestModel {
let zone = this.getTimeZone();
return DateTime.fromISO(this.localDateString(time), {zone});
return DateTime.fromISO(this.localDateString(time), { zone });
}
utcDate() {
@@ -254,7 +254,7 @@ export class Photo extends RestModel {
return false;
}
return this.Files.findIndex(f => f.Video) !== -1;
return this.Files.findIndex((f) => f.Video) !== -1;
}
videoFile() {
@@ -262,14 +262,14 @@ export class Photo extends RestModel {
return false;
}
let file = this.Files.find(f => f.Codec === CodecAvc1);
let file = this.Files.find((f) => f.Codec === CodecAvc1);
if (!file) {
file = this.Files.find(f => f.Type === FormatMp4);
file = this.Files.find((f) => f.Type === FormatMp4);
}
if (!file) {
file = this.Files.find(f => !!f.Video);
file = this.Files.find((f) => !!f.Video);
}
return file;
@@ -290,13 +290,13 @@ export class Photo extends RestModel {
return this;
}
let file = this.Files.find(f => !!f.Primary);
let file = this.Files.find((f) => !!f.Primary);
if (file) {
return file;
}
return this.Files.find(f => f.Type === FormatJpeg);
return this.Files.find((f) => f.Type === FormatJpeg);
}
mainFileHash() {
@@ -380,8 +380,9 @@ export class Photo extends RestModel {
}
calculateSize(width, height) {
if (width >= this.Width && height >= this.Height) { // Smaller
return {width: this.Width, height: this.Height};
if (width >= this.Width && height >= this.Height) {
// Smaller
return { width: this.Width, height: this.Height };
}
const srcAspectRatio = this.Width / this.Height;
@@ -392,13 +393,12 @@ export class Photo extends RestModel {
if (srcAspectRatio > maxAspectRatio) {
newW = width;
newH = Math.round(newW / srcAspectRatio);
} else {
newH = height;
newW = Math.round(newH * srcAspectRatio);
}
return {width: newW, height: newH};
return { width: newW, height: newH };
}
getDateString() {
@@ -407,7 +407,7 @@ export class Photo extends RestModel {
} else if (this.Month === MonthUnknown) {
return this.localYearString();
} else if (this.Day === DayUnknown) {
return this.localDate().toLocaleString({month: "long", year: "numeric"});
return this.localDate().toLocaleString({ month: "long", year: "numeric" });
} else if (this.TimeZone) {
return this.localDate().toLocaleString(DateTime.DATETIME_FULL);
}
@@ -421,7 +421,7 @@ export class Photo extends RestModel {
} else if (this.Month === MonthUnknown) {
return this.localYearString();
} else if (this.Day === DayUnknown) {
return this.localDate().toLocaleString({month: "long", year: "numeric"});
return this.localDate().toLocaleString({ month: "long", year: "numeric" });
}
return this.localDate().toLocaleString(DateTime.DATE_MED);
@@ -433,7 +433,7 @@ export class Photo extends RestModel {
countryName() {
if (this.Country !== "zz") {
const country = countries.find(c => c.Code === this.Country);
const country = countries.find((c) => c.Code === this.Country);
if (country) {
return country.Name;
@@ -445,7 +445,7 @@ export class Photo extends RestModel {
locationInfo() {
if (this.PlaceID === "zz" && this.Country !== "zz") {
const country = countries.find(c => c.Code === this.Country);
const country = countries.find((c) => c.Code === this.Country);
if (country) {
return country.Name;
@@ -548,7 +548,7 @@ export class Photo extends RestModel {
}
archive() {
return Api.post("batch/photos/archive", {"photos": [this.getId()]});
return Api.post("batch/photos/archive", { photos: [this.getId()] });
}
approve() {
@@ -568,19 +568,25 @@ export class Photo extends RestModel {
togglePrivate() {
this.Private = !this.Private;
return Api.put(this.getEntityResource(), {Private: this.Private});
return Api.put(this.getEntityResource(), { Private: this.Private });
}
primaryFile(fileUID) {
return Api.post(`${this.getEntityResource()}/files/${fileUID}/primary`).then((r) => Promise.resolve(this.setValues(r.data)));
return Api.post(`${this.getEntityResource()}/files/${fileUID}/primary`).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
unstackFile(fileUID) {
return Api.post(`${this.getEntityResource()}/files/${fileUID}/unstack`).then((r) => Promise.resolve(this.setValues(r.data)));
return Api.post(`${this.getEntityResource()}/files/${fileUID}/unstack`).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
deleteFile(fileUID) {
return Api.delete(`${this.getEntityResource()}/files/${fileUID}`).then((r) => Promise.resolve(this.setValues(r.data)));
return Api.delete(`${this.getEntityResource()}/files/${fileUID}`).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
like() {
@@ -594,23 +600,27 @@ export class Photo extends RestModel {
}
addLabel(name) {
return Api.post(this.getEntityResource() + "/label", {Name: name, Priority: 10})
.then((r) => Promise.resolve(this.setValues(r.data)));
return Api.post(this.getEntityResource() + "/label", { Name: name, Priority: 10 }).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
activateLabel(id) {
return Api.put(this.getEntityResource() + "/label/" + id, {Uncertainty: 0})
.then((r) => Promise.resolve(this.setValues(r.data)));
return Api.put(this.getEntityResource() + "/label/" + id, { Uncertainty: 0 }).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
renameLabel(id, name) {
return Api.put(this.getEntityResource() + "/label/" + id, {Label: {Name: name}})
.then((r) => Promise.resolve(this.setValues(r.data)));
return Api.put(this.getEntityResource() + "/label/" + id, { Label: { Name: name } }).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
removeLabel(id) {
return Api.delete(this.getEntityResource() + "/label/" + id)
.then((r) => Promise.resolve(this.setValues(r.data)));
return Api.delete(this.getEntityResource() + "/label/" + id).then((r) =>
Promise.resolve(this.setValues(r.data))
);
}
update() {
@@ -636,7 +646,14 @@ export class Photo extends RestModel {
values.TakenSrc = SrcManual;
}
if (values.CameraID || values.LensID || values.FocalLength || values.FNumber || values.Iso || values.Exposure) {
if (
values.CameraID ||
values.LensID ||
values.FocalLength ||
values.FNumber ||
values.Iso ||
values.Exposure
) {
values.CameraSrc = SrcManual;
}

View File

@@ -32,7 +32,7 @@ import Api from "common/api";
import Form from "common/form";
import Model from "./model";
import Link from "./link";
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
export class Rest extends Model {
getId() {
@@ -52,7 +52,9 @@ export class Rest extends Model {
}
find(id, params) {
return Api.get(this.getEntityResource(id), params).then((resp) => Promise.resolve(new this.constructor(resp.data)));
return Api.get(this.getEntityResource(id), params).then((resp) =>
Promise.resolve(new this.constructor(resp.data))
);
}
save() {
@@ -60,11 +62,15 @@ export class Rest extends Model {
return this.update();
}
return Api.post(this.constructor.getCollectionResource(), this.getValues()).then((resp) => Promise.resolve(this.setValues(resp.data)));
return Api.post(this.constructor.getCollectionResource(), this.getValues()).then((resp) =>
Promise.resolve(this.setValues(resp.data))
);
}
update() {
return Api.put(this.getEntityResource(), this.getValues(true)).then((resp) => Promise.resolve(this.setValues(resp.data)));
return Api.put(this.getEntityResource(), this.getValues(true)).then((resp) =>
Promise.resolve(this.setValues(resp.data))
);
}
remove() {
@@ -72,7 +78,9 @@ export class Rest extends Model {
}
getEditForm() {
return Api.options(this.getEntityResource()).then(resp => Promise.resolve(new Form(resp.data)));
return Api.options(this.getEntityResource()).then((resp) =>
Promise.resolve(new Form(resp.data))
);
}
getEntityResource(id) {
@@ -88,37 +96,35 @@ export class Rest extends Model {
}
createLink(password, expires) {
return Api
.post(this.getEntityResource() + "/links", {
"Password": password ? password : "",
"Expires": expires ? expires : 0,
"Slug": this.getSlug(),
"CanEdit": false,
"CanComment": false,
})
.then((resp) => Promise.resolve(new Link(resp.data)));
return Api.post(this.getEntityResource() + "/links", {
Password: password ? password : "",
Expires: expires ? expires : 0,
Slug: this.getSlug(),
CanEdit: false,
CanComment: false,
}).then((resp) => Promise.resolve(new Link(resp.data)));
}
updateLink(link) {
let values = link.getValues(false);
if(link.Token) {
if (link.Token) {
values["Token"] = link.getToken();
}
if(link.Password) {
if (link.Password) {
values["Password"] = link.Password;
}
return Api
.put(this.getEntityResource() + "/links/" + link.getId(), values)
.then((resp) => Promise.resolve(link.setValues(resp.data)));
return Api.put(this.getEntityResource() + "/links/" + link.getId(), values).then((resp) =>
Promise.resolve(link.setValues(resp.data))
);
}
removeLink(link) {
return Api
.delete(this.getEntityResource() + "/links/" + link.getId())
.then((resp) => Promise.resolve(link.setValues(resp.data)));
return Api.delete(this.getEntityResource() + "/links/" + link.getId()).then((resp) =>
Promise.resolve(link.setValues(resp.data))
);
}
links() {
@@ -148,7 +154,9 @@ export class Rest extends Model {
}
static getCreateForm() {
return Api.options(this.getCreateResource()).then(resp => Promise.resolve(new Form(resp.data)));
return Api.options(this.getCreateResource()).then((resp) =>
Promise.resolve(new Form(resp.data))
);
}
static getModelName() {
@@ -156,7 +164,9 @@ export class Rest extends Model {
}
static getSearchForm() {
return Api.options(this.getCollectionResource()).then(resp => Promise.resolve(new Form(resp.data)));
return Api.options(this.getCollectionResource()).then((resp) =>
Promise.resolve(new Form(resp.data))
);
}
static limit() {

View File

@@ -37,7 +37,7 @@ export class Settings extends Model {
return false;
}
return (this[area][key] !== this.__originalValues[area][key]);
return this[area][key] !== this.__originalValues[area][key];
}
load() {
@@ -47,7 +47,9 @@ export class Settings extends Model {
}
save() {
return Api.post("settings", this.getValues(true)).then((response) => Promise.resolve(this.setValues(response.data)));
return Api.post("settings", this.getValues(true)).then((response) =>
Promise.resolve(this.setValues(response.data))
);
}
}

View File

@@ -30,8 +30,8 @@ https://docs.photoprism.org/developer-guide/
import Model from "./model";
import Api from "common/api";
import {config} from "../session";
import {$gettext} from "common/vm";
import { config } from "../session";
import { $gettext } from "common/vm";
const thumbs = window.__CONFIG__.thumbs;
@@ -206,8 +206,9 @@ export class Thumb extends Model {
}
static calculateSize(file, width, height) {
if (width >= file.Width && height >= file.Height) { // Smaller
return {width: file.Width, height: file.Height};
if (width >= file.Width && height >= file.Height) {
// Smaller
return { width: file.Width, height: file.Height };
}
const srcAspectRatio = file.Width / file.Height;
@@ -218,19 +219,17 @@ export class Thumb extends Model {
if (srcAspectRatio > maxAspectRatio) {
newW = width;
newH = Math.round(newW / srcAspectRatio);
} else {
newH = height;
newW = Math.round(newH * srcAspectRatio);
}
return {width: newW, height: newH};
return { width: newW, height: newH };
}
static thumbnailUrl(file, size) {
if (!file.Hash) {
return "/api/v1/svg/photo";
}
return `/api/v1/t/${file.Hash}/${config.previewToken()}/${size}`;

View File

@@ -31,7 +31,7 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Form from "common/form";
import Api from "common/api";
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
export class User extends RestModel {
getDefaults() {
@@ -90,11 +90,15 @@ export class User extends RestModel {
}
getRegisterForm() {
return Api.options(this.getEntityResource() + "/register").then(response => Promise.resolve(new Form(response.data)));
return Api.options(this.getEntityResource() + "/register").then((response) =>
Promise.resolve(new Form(response.data))
);
}
getProfileForm() {
return Api.options(this.getEntityResource() + "/profile").then(response => Promise.resolve(new Form(response.data)));
return Api.options(this.getEntityResource() + "/profile").then((response) =>
Promise.resolve(new Form(response.data))
);
}
changePassword(oldPassword, newPassword) {
@@ -105,7 +109,9 @@ export class User extends RestModel {
}
saveProfile() {
return Api.post(this.getEntityResource() + "/profile", this.getValues()).then((response) => Promise.resolve(this.setValues(response.data)));
return Api.post(this.getEntityResource() + "/profile", this.getValues()).then((response) =>
Promise.resolve(this.setValues(response.data))
);
}
static getCollectionResource() {

View File

@@ -1,8 +1,8 @@
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
import moment from "moment-timezone";
import {Info} from "luxon";
import {config} from "../session";
import {TypeVideo,TypeImage,TypeLive,TypeRaw} from "../model/photo";
import { Info } from "luxon";
import { config } from "../session";
import { TypeVideo, TypeImage, TypeLive, TypeRaw } from "../model/photo";
export const TimeZones = () => moment.tz.names();
@@ -10,10 +10,10 @@ export const Days = () => {
let result = [];
for (let i = 1; i <= 31; i++) {
result.push({"value": i, "text": i.toString().padStart(2, "0")});
result.push({ value: i, text: i.toString().padStart(2, "0") });
}
result.push({"value": -1, "text": $gettext("Unknown")});
result.push({ value: -1, text: $gettext("Unknown") });
return result;
};
@@ -24,10 +24,10 @@ export const Years = () => {
const currentYear = new Date().getUTCFullYear();
for (let i = currentYear; i >= 1750; i--) {
result.push({"value": i, "text": i.toString().padStart(4, "0")});
result.push({ value: i, text: i.toString().padStart(4, "0") });
}
result.push({"value": -1, "text": $gettext("Unknown")});
result.push({ value: -1, text: $gettext("Unknown") });
return result;
};
@@ -37,11 +37,14 @@ export const IndexedYears = () => {
if (config.values.years) {
for (let i = 0; i < config.values.years.length; i++) {
result.push({"value": parseInt(config.values.years[i]), "text": config.values.years[i].toString()});
result.push({
value: parseInt(config.values.years[i]),
text: config.values.years[i].toString(),
});
}
}
result.push({"value": -1, "text": $gettext("Unknown")});
result.push({ value: -1, text: $gettext("Unknown") });
return result;
};
@@ -52,10 +55,10 @@ export const Months = () => {
const months = Info.months("long");
for (let i = 0; i < months.length; i++) {
result.push({"value": i + 1, "text": months[i]});
result.push({ value: i + 1, text: months[i] });
}
result.push({"value": -1, "text": $gettext("Unknown")});
result.push({ value: -1, text: $gettext("Unknown") });
return result;
};
@@ -64,213 +67,213 @@ export const MonthsShort = () => {
let result = [];
for (let i = 1; i <= 12; i++) {
result.push({"value": i, "text": i.toString().padStart(2, "0")});
result.push({ value: i, text: i.toString().padStart(2, "0") });
}
result.push({"value": -1, "text": $gettext("Unknown")});
result.push({ value: -1, text: $gettext("Unknown") });
return result;
};
export const Languages = () => [
{
"text": "English",
"translated": $gettext("English"),
"value": "en",
text: "English",
translated: $gettext("English"),
value: "en",
},
{
"text": "Deutsch",
"translated": $gettext("German"),
"value": "de",
text: "Deutsch",
translated: $gettext("German"),
value: "de",
},
{
"text": "Español",
"translated": $gettext("Spanish"),
"value": "es",
text: "Español",
translated: $gettext("Spanish"),
value: "es",
},
{
"text": "Français",
"translated": $gettext("French"),
"value": "fr",
text: "Français",
translated: $gettext("French"),
value: "fr",
},
{
"text": "हिन्दी",
"translated": $gettext("Hindi"),
"value": "hi",
text: "हिन्दी",
translated: $gettext("Hindi"),
value: "hi",
},
{
"text": "Nederlands",
"translated": $gettext("Dutch"),
"value": "nl",
text: "Nederlands",
translated: $gettext("Dutch"),
value: "nl",
},
{
"text": "Polski",
"translated": $gettext("Polish"),
"value": "pl",
text: "Polski",
translated: $gettext("Polish"),
value: "pl",
},
{
"text": "Português do Brasil",
"translated": $gettext("Brazilian Portuguese"),
"value": "pt_BR",
text: "Português do Brasil",
translated: $gettext("Brazilian Portuguese"),
value: "pt_BR",
},
{
"text": "Русский",
"translated": $gettext("Russian"),
"value": "ru",
text: "Русский",
translated: $gettext("Russian"),
value: "ru",
},
{
"text": "Slovenčina",
"translated": $gettext("Slovak"),
"value": "sk",
text: "Slovenčina",
translated: $gettext("Slovak"),
value: "sk",
},
{
"text": "简体中文",
"translated": $gettext("Chinese Simplified"),
"value": "zh",
text: "简体中文",
translated: $gettext("Chinese Simplified"),
value: "zh",
},
{
"text": "繁体中文",
"translated": $gettext("Chinese Traditional"),
"value": "zh_TW",
text: "繁体中文",
translated: $gettext("Chinese Traditional"),
value: "zh_TW",
},
];
export const Themes = () => [
{
"text": $gettext("Default"),
"value": "default",
text: $gettext("Default"),
value: "default",
},
{
"text": $gettext("Cyano"),
"value": "cyano",
text: $gettext("Cyano"),
value: "cyano",
},
{
"text": $gettext("Lavender"),
"value": "lavender",
text: $gettext("Lavender"),
value: "lavender",
},
{
"text": $gettext("Moonlight"),
"value": "moonlight",
text: $gettext("Moonlight"),
value: "moonlight",
},
{
"text": $gettext("Onyx"),
"value": "onyx",
text: $gettext("Onyx"),
value: "onyx",
},
{
"text": $gettext("Raspberry"),
"value": "raspberry",
text: $gettext("Raspberry"),
value: "raspberry",
},
{
"text": $gettext("Seaweed"),
"value": "seaweed",
text: $gettext("Seaweed"),
value: "seaweed",
},
];
export const MapsAnimate = () => [
{
"text": $gettext("None"),
"value": 0,
text: $gettext("None"),
value: 0,
},
{
"text": $gettext("Fast"),
"value": 2500,
text: $gettext("Fast"),
value: 2500,
},
{
"text": $gettext("Medium"),
"value": 6250,
text: $gettext("Medium"),
value: 6250,
},
{
"text": $gettext("Slow"),
"value": 10000,
text: $gettext("Slow"),
value: 10000,
},
];
export const MapsStyle = () => [
{
"text": $gettext("Offline"),
"value": "offline",
text: $gettext("Offline"),
value: "offline",
},
{
"text": $gettext("Streets"),
"value": "streets",
text: $gettext("Streets"),
value: "streets",
},
{
"text": $gettext("Hybrid"),
"value": "hybrid",
text: $gettext("Hybrid"),
value: "hybrid",
},
{
"text": $gettext("Topographic"),
"value": "topographique",
text: $gettext("Topographic"),
value: "topographique",
},
{
"text": $gettext("Outdoor"),
"value": "outdoor",
text: $gettext("Outdoor"),
value: "outdoor",
},
];
export const PhotoTypes = () => [
{
"text": $gettext("Image"),
"value": TypeImage,
text: $gettext("Image"),
value: TypeImage,
},
{
"text": $gettext("Raw"),
"value": TypeRaw,
text: $gettext("Raw"),
value: TypeRaw,
},
{
"text": $gettext("Live"),
"value": TypeLive,
text: $gettext("Live"),
value: TypeLive,
},
{
"text": $gettext("Video"),
"value": TypeVideo,
text: $gettext("Video"),
value: TypeVideo,
},
];
export const Intervals = () => [
{"value": 0, "text": $gettext("Never")},
{"value": 3600, "text": $gettext("1 hour")},
{"value": 3600 * 4, "text": $gettext("4 hours")},
{"value": 3600 * 12, "text": $gettext("12 hours")},
{"value": 86400, "text": $gettext("Daily")},
{"value": 86400 * 2, "text": $gettext("Every two days")},
{"value": 86400 * 7, "text": $gettext("Once a week")},
{ value: 0, text: $gettext("Never") },
{ value: 3600, text: $gettext("1 hour") },
{ value: 3600 * 4, text: $gettext("4 hours") },
{ value: 3600 * 12, text: $gettext("12 hours") },
{ value: 86400, text: $gettext("Daily") },
{ value: 86400 * 2, text: $gettext("Every two days") },
{ value: 86400 * 7, text: $gettext("Once a week") },
];
export const Expires = () => [
{"value": 0, "text": $gettext("Never")},
{"value": 86400, "text": $gettext("After 1 day")},
{"value": 86400 * 3, "text": $gettext("After 3 days")},
{"value": 86400 * 7, "text": $gettext("After 7 days")},
{"value": 86400 * 14, "text": $gettext("After two weeks")},
{"value": 86400 * 31, "text": $gettext("After one month")},
{"value": 86400 * 60, "text": $gettext("After two months")},
{"value": 86400 * 365, "text": $gettext("After one year")},
{ value: 0, text: $gettext("Never") },
{ value: 86400, text: $gettext("After 1 day") },
{ value: 86400 * 3, text: $gettext("After 3 days") },
{ value: 86400 * 7, text: $gettext("After 7 days") },
{ value: 86400 * 14, text: $gettext("After two weeks") },
{ value: 86400 * 31, text: $gettext("After one month") },
{ value: 86400 * 60, text: $gettext("After two months") },
{ value: 86400 * 365, text: $gettext("After one year") },
];
export const Colors = () => [
{"Example": "#AB47BC", "Name": $gettext("Purple"), "Slug": "purple"},
{"Example": "#FF00FF", "Name": $gettext("Magenta"), "Slug": "magenta"},
{"Example": "#EC407A", "Name": $gettext("Pink"), "Slug": "pink"},
{"Example": "#EF5350", "Name": $gettext("Red"), "Slug": "red"},
{"Example": "#FFA726", "Name": $gettext("Orange"), "Slug": "orange"},
{"Example": "#D4AF37", "Name": $gettext("Gold"), "Slug": "gold"},
{"Example": "#FDD835", "Name": $gettext("Yellow"), "Slug": "yellow"},
{"Example": "#CDDC39", "Name": $gettext("Lime"), "Slug": "lime"},
{"Example": "#66BB6A", "Name": $gettext("Green"), "Slug": "green"},
{"Example": "#009688", "Name": $gettext("Teal"), "Slug": "teal"},
{"Example": "#00BCD4", "Name": $gettext("Cyan"), "Slug": "cyan"},
{"Example": "#2196F3", "Name": $gettext("Blue"), "Slug": "blue"},
{"Example": "#A1887F", "Name": $gettext("Brown"), "Slug": "brown"},
{"Example": "#F5F5F5", "Name": $gettext("White"), "Slug": "white"},
{"Example": "#9E9E9E", "Name": $gettext("Grey"), "Slug": "grey"},
{"Example": "#212121", "Name": $gettext("Black"), "Slug": "black"},
{ Example: "#AB47BC", Name: $gettext("Purple"), Slug: "purple" },
{ Example: "#FF00FF", Name: $gettext("Magenta"), Slug: "magenta" },
{ Example: "#EC407A", Name: $gettext("Pink"), Slug: "pink" },
{ Example: "#EF5350", Name: $gettext("Red"), Slug: "red" },
{ Example: "#FFA726", Name: $gettext("Orange"), Slug: "orange" },
{ Example: "#D4AF37", Name: $gettext("Gold"), Slug: "gold" },
{ Example: "#FDD835", Name: $gettext("Yellow"), Slug: "yellow" },
{ Example: "#CDDC39", Name: $gettext("Lime"), Slug: "lime" },
{ Example: "#66BB6A", Name: $gettext("Green"), Slug: "green" },
{ Example: "#009688", Name: $gettext("Teal"), Slug: "teal" },
{ Example: "#00BCD4", Name: $gettext("Cyan"), Slug: "cyan" },
{ Example: "#2196F3", Name: $gettext("Blue"), Slug: "blue" },
{ Example: "#A1887F", Name: $gettext("Brown"), Slug: "brown" },
{ Example: "#F5F5F5", Name: $gettext("White"), Slug: "white" },
{ Example: "#9E9E9E", Name: $gettext("Grey"), Slug: "grey" },
{ Example: "#212121", Name: $gettext("Black"), Slug: "black" },
];
export const FeedbackCategories = () => [
{"value": "help", "text": $gettext("Customer Support")},
{"value": "feedback", "text": $gettext("Product Feedback")},
{"value": "feature", "text": $gettext("Feature Request")},
{"value": "bug", "text": $gettext("Bug Report")},
{"value": "donations", "text": $gettext("Donations")},
{"value": "other", "text": $gettext("Other")},
{ value: "help", text: $gettext("Customer Support") },
{ value: "feedback", text: $gettext("Product Feedback") },
{ value: "feature", text: $gettext("Feature Request") },
{ value: "bug", text: $gettext("Bug Report") },
{ value: "donations", text: $gettext("Donations") },
{ value: "other", text: $gettext("Other") },
];

View File

@@ -44,7 +44,7 @@ import About from "pages/about/about.vue";
import Feedback from "pages/about/feedback.vue";
import License from "pages/about/license.vue";
import Help from "pages/help.vue";
import {$gettext} from "common/vm";
import { $gettext } from "common/vm";
const c = window.__CONFIG__;
@@ -58,274 +58,295 @@ export default [
name: "about",
path: "/about",
component: About,
meta: {title: c.name, auth: false},
meta: { title: c.name, auth: false },
},
{
name: "feedback",
path: "/feedback",
component: Feedback,
meta: {title: c.name, auth: true},
meta: { title: c.name, auth: true },
},
{
name: "license",
path: "/about/license",
component: License,
meta: {title: c.name, auth: false},
meta: { title: c.name, auth: false },
},
{
name: "help",
path: "/help*",
component: Help,
meta: {title: c.name, auth: false},
meta: { title: c.name, auth: false },
},
{
name: "login",
path: "/login",
component: Login,
meta: {auth: false},
meta: { auth: false },
},
{
name: "photos",
path: "/photos",
component: Photos,
meta: {title: c.name, auth: true},
props: {staticFilter: {photo: "true"}},
meta: { title: c.name, auth: true },
props: { staticFilter: { photo: "true" } },
},
{
name: "moments",
path: "/moments",
component: Albums,
meta: {title: $gettext("Moments"), auth: true},
props: {view: "moment", staticFilter: {type: "moment"}},
meta: { title: $gettext("Moments"), auth: true },
props: { view: "moment", staticFilter: { type: "moment" } },
},
{
name: "moment",
path: "/moments/:uid/:slug",
component: AlbumPhotos,
meta: {title: $gettext("Moments"), auth: true},
meta: { title: $gettext("Moments"), auth: true },
},
{
name: "albums",
path: "/albums",
component: Albums,
meta: {title: $gettext("Albums"), auth: true},
props: {view: "album", staticFilter: {type: "album"}},
meta: { title: $gettext("Albums"), auth: true },
props: { view: "album", staticFilter: { type: "album" } },
},
{
name: "album",
path: "/albums/:uid/:slug",
component: AlbumPhotos,
meta: {auth: true},
meta: { auth: true },
},
{
name: "calendar",
path: "/calendar",
component: Albums,
meta: {title: $gettext("Calendar"), auth: true},
props: {view: "month", staticFilter: {type: "month"}},
meta: { title: $gettext("Calendar"), auth: true },
props: { view: "month", staticFilter: { type: "month" } },
},
{
name: "month",
path: "/calendar/:uid/:slug",
component: AlbumPhotos,
meta: {title: $gettext("Calendar"), auth: true},
meta: { title: $gettext("Calendar"), auth: true },
},
{
name: "folders",
path: "/folders",
component: Albums,
meta: {title: $gettext("Folders"), auth: true},
props: {view: "folder", staticFilter: {type: "folder", order: "default"}},
meta: { title: $gettext("Folders"), auth: true },
props: { view: "folder", staticFilter: { type: "folder", order: "default" } },
},
{
name: "folder",
path: "/folders/:uid/:slug",
component: AlbumPhotos,
meta: {title: $gettext("Folders"), auth: true},
meta: { title: $gettext("Folders"), auth: true },
},
{
name: "unsorted",
path: "/unsorted",
component: Photos,
meta: {title: $gettext("Unsorted"), auth: true},
props: {staticFilter: {unsorted: true}},
meta: { title: $gettext("Unsorted"), auth: true },
props: { staticFilter: { unsorted: true } },
},
{
name: "favorites",
path: "/favorites",
component: Photos,
meta: {title: $gettext("Favorites"), auth: true},
props: {staticFilter: {favorite: true}},
meta: { title: $gettext("Favorites"), auth: true },
props: { staticFilter: { favorite: true } },
},
{
name: "videos",
path: "/videos",
component: Photos,
meta: {title: $gettext("Videos"), auth: true},
props: {staticFilter: {video: "true"}},
meta: { title: $gettext("Videos"), auth: true },
props: { staticFilter: { video: "true" } },
},
{
name: "review",
path: "/review",
component: Photos,
meta: {title: $gettext("Review"), auth: true},
props: {staticFilter: {review: true}},
meta: { title: $gettext("Review"), auth: true },
props: { staticFilter: { review: true } },
},
{
name: "private",
path: "/private",
component: Photos,
meta: {title: $gettext("Private"), auth: true},
props: {staticFilter: {private: true}},
meta: { title: $gettext("Private"), auth: true },
props: { staticFilter: { private: true } },
},
{
name: "archive",
path: "/archive",
component: Photos,
meta: {title: $gettext("Archive"), auth: true},
props: {staticFilter: {archived: true}},
meta: { title: $gettext("Archive"), auth: true },
props: { staticFilter: { archived: true } },
},
{
name: "places",
path: "/places",
component: Places,
meta: {title: $gettext("Places"), auth: true},
meta: { title: $gettext("Places"), auth: true },
},
{
name: "place",
path: "/places/:q",
component: Places,
meta: {title: $gettext("Places"), auth: true},
meta: { title: $gettext("Places"), auth: true },
},
{
name: "states",
path: "/states",
component: Albums,
meta: {title: $gettext("Places"), auth: true},
props: {view: "state", staticFilter: {type: "state"}},
meta: { title: $gettext("Places"), auth: true },
props: { view: "state", staticFilter: { type: "state" } },
},
{
name: "state",
path: "/states/:uid/:slug",
component: AlbumPhotos,
meta: {title: $gettext("Places"), auth: true},
meta: { title: $gettext("Places"), auth: true },
},
{
name: "files",
path: "/library/files*",
component: Files,
meta: {title: $gettext("File Browser"), auth: true},
meta: { title: $gettext("File Browser"), auth: true },
},
{
name: "hidden",
path: "/library/hidden",
component: Photos,
meta: {title: $gettext("Hidden Files"), auth: true},
props: {staticFilter: {hidden: true}},
meta: { title: $gettext("Hidden Files"), auth: true },
props: { staticFilter: { hidden: true } },
},
{
name: "errors",
path: "/library/errors",
component: Errors,
meta: {title: c.name, auth: true},
meta: { title: c.name, auth: true },
},
{
name: "labels",
path: "/labels",
component: Labels,
meta: {title: $gettext("Labels"), auth: true},
meta: { title: $gettext("Labels"), auth: true },
},
{
name: "browse",
path: "/browse",
component: Photos,
meta: {title: $gettext("Search"), auth: true},
props: {staticFilter: {quality: 0}},
meta: { title: $gettext("Search"), auth: true },
props: { staticFilter: { quality: 0 } },
},
{
name: "people",
path: "/people",
component: People,
meta: {title: $gettext("People"), auth: true},
meta: { title: $gettext("People"), auth: true },
},
{
name: "library",
path: "/library",
component: Library,
meta: {title: $gettext("Library"), auth: true, background: "application-light"},
props: {tab: "library-index"},
meta: { title: $gettext("Library"), auth: true, background: "application-light" },
props: { tab: "library-index" },
},
{
name: "library_import",
path: "/library/import",
component: Library,
meta: {title: $gettext("Library"), auth: true, background: "application-light"},
props: {tab: "library-import"},
meta: { title: $gettext("Library"), auth: true, background: "application-light" },
props: { tab: "library-import" },
},
{
name: "library_logs",
path: "/library/logs",
component: Library,
meta: {title: $gettext("Library"), auth: true, background: "application-light"},
props: {tab: "library-logs"},
meta: { title: $gettext("Library"), auth: true, background: "application-light" },
props: { tab: "library-logs" },
},
{
name: "settings",
path: "/settings",
component: Settings,
meta: {title: $gettext("Settings"), auth: true, settings: true, background: "application-light"},
props: {tab: "settings-general"},
meta: {
title: $gettext("Settings"),
auth: true,
settings: true,
background: "application-light",
},
props: { tab: "settings-general" },
},
{
name: "settings_library",
path: "/settings/library",
component: Settings,
meta: {title: $gettext("Settings"), auth: true, settings: true, background: "application-light"},
props: {tab: "settings-library"},
meta: {
title: $gettext("Settings"),
auth: true,
settings: true,
background: "application-light",
},
props: { tab: "settings-library" },
},
{
name: "settings_sync",
path: "/settings/sync",
component: Settings,
meta: {title: $gettext("Settings"), auth: true, settings: true, background: "application-light"},
props: {tab: "settings-sync"},
meta: {
title: $gettext("Settings"),
auth: true,
settings: true,
background: "application-light",
},
props: { tab: "settings-sync" },
},
{
name: "settings_account",
path: "/settings/account",
component: Settings,
meta: {title: $gettext("Settings"), auth: true, settings: true, background: "application-light"},
props: {tab: "settings-account"},
meta: {
title: $gettext("Settings"),
auth: true,
settings: true,
background: "application-light",
},
props: { tab: "settings-account" },
},
{
name: "discover",
path: "/discover",
component: Discover,
meta: {title: $gettext("Discover"), auth: true, background: "application-light"},
props: {tab: 0},
meta: { title: $gettext("Discover"), auth: true, background: "application-light" },
props: { tab: 0 },
},
{
name: "discover_similar",
path: "/discover/similar",
component: Discover,
meta: {title: $gettext("Discover"), auth: true, background: "application-light"},
props: {tab: 1},
meta: { title: $gettext("Discover"), auth: true, background: "application-light" },
props: { tab: 1 },
},
{
name: "discover_season",
path: "/discover/season",
component: Discover,
meta: {title: $gettext("Discover"), auth: true, background: "application-light"},
props: {tab: 2},
meta: { title: $gettext("Discover"), auth: true, background: "application-light" },
props: { tab: 2 },
},
{
name: "discover_random",
path: "/discover/random",
component: Discover,
meta: {title: $gettext("Discover"), auth: true, background: "application-light"},
props: {tab: 3},
meta: { title: $gettext("Discover"), auth: true, background: "application-light" },
props: { tab: 3 },
},
{
path: "*", redirect: "/photos",
path: "*",
redirect: "/photos",
},
];

View File

@@ -41,8 +41,8 @@ import Log from "common/log";
import PhotoPrism from "share.vue";
import Router from "vue-router";
import Routes from "share/routes";
import {config, session} from "session";
import {Settings} from "luxon";
import { config, session } from "session";
import { Settings } from "luxon";
import Socket from "common/websocket";
import Viewer from "common/viewer";
import Vue from "vue";
@@ -53,13 +53,15 @@ import VueFullscreen from "vue-fullscreen";
import VueInfiniteScroll from "vue-infinite-scroll";
import VueModal from "vue-js-modal";
import Hls from "hls.js";
import {$gettext, Mount} from "common/vm";
import { $gettext, Mount } from "common/vm";
// Initialize helpers
const viewer = new Viewer();
const clipboard = new Clipboard(window.localStorage, "photo_clipboard");
const isPublic = config.get("public");
const isMobile = (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
);
// HTTP Live Streaming (video support)
window.Hls = Hls;
@@ -77,7 +79,7 @@ Vue.prototype.$clipboard = clipboard;
Vue.prototype.$isMobile = isMobile;
// Register Vuetify
Vue.use(Vuetify, {"theme": config.theme});
Vue.use(Vuetify, { theme: config.theme });
Vue.config.language = config.values.settings.ui.language;
Settings.defaultLocale = Vue.config.language.substring(0, 2);
@@ -93,7 +95,7 @@ Vue.use(GetTextPlugin, {
Vue.use(VueLuxon);
Vue.use(VueInfiniteScroll);
Vue.use(VueFullscreen);
Vue.use(VueModal, {dynamic: true, dynamicDefaults: {clickToClose: true}});
Vue.use(VueModal, { dynamic: true, dynamicDefaults: { clickToClose: true } });
Vue.use(VueFilters);
Vue.use(Components);
Vue.use(Dialogs);
@@ -107,24 +109,24 @@ const router = new Router({
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.settings) && config.values.disable.settings) {
next({name: "home"});
} else if (to.matched.some(record => record.meta.admin)) {
if (to.matched.some((record) => record.meta.settings) && config.values.disable.settings) {
next({ name: "home" });
} else if (to.matched.some((record) => record.meta.admin)) {
if (isPublic || session.isAdmin()) {
next();
} else {
next({
name: "login",
params: {nextUrl: to.fullPath},
params: { nextUrl: to.fullPath },
});
}
} else if (to.matched.some(record => record.meta.auth)) {
} else if (to.matched.some((record) => record.meta.auth)) {
if (isPublic || session.isUser()) {
next();
} else {
next({
name: "login",
params: {nextUrl: to.fullPath},
params: { nextUrl: to.fullPath },
});
}
} else {

View File

@@ -43,17 +43,17 @@ import PAlbumClipboard from "./album/clipboard.vue";
const components = {};
components.install = (Vue) => {
Vue.component("p-notify", PNotify);
Vue.component("p-navigation", PNavigation);
Vue.component("p-scroll-top", PScrollTop);
Vue.component("p-loading-bar", PLoadingBar);
Vue.component("p-video-player", PVideoPlayer);
Vue.component("p-photo-viewer", PPhotoViewer);
Vue.component("p-photo-cards", PPhotoCards);
Vue.component("p-photo-mosaic", PPhotoMosaic);
Vue.component("p-photo-list", PPhotoList);
Vue.component("p-photo-clipboard", PPhotoClipboard);
Vue.component("p-album-clipboard", PAlbumClipboard);
Vue.component("PNotify", PNotify);
Vue.component("PNavigation", PNavigation);
Vue.component("PScrollTop", PScrollTop);
Vue.component("PLoadingBar", PLoadingBar);
Vue.component("PVideoPlayer", PVideoPlayer);
Vue.component("PPhotoViewer", PPhotoViewer);
Vue.component("PPhotoCards", PPhotoCards);
Vue.component("PPhotoMosaic", PPhotoMosaic);
Vue.component("PPhotoList", PPhotoList);
Vue.component("PPhotoClipboard", PPhotoClipboard);
Vue.component("PAlbumClipboard", PAlbumClipboard);
};
export default components;

View File

@@ -2,28 +2,30 @@ import Albums from "share/albums.vue";
import AlbumPhotos from "share/photos.vue";
const c = window.__CONFIG__;
const shareTitle = c.settings.share.title ? c.settings.share.title : c.siteAuthor ? c.siteAuthor : c.name;
const siteTitle = c.siteAuthor ? c.siteAuthor : c.name;
const shareTitle = c.settings.share.title ? c.settings.share.title : siteTitle;
export default [
{
name: "home",
path: "/",
redirect: {name: "albums"},
redirect: { name: "albums" },
},
{
name: "albums",
path: "/s/:token",
component: Albums,
meta: {title: shareTitle, auth: true},
props: {view: "album", staticFilter: {type: "album"}},
meta: { title: shareTitle, auth: true },
props: { view: "album", staticFilter: { type: "album" } },
},
{
name: "album",
path: "/s/:token/:uid",
component: AlbumPhotos,
meta: {title: shareTitle, auth: true},
meta: { title: shareTitle, auth: true },
},
{
path: "*", redirect: {name: "albums"},
path: "*",
redirect: { name: "albums" },
},
];

View File

@@ -36,7 +36,7 @@ const webpack = require("webpack");
const isDev = process.env.NODE_ENV !== "production";
if(isDev) {
if (isDev) {
console.log("Building frontend in DEVELOPMENT mode. Please wait.");
} else {
console.log("Building frontend in PRODUCTION mode. Please wait.");
@@ -62,10 +62,7 @@ const config = {
filename: "[name].js",
},
resolve: {
modules: [
path.join(__dirname, "src"),
path.join(__dirname, "node_modules"),
],
modules: [path.join(__dirname, "src"), path.join(__dirname, "node_modules")],
alias: {
vue: isDev ? "vue/dist/vue.js" : "vue/dist/vue.min.js",
},
@@ -110,9 +107,7 @@ const config = {
test: /\.js$/,
loader: "babel-loader",
include: PATHS.js,
exclude: file => (
/node_modules/.test(file)
),
exclude: (file) => /node_modules/.test(file),
query: {
presets: ["@babel/preset-env"],
compact: false,
@@ -197,7 +192,6 @@ const config = {
"resolve-url-loader",
"sass-loader",
],
},
{
test: /\.(png|jpg|jpeg|gif)$/,