Great big ESLint
This commit is contained in:
parent
051eabbdc3
commit
ebcb938da1
48 changed files with 3890 additions and 2536 deletions
24
.eslintrc.js
Normal file
24
.eslintrc.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
"plugin:vue/recommended",
|
||||
"eslint:recommended",
|
||||
"prettier/vue",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
rules: {
|
||||
"vue/component-name-in-template-casing": ["error", "PascalCase"],
|
||||
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
|
||||
},
|
||||
globals: {
|
||||
$nuxt: true
|
||||
},
|
||||
parserOptions: {
|
||||
parser: "babel-eslint"
|
||||
}
|
||||
};
|
||||
|
|
@ -1,27 +1,27 @@
|
|||
const electron = require('electron')
|
||||
const contextMenu = require('electron-context-menu')
|
||||
const path = require('path')
|
||||
const electron = require("electron");
|
||||
const contextMenu = require("electron-context-menu");
|
||||
const path = require("path");
|
||||
|
||||
const app = electron.app
|
||||
const BrowserWindow = electron.BrowserWindow
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
let url = 'http://localhost:8080/'
|
||||
let url = "http://localhost:8080/";
|
||||
|
||||
// Set the application menu
|
||||
require('./menu.js')
|
||||
require("./menu.js");
|
||||
|
||||
app.on('ready', () => {
|
||||
app.on("ready", () => {
|
||||
let window = new BrowserWindow({
|
||||
width: 1124,
|
||||
width: 1124,
|
||||
height: 800,
|
||||
icon: path.join(__dirname, '/icons/png/64x64.png')
|
||||
})
|
||||
icon: path.join(__dirname, "/icons/png/64x64.png")
|
||||
});
|
||||
|
||||
contextMenu({
|
||||
showCopyImageAddress: true,
|
||||
showSaveImageAs: true,
|
||||
showInspectElement: true,
|
||||
showInspectElement: true
|
||||
});
|
||||
|
||||
window.loadURL(url)
|
||||
})
|
||||
window.loadURL(url);
|
||||
});
|
||||
|
|
|
|||
149
app/app.js
149
app/app.js
|
|
@ -1,144 +1,159 @@
|
|||
// Required packages
|
||||
const electron = require('electron')
|
||||
const { dialog } = require('electron')
|
||||
const electron = require("electron");
|
||||
const { dialog } = require("electron");
|
||||
const updater = require("electron-updater");
|
||||
const autoUpdater = updater.autoUpdater;
|
||||
const contextMenu = require('electron-context-menu')
|
||||
const path = require('path')
|
||||
const contextMenu = require("electron-context-menu");
|
||||
const path = require("path");
|
||||
|
||||
// Attach settings store
|
||||
const { store } = require('./store')
|
||||
const { store } = require("./store");
|
||||
|
||||
// Auto upadater
|
||||
// Auto upadater
|
||||
autoUpdater.autoDownload = false;
|
||||
|
||||
autoUpdater.on('checking-for-update', function () {});
|
||||
autoUpdater.on("checking-for-update", function() {});
|
||||
|
||||
autoUpdater.on('update-available', function (info) {
|
||||
sendStatusToWindow('Update available.' + info)
|
||||
dialog.showMessageBox(mainWindow, {
|
||||
type: 'info',
|
||||
title: 'Update available',
|
||||
message: 'A new version of OpenFlexure eV is available.',
|
||||
buttons: ['Download', 'Later']
|
||||
}, (buttonIndex) => {
|
||||
if (buttonIndex === 0) {
|
||||
autoUpdater.downloadUpdate()
|
||||
autoUpdater.on("update-available", function(info) {
|
||||
sendStatusToWindow("Update available." + info);
|
||||
dialog.showMessageBox(
|
||||
mainWindow,
|
||||
{
|
||||
type: "info",
|
||||
title: "Update available",
|
||||
message: "A new version of OpenFlexure eV is available.",
|
||||
buttons: ["Download", "Later"]
|
||||
},
|
||||
buttonIndex => {
|
||||
if (buttonIndex === 0) {
|
||||
autoUpdater.downloadUpdate();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', function (info) {
|
||||
sendStatusToWindow('Update downloaded.' + info)
|
||||
dialog.showMessageBox(mainWindow, {
|
||||
type: 'info',
|
||||
autoUpdater.on("update-downloaded", function(info) {
|
||||
sendStatusToWindow("Update downloaded." + info);
|
||||
dialog.showMessageBox(
|
||||
mainWindow,
|
||||
{
|
||||
type: "info",
|
||||
title: "Update downloaded",
|
||||
message: 'Please restart the application to apply the update.',
|
||||
buttons: ['Update', 'Later']
|
||||
}, (buttonIndex) => {
|
||||
if (buttonIndex === 0) {
|
||||
autoUpdater.quitAndInstall();
|
||||
message: "Please restart the application to apply the update.",
|
||||
buttons: ["Update", "Later"]
|
||||
},
|
||||
buttonIndex => {
|
||||
if (buttonIndex === 0) {
|
||||
autoUpdater.quitAndInstall();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', function (info) {
|
||||
sendStatusToWindow('Update not available.');
|
||||
autoUpdater.on("update-not-available", function() {
|
||||
sendStatusToWindow("Update not available.");
|
||||
});
|
||||
|
||||
autoUpdater.on('error', function (err) {
|
||||
sendStatusToWindow('Error in auto-updater.');
|
||||
autoUpdater.on("error", function() {
|
||||
sendStatusToWindow("Error in auto-updater.");
|
||||
});
|
||||
|
||||
autoUpdater.on('download-progress', function (progressObj) {
|
||||
autoUpdater.on("download-progress", function(progressObj) {
|
||||
let log_message = "Download speed: " + progressObj.bytesPerSecond;
|
||||
log_message = log_message + ' - Downloaded ' + parseInt(progressObj.percent) + '%';
|
||||
log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
|
||||
log_message =
|
||||
log_message + " - Downloaded " + parseInt(progressObj.percent) + "%";
|
||||
log_message =
|
||||
log_message +
|
||||
" (" +
|
||||
progressObj.transferred +
|
||||
"/" +
|
||||
progressObj.total +
|
||||
")";
|
||||
sendStatusToWindow(log_message);
|
||||
});
|
||||
|
||||
function sendStatusToWindow(message) {
|
||||
console.log(message);
|
||||
console.log(message);
|
||||
}
|
||||
|
||||
// Set up the app
|
||||
const app = electron.app
|
||||
const BrowserWindow = electron.BrowserWindow
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
// Set the window content
|
||||
let url = `file://${path.join(__dirname, '/dist/index.html')}`
|
||||
let mainWindow
|
||||
let url = `file://${path.join(__dirname, "/dist/index.html")}`;
|
||||
let mainWindow;
|
||||
|
||||
// Set the application menu
|
||||
require('./menu.js')
|
||||
require("./menu.js");
|
||||
|
||||
// Handle redrawing the mainWindow
|
||||
let recreatingWindowInProgress = false;
|
||||
|
||||
function toggleCustomTitleBar () {
|
||||
function toggleCustomTitleBar() {
|
||||
// Mark window as being recreated, to prevent stopping the application
|
||||
recreatingWindowInProgress = true
|
||||
recreatingWindowInProgress = true;
|
||||
|
||||
// Invert the drawCustomTitleBar setting
|
||||
store.set('drawCustomTitleBar', !store.get('drawCustomTitleBar'))
|
||||
store.set("drawCustomTitleBar", !store.get("drawCustomTitleBar"));
|
||||
|
||||
// Destroy old window
|
||||
mainWindow.destroy()
|
||||
mainWindow.destroy();
|
||||
// Create new window
|
||||
createWindow()
|
||||
createWindow();
|
||||
|
||||
// Mark window as no longer being recreated
|
||||
recreatingWindowInProgress = false
|
||||
recreatingWindowInProgress = false;
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
frame: !store.get('drawCustomTitleBar'),
|
||||
width: 1124,
|
||||
frame: !store.get("drawCustomTitleBar"),
|
||||
width: 1124,
|
||||
height: 800,
|
||||
icon: path.join(__dirname, '/icons/png/64x64.png'),
|
||||
icon: path.join(__dirname, "/icons/png/64x64.png"),
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Make a context menu
|
||||
contextMenu({
|
||||
showCopyImageAddress: true,
|
||||
showSaveImageAs: true,
|
||||
showInspectElement: false,
|
||||
showInspectElement: false
|
||||
});
|
||||
|
||||
// Load window contents
|
||||
mainWindow.loadURL(url)
|
||||
mainWindow.loadURL(url);
|
||||
|
||||
// Check for updates
|
||||
autoUpdater.checkForUpdates();
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function() {
|
||||
mainWindow = null // Dereference the window object
|
||||
})
|
||||
mainWindow.on("closed", function() {
|
||||
mainWindow = null; // Dereference the window object
|
||||
});
|
||||
}
|
||||
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.on('ready', () => {
|
||||
createWindow()
|
||||
})
|
||||
app.on("ready", () => {
|
||||
createWindow();
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
if ((process.platform !== 'darwin') && recreatingWindowInProgress != true) {
|
||||
app.quit()
|
||||
app.on("window-all-closed", function() {
|
||||
if (process.platform !== "darwin" && recreatingWindowInProgress != true) {
|
||||
app.quit();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
app.on('activate', function() {
|
||||
app.on("activate", function() {
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
createWindow();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Export toggleCustomTitleBar for use in ./menu.js
|
||||
module.exports.toggleCustomTitleBar = toggleCustomTitleBar
|
||||
module.exports.toggleCustomTitleBar = toggleCustomTitleBar;
|
||||
|
|
|
|||
151
app/menu.js
151
app/menu.js
|
|
@ -1,129 +1,122 @@
|
|||
const { app, shell, Menu } = require('electron')
|
||||
const { app, shell, Menu } = require("electron");
|
||||
const updater = require("electron-updater");
|
||||
const autoUpdater = updater.autoUpdater;
|
||||
const path = require('path')
|
||||
const path = require("path");
|
||||
|
||||
const openAboutWindow = require('about-window').default
|
||||
const openAboutWindow = require("about-window").default;
|
||||
|
||||
const main = require('./app')
|
||||
const { store } = require('./store')
|
||||
const main = require("./app");
|
||||
const { store } = require("./store");
|
||||
|
||||
const template = [
|
||||
{
|
||||
label: 'Edit',
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'delete' },
|
||||
{ role: 'selectall' }
|
||||
{ role: "undo" },
|
||||
{ role: "redo" },
|
||||
{ type: "separator" },
|
||||
{ role: "cut" },
|
||||
{ role: "copy" },
|
||||
{ role: "paste" },
|
||||
{ role: "delete" },
|
||||
{ role: "selectall" }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
label: "View",
|
||||
submenu: [
|
||||
{ role: 'reload' },
|
||||
{ role: 'forcereload' },
|
||||
{ role: 'toggledevtools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' },
|
||||
{ type: 'separator' },
|
||||
{ role: "reload" },
|
||||
{ role: "forcereload" },
|
||||
{ role: "toggledevtools" },
|
||||
{ type: "separator" },
|
||||
{ role: "togglefullscreen" },
|
||||
{ type: "separator" },
|
||||
{
|
||||
type: 'checkbox',
|
||||
checked: store.get('drawCustomTitleBar'),
|
||||
label: 'Custom titlebar',
|
||||
click () {
|
||||
main.toggleCustomTitleBar()
|
||||
type: "checkbox",
|
||||
checked: store.get("drawCustomTitleBar"),
|
||||
label: "Custom titlebar",
|
||||
click() {
|
||||
main.toggleCustomTitleBar();
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{ role: 'minimize' },
|
||||
{ role: 'close' }
|
||||
]
|
||||
role: "window",
|
||||
submenu: [{ role: "minimize" }, { role: "close" }]
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
role: "help",
|
||||
submenu: [
|
||||
{
|
||||
label: 'About',
|
||||
click () {
|
||||
label: "About",
|
||||
click() {
|
||||
openAboutWindow({
|
||||
package_json_dir: path.join(__dirname, '..'),
|
||||
icon_path: path.join(__dirname, '/icons/png/512x512.png'),
|
||||
bug_report_url: "https://gitlab.com/openflexure/openflexure-microscope-jsclient/issues",
|
||||
homepage: "https://gitlab.com/openflexure/openflexure-microscope-jsclient",
|
||||
})
|
||||
package_json_dir: path.join(__dirname, ".."),
|
||||
icon_path: path.join(__dirname, "/icons/png/512x512.png"),
|
||||
bug_report_url:
|
||||
"https://gitlab.com/openflexure/openflexure-microscope-jsclient/issues",
|
||||
homepage:
|
||||
"https://gitlab.com/openflexure/openflexure-microscope-jsclient"
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Homepage',
|
||||
click () {
|
||||
shell.openExternal('https://openflexure.org')
|
||||
label: "Homepage",
|
||||
click() {
|
||||
shell.openExternal("https://openflexure.org");
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
click () {
|
||||
label: "Check for Updates",
|
||||
click() {
|
||||
autoUpdater.checkForUpdates();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (process.platform === "darwin") {
|
||||
template.unshift({
|
||||
label: app.getName(),
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' }
|
||||
{ role: "about" },
|
||||
{ type: "separator" },
|
||||
{ role: "services" },
|
||||
{ type: "separator" },
|
||||
{ role: "hide" },
|
||||
{ role: "hideothers" },
|
||||
{ role: "unhide" },
|
||||
{ type: "separator" },
|
||||
{ role: "quit" }
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
// Edit menu
|
||||
template[1].submenu.push(
|
||||
{ type: 'separator' },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: 'Speech',
|
||||
submenu: [
|
||||
{ role: 'startspeaking' },
|
||||
{ role: 'stopspeaking' }
|
||||
]
|
||||
label: "Speech",
|
||||
submenu: [{ role: "startspeaking" }, { role: "stopspeaking" }]
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Window menu
|
||||
template[3].submenu = [
|
||||
{ role: 'close' },
|
||||
{ role: 'minimize' },
|
||||
{ role: 'zoom' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'front' }
|
||||
]
|
||||
}
|
||||
else {
|
||||
{ role: "close" },
|
||||
{ role: "minimize" },
|
||||
{ role: "zoom" },
|
||||
{ type: "separator" },
|
||||
{ role: "front" }
|
||||
];
|
||||
} else {
|
||||
template.unshift({
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{ role: 'quit' }
|
||||
]
|
||||
})
|
||||
label: "File",
|
||||
submenu: [{ role: "quit" }]
|
||||
});
|
||||
}
|
||||
|
||||
const menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
const Store = require('electron-store');
|
||||
const Store = require("electron-store");
|
||||
const store = new Store();
|
||||
|
||||
if (store.has('drawCustomTitleBar') !== true) {
|
||||
if (store.has("drawCustomTitleBar") !== true) {
|
||||
// Default to false if on MacOS, otherwise true
|
||||
store.set('drawCustomTitleBar', (process.platform === 'win32') ? true : false)
|
||||
store.set("drawCustomTitleBar", process.platform === "win32" ? true : false);
|
||||
}
|
||||
|
||||
module.exports.store = store
|
||||
module.exports.store = store;
|
||||
|
|
|
|||
627
package-lock.json
generated
627
package-lock.json
generated
|
|
@ -1538,6 +1538,12 @@
|
|||
"integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
|
||||
"integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
|
||||
|
|
@ -2097,6 +2103,31 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz",
|
||||
"integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"@babel/parser": "^7.0.0",
|
||||
"@babel/traverse": "^7.0.0",
|
||||
"@babel/types": "^7.0.0",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"resolve": "^1.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"resolve": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
|
||||
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-loader": {
|
||||
"version": "8.0.6",
|
||||
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz",
|
||||
|
|
@ -2814,8 +2845,7 @@
|
|||
"chardet": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||
"optional": true
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||
},
|
||||
"check-types": {
|
||||
"version": "8.0.3",
|
||||
|
|
@ -2981,8 +3011,7 @@
|
|||
"cli-width": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
|
||||
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
|
||||
"optional": true
|
||||
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
|
||||
},
|
||||
"clipboardy": {
|
||||
"version": "2.1.0",
|
||||
|
|
@ -4150,6 +4179,12 @@
|
|||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"dev": true
|
||||
},
|
||||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||
"dev": true
|
||||
},
|
||||
"deepmerge": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
|
||||
|
|
@ -4502,6 +4537,15 @@
|
|||
"buffer-indexof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"dom-converter": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
|
||||
|
|
@ -5131,6 +5175,249 @@
|
|||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.6.0.tgz",
|
||||
"integrity": "sha512-PpEBq7b6qY/qrOmpYQ/jTMDYfuQMELR4g4WI1M/NaSDDD/bdcMb+dj4Hgks7p41kW2caXsPsEZAEAyAgjVVC0g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"ajv": "^6.10.0",
|
||||
"chalk": "^2.1.0",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"debug": "^4.0.1",
|
||||
"doctrine": "^3.0.0",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-utils": "^1.4.3",
|
||||
"eslint-visitor-keys": "^1.1.0",
|
||||
"espree": "^6.1.2",
|
||||
"esquery": "^1.0.1",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^5.0.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob-parent": "^5.0.0",
|
||||
"globals": "^11.7.0",
|
||||
"ignore": "^4.0.6",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"inquirer": "^7.0.0",
|
||||
"is-glob": "^4.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.3.0",
|
||||
"lodash": "^4.17.14",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.8.2",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^2.0.1",
|
||||
"semver": "^6.1.2",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"strip-json-comments": "^3.0.1",
|
||||
"table": "^5.2.3",
|
||||
"text-table": "^0.2.0",
|
||||
"v8-compile-cache": "^2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-escapes": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
|
||||
"integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^0.5.2"
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
|
||||
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.1.0",
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz",
|
||||
"integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
|
||||
"integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||
"dev": true
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
|
||||
"integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
|
||||
"integrity": "sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^4.2.1",
|
||||
"chalk": "^2.4.2",
|
||||
"cli-cursor": "^3.1.0",
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^3.0.3",
|
||||
"figures": "^3.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"mute-stream": "0.0.8",
|
||||
"run-async": "^2.2.0",
|
||||
"rxjs": "^6.4.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^5.1.0",
|
||||
"through": "^2.3.6"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"onetime": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
|
||||
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"onetime": "^5.1.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
|
||||
"integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
|
||||
"integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
|
||||
"dev": true
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
|
||||
"integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-config-prettier": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz",
|
||||
"integrity": "sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"get-stdin": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"get-stdin": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
|
||||
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-prettier": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz",
|
||||
"integrity": "sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prettier-linter-helpers": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-vue": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-6.0.0.tgz",
|
||||
"integrity": "sha512-+LxTJCd6nDt+AKQ1X+ySD48xJHft8OkeQmAhiq6UoAMxRFTiEKIDusiGgEUJLwKyiwGUGWbbqEbbWvupH5TSjg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"vue-eslint-parser": "^6.0.4"
|
||||
}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
|
||||
|
|
@ -5141,11 +5428,54 @@
|
|||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
|
||||
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
|
||||
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
|
||||
"integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^7.1.0",
|
||||
"acorn-jsx": "^5.1.0",
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
|
||||
"integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
|
||||
"integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estraverse": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"esrecurse": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
|
||||
|
|
@ -5384,7 +5714,6 @@
|
|||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
|
||||
"integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chardet": "^0.7.0",
|
||||
"iconv-lite": "^0.4.24",
|
||||
|
|
@ -5496,6 +5825,12 @@
|
|||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
},
|
||||
"fast-diff": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
|
||||
|
|
@ -5515,6 +5850,12 @@
|
|||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||
},
|
||||
"fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fastparse": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
|
||||
|
|
@ -5554,6 +5895,15 @@
|
|||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
|
||||
"integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"flat-cache": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"file-loader": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
|
||||
|
|
@ -5663,6 +6013,34 @@
|
|||
"locate-path": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
|
||||
"integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"flatted": "^2.0.0",
|
||||
"rimraf": "2.6.3",
|
||||
"write": "1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"flatted": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
|
||||
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
|
||||
"dev": true
|
||||
},
|
||||
"flush-write-stream": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
|
||||
|
|
@ -5795,7 +6173,8 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
|
@ -5816,12 +6195,14 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -5836,17 +6217,20 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -5963,7 +6347,8 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -5975,6 +6360,7 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
|
@ -5989,6 +6375,7 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -5996,12 +6383,14 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
|
@ -6020,6 +6409,7 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
|
@ -6100,7 +6490,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -6112,6 +6503,7 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -6197,7 +6589,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
|
@ -6233,6 +6626,7 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
@ -6252,6 +6646,7 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
|
@ -6295,12 +6690,14 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -6310,6 +6707,12 @@
|
|||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"functional-red-black-tree": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
||||
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
|
||||
"dev": true
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
|
|
@ -7330,8 +7733,7 @@
|
|||
"is-promise": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
|
||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
|
||||
"optional": true
|
||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.0.4",
|
||||
|
|
@ -7513,6 +7915,12 @@
|
|||
"resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.1.tgz",
|
||||
"integrity": "sha512-IqUK+Cqc8/MqHsCvv1TMccbKdBzoATOLHXZAF5UDu70/CCxo648cHUig24hc+XTK53TyeNk1UeVTlc2Haovtsw=="
|
||||
},
|
||||
"json-stable-stringify-without-jsonify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
|
||||
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
|
||||
"dev": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
|
|
@ -7675,6 +8083,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"lines-and-columns": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
|
||||
|
|
@ -8329,6 +8747,12 @@
|
|||
"to-regex": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"natural-compare": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||
"dev": true
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
|
|
@ -8688,6 +9112,20 @@
|
|||
"is-wsl": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
|
||||
"integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"deep-is": "~0.1.3",
|
||||
"fast-levenshtein": "~2.0.6",
|
||||
"levn": "~0.3.0",
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2",
|
||||
"word-wrap": "~1.2.3"
|
||||
}
|
||||
},
|
||||
"ora": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
|
||||
|
|
@ -8731,8 +9169,7 @@
|
|||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||
"optional": true
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"p-cancelable": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -8842,6 +9279,23 @@
|
|||
"no-case": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"callsites": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"parse-asn1": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
|
||||
|
|
@ -9601,6 +10055,12 @@
|
|||
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
|
||||
"dev": true
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
|
||||
"dev": true
|
||||
},
|
||||
"prepend-http": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
|
||||
|
|
@ -9613,6 +10073,15 @@
|
|||
"integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==",
|
||||
"dev": true
|
||||
},
|
||||
"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==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-diff": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
|
||||
|
|
@ -9651,6 +10120,12 @@
|
|||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true
|
||||
},
|
||||
"progress-stream": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
|
||||
|
|
@ -10135,6 +10610,12 @@
|
|||
"define-properties": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
|
||||
"integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
|
||||
"dev": true
|
||||
},
|
||||
"regexpu-core": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz",
|
||||
|
|
@ -10443,7 +10924,6 @@
|
|||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
|
||||
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-promise": "^2.1.0"
|
||||
}
|
||||
|
|
@ -10461,7 +10941,6 @@
|
|||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
|
||||
"integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
|
|
@ -11465,6 +11944,43 @@
|
|||
"util.promisify": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"version": "5.4.6",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
|
||||
"integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.10.2",
|
||||
"lodash": "^4.17.14",
|
||||
"slice-ansi": "^2.1.0",
|
||||
"string-width": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tapable": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
|
||||
|
|
@ -11603,6 +12119,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"thenify": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
|
||||
|
|
@ -11641,8 +12163,7 @@
|
|||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"optional": true
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
|
|
@ -11679,7 +12200,6 @@
|
|||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
|
|
@ -11827,6 +12347,15 @@
|
|||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"dev": true
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"prelude-ls": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
|
||||
|
|
@ -12206,6 +12735,12 @@
|
|||
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
|
||||
"dev": true
|
||||
},
|
||||
"v8-compile-cache": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
|
||||
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
|
||||
"dev": true
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
|
|
@ -12251,6 +12786,33 @@
|
|||
"integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==",
|
||||
"dev": true
|
||||
},
|
||||
"vue-eslint-parser": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-6.0.5.tgz",
|
||||
"integrity": "sha512-Bvjlx7rH1Ulvus56KHeLXOjEi3JMOYTa1GAqZr9lBQhd8weK8mV7U7V2l85yokBZEWHJQjLn6X3nosY8TzkOKg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"eslint-scope": "^4.0.0",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"espree": "^5.0.0",
|
||||
"esquery": "^1.0.1",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"espree": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
|
||||
"integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^6.0.7",
|
||||
"acorn-jsx": "^5.0.0",
|
||||
"eslint-visitor-keys": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-hot-reload-api": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||
|
|
@ -12696,6 +13258,12 @@
|
|||
"string-width": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
|
|
@ -12758,6 +13326,15 @@
|
|||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
},
|
||||
"write": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
|
||||
"integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mkdirp": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
|
|
|
|||
|
|
@ -34,9 +34,14 @@
|
|||
"@vue/cli-plugin-babel": "^3.11.0",
|
||||
"@vue/cli-service": "^3.11.0",
|
||||
"axios": "^0.19.0",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"css-loader": "^3.2.0",
|
||||
"electron": "^6.0.10",
|
||||
"electron-builder": "^21.2.0",
|
||||
"eslint": "^6.6.0",
|
||||
"eslint-config-prettier": "^6.5.0",
|
||||
"eslint-plugin-prettier": "^3.1.1",
|
||||
"eslint-plugin-vue": "^6.0.0",
|
||||
"less": "^3.10.3",
|
||||
"less-loader": "^5.0.0",
|
||||
"mdns-js": "^1.0.3",
|
||||
|
|
@ -58,4 +63,4 @@
|
|||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
}
|
||||
69
src/App.vue
69
src/App.vue
|
|
@ -1,57 +1,55 @@
|
|||
<template>
|
||||
<div id="app" v-bind:class="handleTheme">
|
||||
|
||||
<div id="app" :class="handleTheme">
|
||||
<!-- Grid managing whole app -->
|
||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove" margin=0>
|
||||
<panelLeft/>
|
||||
<panelRight/>
|
||||
<div
|
||||
uk-grid
|
||||
class="uk-height-1-1 uk-margin-remove uk-padding-remove"
|
||||
margin="0"
|
||||
>
|
||||
<panelLeft />
|
||||
<panelRight />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Import axios for HTTP requests
|
||||
import axios from 'axios'
|
||||
|
||||
// Import components
|
||||
import panelLeft from './components/panelLeft.vue'
|
||||
import panelRight from './components/panelRight.vue'
|
||||
import panelLeft from "./components/panelLeft.vue";
|
||||
import panelRight from "./components/panelRight.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'app',
|
||||
name: "App",
|
||||
|
||||
components: {
|
||||
panelRight,
|
||||
panelLeft
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {}
|
||||
},
|
||||
|
||||
created: function () {
|
||||
window.addEventListener('beforeunload', this.handleExit)
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleExit: function(event) {
|
||||
console.log("Triggered beforeunload")
|
||||
this.$root.$emit('globalTogglePreview', false)
|
||||
}
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
computed: {
|
||||
handleTheme: function () {
|
||||
handleTheme: function() {
|
||||
return {
|
||||
'uk-light': this.$store.state.globalSettings.darkMode,
|
||||
'uk-background-secondary': this.$store.state.globalSettings.darkMode
|
||||
}
|
||||
"uk-light": this.$store.state.globalSettings.darkMode,
|
||||
"uk-background-secondary": this.$store.state.globalSettings.darkMode
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
window.addEventListener("beforeunload", this.handleExit);
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleExit: function() {
|
||||
console.log("Triggered beforeunload");
|
||||
this.$root.$emit("globalTogglePreview", false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
@ -63,7 +61,8 @@ export default {
|
|||
// We override the custom-electron-titlebar z-index
|
||||
// UIKit lightbox must be able to draw over the titlebar
|
||||
// as it currently always spawns at the root of the DOM
|
||||
.titlebar, .titlebar > * {
|
||||
.titlebar,
|
||||
.titlebar > * {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
|
|
@ -71,10 +70,11 @@ export default {
|
|||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: left;
|
||||
height: 100%
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body, html {
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -83,5 +83,4 @@ body, html {
|
|||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
// Theming specific to the electron app
|
||||
|
||||
.menubar-menu-container {
|
||||
box-shadow: 0.5px 1px 4px 0px rgba(0,0,0,0.3) !important;
|
||||
box-shadow: 0.5px 1px 4px 0px rgba(0, 0, 0, 0.3) !important;
|
||||
}
|
||||
|
||||
.menubar-menu-container > * {
|
||||
box-shadow: none !important;
|
||||
.menubar-menu-container>* {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.menubar-menu-container .action-menu-item, .menubar-menu-container .action-label {
|
||||
.menubar-menu-container .action-menu-item,
|
||||
.menubar-menu-container .action-label {
|
||||
cursor: default
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,35 +8,49 @@
|
|||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta { color: #969896; }
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote { color: @global-danger-background; }
|
||||
.hljs-quote {
|
||||
color: @global-danger-background;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type { color: #1f34aa; }
|
||||
.hljs-type {
|
||||
color: #1f34aa;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute { color: #0086b3; }
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name { color: #63a35c; }
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag { color: #333; }
|
||||
.hljs-tag {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo { color: #795da3; }
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
|
|
@ -48,4 +62,6 @@
|
|||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link { text-decoration: underline; }
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
@ -15,31 +15,31 @@
|
|||
// UIkit
|
||||
// ========================================================================
|
||||
|
||||
@global-font-family: ProximaNova, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
@global-font-size: 14px;
|
||||
@global-font-family: ProximaNova, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
@global-font-size: 14px;
|
||||
|
||||
@global-xxlarge-font-size: 38px;
|
||||
@global-xlarge-font-size: 30px;
|
||||
@global-large-font-size: 24px;
|
||||
@global-medium-font-size: 20px;
|
||||
@global-small-font-size: 14px;
|
||||
@global-xxlarge-font-size: 38px;
|
||||
@global-xlarge-font-size: 30px;
|
||||
@global-large-font-size: 24px;
|
||||
@global-medium-font-size: 20px;
|
||||
@global-small-font-size: 14px;
|
||||
|
||||
@global-emphasis-color: #222;
|
||||
@global-emphasis-color: #222;
|
||||
|
||||
//
|
||||
// Base
|
||||
//
|
||||
|
||||
@base-code-font-family: 'Roboto Mono', monospace;
|
||||
@base-code-font-size: 12px;
|
||||
@base-code-font-family: 'Roboto Mono', monospace;
|
||||
@base-code-font-size: 12px;
|
||||
|
||||
@base-heading-font-weight: 300;
|
||||
@base-heading-font-weight: 300;
|
||||
|
||||
@base-pre-font-size: 12px;
|
||||
@base-pre-padding: 25px;
|
||||
@base-pre-background: @global-muted-background;
|
||||
@base-pre-border-width: 0;
|
||||
@base-pre-border-radius: 0;
|
||||
@base-pre-font-size: 12px;
|
||||
@base-pre-padding: 25px;
|
||||
@base-pre-background: @global-muted-background;
|
||||
@base-pre-border-width: 0;
|
||||
@base-pre-border-radius: 0;
|
||||
|
||||
.hook-base-body() {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
|
@ -51,96 +51,103 @@
|
|||
// Container
|
||||
//
|
||||
|
||||
@container-max-width: 1380px;
|
||||
@container-small-max-width: 650px;
|
||||
@container-max-width: 1380px;
|
||||
@container-small-max-width: 650px;
|
||||
|
||||
//
|
||||
// Navbar
|
||||
//
|
||||
|
||||
@inverse-navbar-nav-item-color: @inverse-global-color;
|
||||
@inverse-navbar-nav-item-hover-color: @inverse-global-emphasis-color;
|
||||
@inverse-navbar-nav-item-color: @inverse-global-color;
|
||||
@inverse-navbar-nav-item-hover-color: @inverse-global-emphasis-color;
|
||||
|
||||
//
|
||||
// Nav
|
||||
//
|
||||
|
||||
@nav-header-font-size: 12px;
|
||||
@nav-header-font-size: 12px;
|
||||
|
||||
//
|
||||
// Subnav
|
||||
//
|
||||
|
||||
@inverse-subnav-item-color: @inverse-global-color;
|
||||
@inverse-subnav-item-hover-color: @inverse-global-emphasis-color;
|
||||
@inverse-subnav-item-color: @inverse-global-color;
|
||||
@inverse-subnav-item-hover-color: @inverse-global-emphasis-color;
|
||||
|
||||
//
|
||||
// Tab
|
||||
//
|
||||
|
||||
@tab-item-padding-horizontal: 10px;
|
||||
@tab-item-padding-vertical: 9px;
|
||||
@tab-item-border-width: 2px;
|
||||
@tab-item-font-size: 12px;
|
||||
@tab-item-padding-horizontal: 10px;
|
||||
@tab-item-padding-vertical: 9px;
|
||||
@tab-item-border-width: 2px;
|
||||
@tab-item-font-size: 12px;
|
||||
|
||||
.hook-tab-item() { line-height: 20px; }
|
||||
.hook-tab-item() {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
//
|
||||
// Table
|
||||
//
|
||||
|
||||
@table-header-cell-font-size: 12px;
|
||||
@table-header-cell-font-size: 12px;
|
||||
|
||||
//
|
||||
// Label
|
||||
//
|
||||
|
||||
@label-font-size: 12px;
|
||||
@label-font-size: 12px;
|
||||
|
||||
//
|
||||
// Text
|
||||
//
|
||||
|
||||
.hook-text-lead() { font-weight: 300; }
|
||||
.hook-text-large() { font-weight: 300; }
|
||||
.hook-text-lead() {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.hook-text-large() {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
//
|
||||
// Utility
|
||||
//
|
||||
|
||||
@inverse-logo-color: @inverse-global-emphasis-color;
|
||||
@inverse-logo-hover-color: @inverse-global-emphasis-color;
|
||||
@inverse-logo-color: @inverse-global-emphasis-color;
|
||||
@inverse-logo-hover-color: @inverse-global-emphasis-color;
|
||||
|
||||
//
|
||||
// Off-canvas
|
||||
//
|
||||
|
||||
@offcanvas-bar-background: #fff;
|
||||
@offcanvas-bar-color-mode: dark;
|
||||
@offcanvas-bar-background: #fff;
|
||||
@offcanvas-bar-color-mode: dark;
|
||||
|
||||
//
|
||||
// Inverse
|
||||
//
|
||||
|
||||
@inverse-global-color: fade(@global-inverse-color, 80%);
|
||||
@inverse-global-muted-color: fade(@global-inverse-color, 60%);
|
||||
@inverse-global-color: fade(@global-inverse-color, 80%);
|
||||
@inverse-global-muted-color: fade(@global-inverse-color, 60%);
|
||||
|
||||
//
|
||||
// Paper
|
||||
//
|
||||
@paper-border-radius: 4px;
|
||||
@paper-border-radius: 4px;
|
||||
|
||||
|
||||
/* ========================================================================
|
||||
Theme
|
||||
========================================================================== */
|
||||
|
||||
@sidebar-left-width: 240px;
|
||||
@sidebar-left-width-xl: 300px;
|
||||
@sidebar-left-width: 240px;
|
||||
@sidebar-left-width-xl: 300px;
|
||||
|
||||
@sidebar-right-width: 200px;
|
||||
@sidebar-right-left: 0px;
|
||||
@sidebar-right-left-xl: 60px;
|
||||
@sidebar-right-width: 200px;
|
||||
@sidebar-right-left: 0px;
|
||||
@sidebar-right-left-xl: 60px;
|
||||
|
||||
|
||||
|
||||
|
|
@ -152,11 +159,11 @@
|
|||
*/
|
||||
|
||||
// Line Mode
|
||||
@navbar-nav-item-line-margin-vertical: 20px;
|
||||
@navbar-nav-item-line-margin-horizontal: @navbar-nav-item-padding-horizontal;
|
||||
@navbar-nav-item-line-height: 1px;
|
||||
@navbar-nav-item-line-background: currentColor;
|
||||
@navbar-nav-item-line-transition-duration: 0.3s;
|
||||
@navbar-nav-item-line-margin-vertical: 20px;
|
||||
@navbar-nav-item-line-margin-horizontal: @navbar-nav-item-padding-horizontal;
|
||||
@navbar-nav-item-line-height: 1px;
|
||||
@navbar-nav-item-line-background: currentColor;
|
||||
@navbar-nav-item-line-transition-duration: 0.3s;
|
||||
|
||||
.uk-navbar-dropdown.uk-open {
|
||||
border-radius: @paper-border-radius;
|
||||
|
|
@ -168,7 +175,7 @@
|
|||
|
||||
.uk-card {
|
||||
border-radius: @paper-border-radius;
|
||||
border: 1px solid rgba(180, 180, 180, 0.25);
|
||||
border: 1px solid rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
|
||||
.uk-card-media-top img {
|
||||
|
|
@ -176,14 +183,15 @@
|
|||
}
|
||||
|
||||
.uk-card-default .uk-card-footer {
|
||||
border-top: 1px solid rgba(180, 180, 180, 0.25);
|
||||
border-top: 1px solid rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
|
||||
.uk-card-primary .uk-card-footer {
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.075);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.hook-inverse() {
|
||||
|
||||
// Override background colour in dark mode
|
||||
.uk-card-default {
|
||||
background-color: #2a2a2a !important;
|
||||
|
|
@ -228,16 +236,22 @@
|
|||
/*
|
||||
* Links
|
||||
*/
|
||||
.uk-link, .uk-button-link {
|
||||
.uk-link,
|
||||
.uk-button-link {
|
||||
color: @global-muted-color;
|
||||
}
|
||||
|
||||
.uk-link:hover, .uk-button-link:hover, a:hover {
|
||||
.uk-link:hover,
|
||||
.uk-button-link:hover,
|
||||
a:hover {
|
||||
color: @global-primary-background;
|
||||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.uk-link:hover, .uk-button-link:hover, a:hover {
|
||||
|
||||
.uk-link:hover,
|
||||
.uk-button-link:hover,
|
||||
a:hover {
|
||||
color: @inverse-primary-muted-color;
|
||||
}
|
||||
}
|
||||
|
|
@ -256,7 +270,7 @@
|
|||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.uk-button-primary{
|
||||
.uk-button-primary {
|
||||
background-color: rgba(180, 180, 180, 0.15);
|
||||
color: @inverse-primary-muted-color;
|
||||
border-color: @inverse-primary-muted-color;
|
||||
|
|
@ -268,7 +282,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.uk-icon-button, .uk-icon-button:hover {
|
||||
.uk-icon-button,
|
||||
.uk-icon-button:hover {
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +311,7 @@
|
|||
background-color: #333;
|
||||
}
|
||||
|
||||
.uk-open > .uk-accordion-title::before {
|
||||
.uk-open>.uk-accordion-title::before {
|
||||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
|
||||
mask-position: 100% 50%;
|
||||
background-image: none;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,70 @@
|
|||
<template>
|
||||
<div id="paneCapture">
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Filename</label>
|
||||
<input v-model="filename" class="uk-input uk-width-1-1 uk-form-small" name="inputFilename" placeholder="Leave blank for default">
|
||||
<input
|
||||
v-model="filename"
|
||||
class="uk-input uk-width-1-1 uk-form-small"
|
||||
name="inputFilename"
|
||||
placeholder="Leave blank for default"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p uk-tooltip="title: Capture will be removed automatically; delay: 500"><label><input v-model="temporary" class="uk-checkbox" type="checkbox"> Temporary</label></p>
|
||||
<p uk-tooltip="title: Capture will be removed automatically; delay: 500">
|
||||
<label
|
||||
><input v-model="temporary" class="uk-checkbox" type="checkbox" />
|
||||
Temporary</label
|
||||
>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
<p><label><input v-model="fullResolution" class="uk-checkbox" type="checkbox"> Full resolution</label></p>
|
||||
<p><label><input v-model="storeBayer" class="uk-checkbox" type="checkbox"> Store raw data</label></p>
|
||||
<p>
|
||||
<label
|
||||
><input
|
||||
v-model="fullResolution"
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
/>
|
||||
Full resolution</label
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<label
|
||||
><input v-model="storeBayer" class="uk-checkbox" type="checkbox" />
|
||||
Store raw data</label
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<p><label><input v-model="resizeCapture" class="uk-checkbox" type="checkbox"> Resize capture</label></p>
|
||||
<p>
|
||||
<label
|
||||
><input v-model="resizeCapture" class="uk-checkbox" type="checkbox" />
|
||||
Resize capture</label
|
||||
>
|
||||
</p>
|
||||
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
<div>
|
||||
<input v-bind:class="resizeClass" v-model="resizeDims[0]" class="uk-input uk-form-width-medium uk-form-small" type="number" name="inputResizeW">
|
||||
<input
|
||||
v-model="resizeDims[0]"
|
||||
:class="resizeClass"
|
||||
class="uk-input uk-form-width-medium uk-form-small"
|
||||
type="number"
|
||||
name="inputResizeW"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input v-bind:class="resizeClass" v-model="resizeDims[1]" class="uk-input uk-form-width-medium uk-form-small" type="number" name="inputResizeH">
|
||||
<input
|
||||
v-model="resizeDims[1]"
|
||||
:class="resizeClass"
|
||||
class="uk-input uk-form-width-medium uk-form-small"
|
||||
type="number"
|
||||
name="inputResizeH"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -33,7 +73,12 @@
|
|||
<a class="uk-accordion-title" href="#">Notes</a>
|
||||
<div class="uk-accordion-content">
|
||||
<div class="uk-margin-small">
|
||||
<textarea v-model="captureNotes" class="uk-textarea" rows="5" placeholder="Capture notes"></textarea>
|
||||
<textarea
|
||||
v-model="captureNotes"
|
||||
class="uk-textarea"
|
||||
rows="5"
|
||||
placeholder="Capture notes"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
@ -41,84 +86,129 @@
|
|||
<li>
|
||||
<a class="uk-accordion-title" href="#">Metadata</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<keyvalList v-model="metadata"/>
|
||||
|
||||
<keyvalList v-model="metadata" />
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a class="uk-accordion-title" href="#">Tags</a>
|
||||
<div class="uk-accordion-content">
|
||||
<tagList v-model="tags"/>
|
||||
<tagList v-model="tags" />
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<ul uk-accordion="multiple: true; animation: false">
|
||||
|
||||
<!--Show stack and scan if default plugin is enabled-->
|
||||
<li v-if="this.$store.state.apiState.plugin.includes('default_scan')">
|
||||
<a class="uk-accordion-title" href="#">Stack and Scan</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<div class="uk-margin">
|
||||
<label><input v-model="scanCapture" class="uk-checkbox" type="checkbox"> Scan capture</label>
|
||||
<label
|
||||
><input
|
||||
v-model="scanCapture"
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
/>
|
||||
Scan capture</label
|
||||
>
|
||||
</div>
|
||||
|
||||
<div v-bind:class="{ 'uk-disabled': !scanCapture }" >
|
||||
|
||||
<div :class="{ 'uk-disabled': !scanCapture }">
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x step-size</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>x step-size</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanStepSize.x" class="uk-input uk-form-small" type="number" name="inputPositionX">
|
||||
<input
|
||||
v-model="scanStepSize.x"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionX"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y step-size</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>y step-size</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanStepSize.y" class="uk-input uk-form-small" type="number" name="inputPositionY">
|
||||
<input
|
||||
v-model="scanStepSize.y"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionY"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z step-size</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>z step-size</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanStepSize.z" class="uk-input uk-form-small" type="number" name="inputPositionZx">
|
||||
<input
|
||||
v-model="scanStepSize.z"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionZx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x steps</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>x steps</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanSteps.x" class="uk-input uk-form-small" type="number" name="inputPositionX">
|
||||
<input
|
||||
v-model="scanSteps.x"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionX"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y steps</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>y steps</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanSteps.y" class="uk-input uk-form-small" type="number" name="inputPositionY">
|
||||
<input
|
||||
v-model="scanSteps.y"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionY"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z steps</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>z steps</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="scanSteps.z" class="uk-input uk-form-small" type="number" name="inputPositionZx">
|
||||
<input
|
||||
v-model="scanSteps.z"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionZx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-margin-small uk-margin-remove-bottom">
|
||||
<label class="uk-form-label" for="form-stacked-text">Autofocus</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Autofocus</label
|
||||
>
|
||||
<select v-model="scanDeltaZ" class="uk-select">
|
||||
<option>Off</option>
|
||||
<option>Coarse</option>
|
||||
|
|
@ -129,44 +219,51 @@
|
|||
</div>
|
||||
|
||||
<div class="uk-margin-small uk-margin-remove-bottom">
|
||||
<label class="uk-form-label" for="form-stacked-text">Scan Style</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Scan Style</label
|
||||
>
|
||||
<select v-model="scanStyle" class="uk-select">
|
||||
<option>Raster</option>
|
||||
<option>Snake</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<taskSubmitter v-if="scanCapture"
|
||||
v-bind:submitURL="scanApiUri"
|
||||
v-bind:submitData="scanPayload"
|
||||
v-bind:submitLabel="'Start Scan'"
|
||||
v-on:submit="onScanSubmit"
|
||||
v-on:response="onScanResponse"
|
||||
v-on:error="onScanError">
|
||||
<taskSubmitter
|
||||
v-if="scanCapture"
|
||||
:submit-u-r-l="scanApiUri"
|
||||
:submit-data="scanPayload"
|
||||
:submit-label="'Start Scan'"
|
||||
@submit="onScanSubmit"
|
||||
@response="onScanResponse"
|
||||
@error="onScanError"
|
||||
>
|
||||
</taskSubmitter>
|
||||
|
||||
<button v-else v-on:click="handleCapture()" class="uk-button uk-button-primary uk-form-small uk-margin uk-margin-remove-top uk-float-right uk-width-1-1">Capture</button>
|
||||
|
||||
<button
|
||||
v-else
|
||||
class="uk-button uk-button-primary uk-form-small uk-margin uk-margin-remove-top uk-float-right uk-width-1-1"
|
||||
@click="handleCapture()"
|
||||
>
|
||||
Capture
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
import tagList from "../fieldComponents/tagList"
|
||||
import keyvalList from "../fieldComponents/keyvalList"
|
||||
import tagList from "../fieldComponents/tagList";
|
||||
import keyvalList from "../fieldComponents/keyvalList";
|
||||
|
||||
import taskSubmitter from "../genericComponents/taskSubmitter"
|
||||
import taskSubmitter from "../genericComponents/taskSubmitter";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'paneCapture',
|
||||
name: "PaneCapture",
|
||||
|
||||
components: {
|
||||
tagList,
|
||||
|
|
@ -174,26 +271,25 @@ export default {
|
|||
taskSubmitter
|
||||
},
|
||||
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
filename: '',
|
||||
filename: "",
|
||||
temporary: false,
|
||||
fullResolution: false,
|
||||
storeBayer: false,
|
||||
resizeCapture: false,
|
||||
captureNotes: "",
|
||||
scanCapture: false,
|
||||
scanDeltaZ: 'Medium',
|
||||
scanStyle: 'Raster',
|
||||
scanDeltaZ: "Medium",
|
||||
scanStyle: "Raster",
|
||||
scanStepSize: {
|
||||
x: parseInt(0.8*this.$store.state.apiConfig.fov[0]),
|
||||
y: parseInt(0.8*this.$store.state.apiConfig.fov[1]),
|
||||
x: parseInt(0.8 * this.$store.state.apiConfig.fov[0]),
|
||||
y: parseInt(0.8 * this.$store.state.apiConfig.fov[1]),
|
||||
z: 50
|
||||
},
|
||||
scanSteps: {
|
||||
x: 3,
|
||||
y: 3,
|
||||
x: 3,
|
||||
y: 3,
|
||||
z: 5
|
||||
},
|
||||
resizeDims: [640, 480],
|
||||
|
|
@ -201,73 +297,27 @@ export default {
|
|||
metadata: {
|
||||
Client: `${process.env.PACKAGE.name}.${process.env.PACKAGE.version}`
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
handleCapture: function() {
|
||||
var payload = this.basePayload
|
||||
|
||||
// Do capture
|
||||
this.newCaptureRequest(payload)
|
||||
},
|
||||
|
||||
handleScan: function() {
|
||||
var payload = this.scanPayload
|
||||
|
||||
// Do capture
|
||||
this.newScanRequest(payload)
|
||||
},
|
||||
|
||||
newCaptureRequest: function(params) {
|
||||
// Send move request
|
||||
axios.post(this.captureApiUri, params)
|
||||
.then(response => {
|
||||
// Flash the stream (capture animation)
|
||||
this.$root.$emit('globalFlashStream')
|
||||
// Update the global capture list
|
||||
this.$root.$emit('globalUpdateCaptureList')
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
},
|
||||
|
||||
onScanSubmit: function(submitData) {
|
||||
// We don't need to do anything on this event yet
|
||||
console.log("onScanSubmit event triggered")
|
||||
},
|
||||
|
||||
onScanResponse: function(responseData) {
|
||||
console.log("Scan finished with response data: ", responseData)
|
||||
this.modalNotify("Finished scan.")
|
||||
},
|
||||
|
||||
onScanError: function(error) {
|
||||
this.modalError(error)
|
||||
}
|
||||
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
resizeClass: function () {
|
||||
resizeClass: function() {
|
||||
return {
|
||||
'uk-disabled': !this.resizeCapture
|
||||
}
|
||||
"uk-disabled": !this.resizeCapture
|
||||
};
|
||||
},
|
||||
captureApiUri: function () {
|
||||
return this.$store.getters.uri + "/camera/capture"
|
||||
captureApiUri: function() {
|
||||
return this.$store.getters.uri + "/camera/capture";
|
||||
},
|
||||
scanApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin/default/scan/tile"
|
||||
scanApiUri: function() {
|
||||
return this.$store.getters.uri + "/plugin/default/scan/tile";
|
||||
},
|
||||
basePayload: function () {
|
||||
var payload = {}
|
||||
|
||||
basePayload: function() {
|
||||
var payload = {};
|
||||
|
||||
// Filename
|
||||
if (Boolean(this.filename)) {
|
||||
payload.filename = this.filename
|
||||
if (this.filename) {
|
||||
payload.filename = this.filename;
|
||||
}
|
||||
|
||||
// Basic boolean params
|
||||
|
|
@ -280,28 +330,32 @@ export default {
|
|||
payload.size = {
|
||||
width: this.resizeDims[0],
|
||||
height: this.resizeDims[1]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Additional metadata
|
||||
payload.metadata = this.metadata
|
||||
payload.tags = this.tags
|
||||
payload.metadata = this.metadata;
|
||||
payload.tags = this.tags;
|
||||
|
||||
// Attach notes
|
||||
if (this.captureNotes) {
|
||||
payload.metadata['Notes'] = this.captureNotes
|
||||
payload.metadata["Notes"] = this.captureNotes;
|
||||
}
|
||||
|
||||
return payload
|
||||
return payload;
|
||||
},
|
||||
|
||||
scanPayload: function() {
|
||||
var payload = this.basePayload
|
||||
var payload = this.basePayload;
|
||||
|
||||
// Scan params
|
||||
payload.grid = [this.scanSteps.x, this.scanSteps.y, this.scanSteps.z]
|
||||
payload.step_size = [this.scanStepSize.x, this.scanStepSize.y, this.scanStepSize.z]
|
||||
payload.style = this.scanStyle.toLowerCase()
|
||||
payload.grid = [this.scanSteps.x, this.scanSteps.y, this.scanSteps.z];
|
||||
payload.step_size = [
|
||||
this.scanStepSize.x,
|
||||
this.scanStepSize.y,
|
||||
this.scanStepSize.z
|
||||
];
|
||||
payload.style = this.scanStyle.toLowerCase();
|
||||
|
||||
// Convert AF selector to dz
|
||||
var afDeltas = {
|
||||
|
|
@ -310,17 +364,57 @@ export default {
|
|||
Medium: 30,
|
||||
Fine: 10,
|
||||
Fast: 1500
|
||||
}
|
||||
};
|
||||
|
||||
payload.autofocus_dz = afDeltas[this.scanDeltaZ]
|
||||
payload.fast_autofocus = this.scanDeltaZ == "Fast"
|
||||
payload.autofocus_dz = afDeltas[this.scanDeltaZ];
|
||||
payload.fast_autofocus = this.scanDeltaZ == "Fast";
|
||||
|
||||
return payload
|
||||
return payload;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleCapture: function() {
|
||||
var payload = this.basePayload;
|
||||
|
||||
// Do capture
|
||||
this.newCaptureRequest(payload);
|
||||
},
|
||||
|
||||
}
|
||||
handleScan: function() {
|
||||
var payload = this.scanPayload;
|
||||
|
||||
}
|
||||
// Do capture
|
||||
this.newScanRequest(payload);
|
||||
},
|
||||
|
||||
newCaptureRequest: function(params) {
|
||||
// Send move request
|
||||
axios
|
||||
.post(this.captureApiUri, params)
|
||||
.then(() => {
|
||||
// Flash the stream (capture animation)
|
||||
this.$root.$emit("globalFlashStream");
|
||||
// Update the global capture list
|
||||
this.$root.$emit("globalUpdateCaptureList");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
onScanSubmit: function() {},
|
||||
|
||||
onScanResponse: function(responseData) {
|
||||
console.log("Scan finished with response data: ", responseData);
|
||||
this.modalNotify("Finished scan.");
|
||||
},
|
||||
|
||||
onScanError: function(error) {
|
||||
this.modalError(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
@ -331,5 +425,4 @@ export default {
|
|||
.deletable-label:hover {
|
||||
background-color: #f0506e;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,98 +1,144 @@
|
|||
<template>
|
||||
<div id="paneNavigate">
|
||||
|
||||
<ul uk-accordion="multiple: true; animation: false">
|
||||
<li>
|
||||
<a class="uk-accordion-title" href="#">Configure</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x-y step size</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="stepXy" class="uk-input uk-form-width-medium uk-form-small" type="number" name="inputStepXy">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z step size</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="stepZz" class="uk-input uk-form-width-medium uk-form-small" type="number" name="inputStepZz">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Move-to</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div id="paneNavigate">
|
||||
<ul uk-accordion="multiple: true; animation: false">
|
||||
<li>
|
||||
<a class="uk-accordion-title" href="#">Configure</a>
|
||||
<div class="uk-accordion-content">
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>x-y step size</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="setPosition.x" class="uk-input uk-form-small" type="number" name="inputPositionX">
|
||||
<input
|
||||
v-model="stepXy"
|
||||
class="uk-input uk-form-width-medium uk-form-small"
|
||||
type="number"
|
||||
name="inputStepXy"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>z step size</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="setPosition.y" class="uk-input uk-form-small" type="number" name="inputPositionY">
|
||||
<input
|
||||
v-model="stepZz"
|
||||
class="uk-input uk-form-width-medium uk-form-small"
|
||||
type="number"
|
||||
name="inputStepZz"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Move-to</a>
|
||||
<div class="uk-accordion-content">
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="setPosition.x"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionX"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="setPosition.y"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionY"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="setPosition.z"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
name="inputPositionZx"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<button
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-width-1-1"
|
||||
>
|
||||
Move
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!--Show autofocus if default plugin is enabled-->
|
||||
<li
|
||||
v-if="this.$store.state.apiState.plugin.includes('default_autofocus')"
|
||||
class="uk-open"
|
||||
>
|
||||
<a class="uk-accordion-title" href="#">Autofocus</a>
|
||||
<div class="uk-accordion-content">
|
||||
<div v-if="isAutofocusing">
|
||||
<progressBar />
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="uk-grid-small uk-child-width-1-3"
|
||||
:hidden="isAutofocusing"
|
||||
uk-grid
|
||||
>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="setPosition.z" class="uk-input uk-form-small" type="number" name="inputPositionZx">
|
||||
</div>
|
||||
<button
|
||||
class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1"
|
||||
@click="runFastAutofocus(2000, 300)"
|
||||
>
|
||||
Fast
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1"
|
||||
@click="runAutofocus([-60, -30, 0, 30, 60])"
|
||||
>
|
||||
Medium
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1"
|
||||
@click="runAutofocus([-20, -10, 0, 10, 20])"
|
||||
>
|
||||
Fine
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<button class="uk-button uk-button-primary uk-form-small uk-float-right uk-width-1-1">Move</button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!--Show autofocus if default plugin is enabled-->
|
||||
<li v-if="this.$store.state.apiState.plugin.includes('default_autofocus')" class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Autofocus</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<div v-if="isAutofocusing">
|
||||
<progressBar/>
|
||||
</div>
|
||||
|
||||
<div class="uk-grid-small uk-child-width-1-3" v-bind:hidden="isAutofocusing" uk-grid>
|
||||
<div>
|
||||
<button v-on:click="runFastAutofocus(2000, 300);" class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1">Fast</button>
|
||||
</div>
|
||||
<div>
|
||||
<button v-on:click="runAutofocus([-60,-30,0,30,60]);" class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1">Medium</button>
|
||||
</div>
|
||||
<div>
|
||||
<button v-on:click="runAutofocus([-20,-10,0,10,20]);" class="uk-button uk-button-default uk-form-small uk-float-right uk-width-1-1">Fine</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import progressBar from "../genericComponents/progressBar"
|
||||
import axios from "axios";
|
||||
import progressBar from "../genericComponents/progressBar";
|
||||
|
||||
// Key Codes
|
||||
const keyCodes = {
|
||||
|
|
@ -104,17 +150,17 @@ const keyCodes = {
|
|||
down: 40,
|
||||
enter: 13,
|
||||
esc: 27
|
||||
}
|
||||
};
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'paneNavigate',
|
||||
name: "PaneNavigate",
|
||||
|
||||
components: {
|
||||
progressBar
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
keysDown: {},
|
||||
stepXy: 200,
|
||||
|
|
@ -122,40 +168,57 @@ export default {
|
|||
setPosition: this.$store.state.apiState.stage.position,
|
||||
isAutofocusing: false,
|
||||
moveLock: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
positionApiUri: function() {
|
||||
return this.$store.getters.uri + "/stage/position";
|
||||
},
|
||||
autofocusApiUri: function() {
|
||||
return this.$store.getters.uri + "/plugin/default/autofocus/autofocus";
|
||||
},
|
||||
fastAutofocusApiUri: function() {
|
||||
return (
|
||||
this.$store.getters.uri + "/plugin/default/autofocus/fast_autofocus"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
created: function () {
|
||||
window.addEventListener('keydown', this.keyDownMonitor);
|
||||
created: function() {
|
||||
window.addEventListener("keydown", this.keyDownMonitor);
|
||||
window.addEventListener("keyup", this.keyUpMonitor);
|
||||
window.addEventListener('wheel', this.wheelMonitor);
|
||||
window.addEventListener("wheel", this.wheelMonitor);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// A global signal listener to perform a move action
|
||||
this.$root.$on('globalMoveEvent', (x, y, z, absolute) => {
|
||||
this.moveRequest(x, y, z, absolute)
|
||||
})
|
||||
this.$root.$on("globalMoveEvent", (x, y, z, absolute) => {
|
||||
this.moveRequest(x, y, z, absolute);
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
beforeDestroy() {
|
||||
// Remove global signal listener to perform a move action
|
||||
this.$root.$off('globalMoveEvent')
|
||||
this.$root.$off("globalMoveEvent");
|
||||
},
|
||||
|
||||
destroyed: function () {
|
||||
window.removeEventListener('keydown', this.keyDownMonitor);
|
||||
destroyed: function() {
|
||||
window.removeEventListener("keydown", this.keyDownMonitor);
|
||||
window.removeEventListener("keyup", this.keyUpMonitor);
|
||||
window.removeEventListener('wheel', this.wheelMonitor);
|
||||
window.removeEventListener("wheel", this.wheelMonitor);
|
||||
},
|
||||
|
||||
methods: {
|
||||
// Handle global mouse wheel events to be associated with navigation
|
||||
wheelMonitor: function(event) {
|
||||
// Only capture scroll if the event target's parent contains the "scrollTarget" class
|
||||
if (event.target.parentNode.classList.contains("scrollTarget") || event.target.classList.contains("scrollTarget")) {
|
||||
var z_rel = (event.deltaY)/100 * this.stepZz
|
||||
this.moveRequest(0, 0, z_rel, false)
|
||||
if (
|
||||
event.target.parentNode.classList.contains("scrollTarget") ||
|
||||
event.target.classList.contains("scrollTarget")
|
||||
) {
|
||||
var z_rel = (event.deltaY / 100) * this.stepZz;
|
||||
this.moveRequest(0, 0, z_rel, false);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -164,9 +227,15 @@ export default {
|
|||
this.keysDown[event.keyCode] = true; //Add key to array
|
||||
|
||||
// Convert keyCode dict into a list of key codes
|
||||
var keyCodeList = Object.keys(keyCodes).map(function(key){return keyCodes[key];});
|
||||
var keyCodeList = Object.keys(keyCodes).map(function(key) {
|
||||
return keyCodes[key];
|
||||
});
|
||||
|
||||
if (!(event.target instanceof HTMLInputElement) && !(event.target.classList.contains('lightbox-link')) && keyCodeList.includes(event.keyCode)) {
|
||||
if (
|
||||
!(event.target instanceof HTMLInputElement) &&
|
||||
!event.target.classList.contains("lightbox-link") &&
|
||||
keyCodeList.includes(event.keyCode)
|
||||
) {
|
||||
//console.log(this.keysDown)
|
||||
// Calculate movement array
|
||||
var x_rel = 0;
|
||||
|
|
@ -192,7 +261,7 @@ export default {
|
|||
}
|
||||
|
||||
// Make a position request
|
||||
this.moveRequest(x_rel, y_rel, z_rel, false)
|
||||
this.moveRequest(x_rel, y_rel, z_rel, false);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -200,105 +269,102 @@ export default {
|
|||
delete this.keysDown[event.keyCode]; //Remove key from array
|
||||
},
|
||||
|
||||
handleSubmit: function(event) {
|
||||
handleSubmit: function() {
|
||||
this.moveRequest(
|
||||
this.setPosition.x,
|
||||
this.setPosition.y,
|
||||
this.setPosition.z,
|
||||
true,
|
||||
)
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
moveRequest: function(x, y, z, absolute) {
|
||||
console.log(`Sending move request of ${x}, ${y}, ${z}`)
|
||||
console.log(`Sending move request of ${x}, ${y}, ${z}`);
|
||||
// If not movement-locked
|
||||
if (!this.moveLock) {
|
||||
// Lock move requests
|
||||
this.moveLock = true
|
||||
this.moveLock = true;
|
||||
|
||||
// Send move request
|
||||
axios.post(this.positionApiUri, {
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
absolute: absolute
|
||||
})
|
||||
.then(response => {
|
||||
this.$store.dispatch('updateState'); // Update store state
|
||||
this.setPosition = response.data.stage.position; // Update boxes from response
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
.then(() => {
|
||||
this.moveLock = false // Release the move lock
|
||||
})
|
||||
axios
|
||||
.post(this.positionApiUri, {
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
absolute: absolute
|
||||
})
|
||||
.then(response => {
|
||||
this.$store.dispatch("updateState"); // Update store state
|
||||
this.setPosition = response.data.stage.position; // Update boxes from response
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
})
|
||||
.then(() => {
|
||||
this.moveLock = false; // Release the move lock
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
runAutofocus: function(dz) {
|
||||
if (!this.moveLock) {
|
||||
// Lock move requests
|
||||
this.moveLock = true
|
||||
this.isAutofocusing = true
|
||||
axios.post(this.autofocusApiUri, {dz: dz})
|
||||
.then(response => {
|
||||
console.log("Autofocus Task ID: " + response.data.id)
|
||||
// Start the store polling TaskId for success
|
||||
return this.$store.dispatch('pollTask', [response.data.id, null, null])
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Successfully finished autofocus")
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after autofocus.")
|
||||
this.isAutofocusing = false;
|
||||
this.moveLock = false // Release the move lock
|
||||
})
|
||||
this.moveLock = true;
|
||||
this.isAutofocusing = true;
|
||||
axios
|
||||
.post(this.autofocusApiUri, { dz: dz })
|
||||
.then(response => {
|
||||
console.log("Autofocus Task ID: " + response.data.id);
|
||||
// Start the store polling TaskId for success
|
||||
return this.$store.dispatch("pollTask", [
|
||||
response.data.id,
|
||||
null,
|
||||
null
|
||||
]);
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Successfully finished autofocus");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after autofocus.");
|
||||
this.isAutofocusing = false;
|
||||
this.moveLock = false; // Release the move lock
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
runFastAutofocus: function(dz, backlash) {
|
||||
if (!this.moveLock) {
|
||||
// Lock move requests
|
||||
this.moveLock = true
|
||||
this.isAutofocusing = true
|
||||
axios.post(this.fastAutofocusApiUri, {dz: dz, backlash: backlash})
|
||||
.then(response => {
|
||||
console.log("Autofocus Task ID: " + response.data.id)
|
||||
// Start the store polling TaskId for success
|
||||
return this.$store.dispatch('pollTask', [response.data.id, null, null])
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Successfully finished autofocus")
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after autofocus.")
|
||||
this.isAutofocusing = false
|
||||
this.moveLock = false // Release the move lock
|
||||
})
|
||||
this.moveLock = true;
|
||||
this.isAutofocusing = true;
|
||||
axios
|
||||
.post(this.fastAutofocusApiUri, { dz: dz, backlash: backlash })
|
||||
.then(response => {
|
||||
console.log("Autofocus Task ID: " + response.data.id);
|
||||
// Start the store polling TaskId for success
|
||||
return this.$store.dispatch("pollTask", [
|
||||
response.data.id,
|
||||
null,
|
||||
null
|
||||
]);
|
||||
})
|
||||
.then(() => {
|
||||
console.log("Successfully finished autofocus");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after autofocus.");
|
||||
this.isAutofocusing = false;
|
||||
this.moveLock = false; // Release the move lock
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
positionApiUri: function () {
|
||||
return this.$store.getters.uri + "/stage/position"
|
||||
},
|
||||
autofocusApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin/default/autofocus/autofocus"
|
||||
},
|
||||
fastAutofocusApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin/default/autofocus/fast_autofocus"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<div id="panePlugins">
|
||||
<h3>Plugins</h3>
|
||||
<div class="uk-placeholder uk-text-center">Plugin support coming soon...</div>
|
||||
<div class="uk-placeholder uk-text-center">
|
||||
Plugin support coming soon...
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'panePlugins',
|
||||
}
|
||||
name: "PanePlugins"
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
<style lang="less"></style>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,35 @@
|
|||
<template>
|
||||
<div id="paneSettings">
|
||||
|
||||
<appSettings/>
|
||||
<appSettings />
|
||||
|
||||
<ul uk-accordion="multiple: true; animation: false">
|
||||
<li>
|
||||
<a class="uk-accordion-title" href="#">Stream settings</a>
|
||||
<div class="uk-accordion-content"><streamSettings/></div>
|
||||
<div class="uk-accordion-content"><streamSettings /></div>
|
||||
</li>
|
||||
|
||||
<li v-if="$store.getters.ready">
|
||||
<a class="uk-accordion-title" href="#">Camera settings</a>
|
||||
<div class="uk-accordion-content"><cameraSettings/></div>
|
||||
<div class="uk-accordion-content"><cameraSettings /></div>
|
||||
</li>
|
||||
|
||||
|
||||
<li v-if="$store.getters.ready">
|
||||
<a class="uk-accordion-title" href="#">Microscope settings</a>
|
||||
<div class="uk-accordion-content"><microscopeSettings/></div>
|
||||
<div class="uk-accordion-content"><microscopeSettings /></div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import streamSettings from './settingsComponents/streamSettings.vue'
|
||||
import microscopeSettings from './settingsComponents/microscopeSettings.vue'
|
||||
import cameraSettings from './settingsComponents/cameraSettings.vue'
|
||||
import appSettings from './settingsComponents/appSettings.vue'
|
||||
import streamSettings from "./settingsComponents/streamSettings.vue";
|
||||
import microscopeSettings from "./settingsComponents/microscopeSettings.vue";
|
||||
import cameraSettings from "./settingsComponents/cameraSettings.vue";
|
||||
import appSettings from "./settingsComponents/appSettings.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'paneSettings',
|
||||
name: "PaneSettings",
|
||||
|
||||
components: {
|
||||
streamSettings,
|
||||
|
|
@ -40,9 +37,7 @@ export default {
|
|||
microscopeSettings,
|
||||
appSettings
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
<style lang="less"></style>
|
||||
|
|
|
|||
|
|
@ -1,70 +1,71 @@
|
|||
<template>
|
||||
<div class="host-input">
|
||||
|
||||
<div v-if="$store.getters.ready">
|
||||
<div v-if="$store.state.apiConfig.name"><b>Device name:</b> <br> {{ $store.state.apiConfig.name }}</div>
|
||||
<hr>
|
||||
<div class="uk-margin-small-bottom">
|
||||
<b>Host:</b>
|
||||
<br>
|
||||
{{ $store.state.host }}
|
||||
<div class="host-input">
|
||||
<div v-if="$store.getters.ready">
|
||||
<div v-if="$store.state.apiConfig.name">
|
||||
<b>Device name:</b> <br />
|
||||
{{ $store.state.apiConfig.name }}
|
||||
</div>
|
||||
<hr />
|
||||
<div class="uk-margin-small-bottom">
|
||||
<b>Host:</b>
|
||||
<br />
|
||||
{{ $store.state.host }}
|
||||
</div>
|
||||
<div>
|
||||
<b>Server version:</b> <br />
|
||||
{{ $store.state.apiState.version }}
|
||||
</div>
|
||||
<hr />
|
||||
<div class="uk-margin-small-bottom">
|
||||
<b>Camera:</b>
|
||||
<br />
|
||||
<div v-if="$store.state.apiState.camera.board">
|
||||
{{ $store.state.apiState.camera.board }}
|
||||
</div>
|
||||
<div v-else class="uk-text-danger"><b>No camera connected</b></div>
|
||||
</div>
|
||||
<div>
|
||||
<b>Stage:</b>
|
||||
<br />
|
||||
<div v-if="$store.state.apiState.stage.board">
|
||||
{{ $store.state.apiState.stage.board }}
|
||||
</div>
|
||||
<div v-else class="uk-text-danger"><b>No stage connected</b></div>
|
||||
</div>
|
||||
</div>
|
||||
<div><b>Server version:</b> <br> {{ $store.state.apiState.version }}</div>
|
||||
<hr>
|
||||
<div class="uk-margin-small-bottom">
|
||||
<b>Camera:</b>
|
||||
<br>
|
||||
<div v-if="$store.state.apiState.camera.board">{{ $store.state.apiState.camera.board }}</div>
|
||||
<div v-else class="uk-text-danger"><b>No camera connected</b></div>
|
||||
<div v-else-if="$store.state.waiting">
|
||||
<progressBar></progressBar>
|
||||
</div>
|
||||
<div>
|
||||
<b>Stage:</b>
|
||||
<br>
|
||||
<div v-if="$store.state.apiState.stage.board">{{ $store.state.apiState.stage.board }}</div>
|
||||
<div v-else class="uk-text-danger"><b>No stage connected</b></div>
|
||||
<div v-else-if="$store.state.error">
|
||||
<b>Error:</b> {{ $store.state.error }}
|
||||
</div>
|
||||
|
||||
<div v-else>No active connection</div>
|
||||
</div>
|
||||
<div v-else-if="$store.state.waiting">
|
||||
<progressBar></progressBar>
|
||||
</div>
|
||||
<div v-else-if="$store.state.error"><b>Error:</b> {{ $store.state.error }}</div>
|
||||
<div v-else>No active connection</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import progressBar from "../genericComponents/progressBar"
|
||||
|
||||
import progressBar from "../genericComponents/progressBar";
|
||||
|
||||
export default {
|
||||
name: 'paneStatus',
|
||||
name: "PaneStatus",
|
||||
|
||||
components: {
|
||||
progressBar
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
}
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
},
|
||||
computed: {},
|
||||
|
||||
watch: {
|
||||
},
|
||||
watch: {},
|
||||
|
||||
methods: {
|
||||
},
|
||||
mounted() {},
|
||||
|
||||
computed: {
|
||||
}
|
||||
|
||||
}
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="less">
|
||||
</style>
|
||||
<style scoped lang="less"></style>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,21 @@
|
|||
<template>
|
||||
<div id="appSettings">
|
||||
|
||||
<p><label><input v-model="darkMode" class="uk-checkbox" type="checkbox"> Enable dark theme</label></p>
|
||||
|
||||
</div>
|
||||
<div id="appSettings">
|
||||
<p>
|
||||
<label
|
||||
><input v-model="darkMode" class="uk-checkbox" type="checkbox" /> Enable
|
||||
dark theme</label
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'appSettings',
|
||||
name: "AppSettings",
|
||||
|
||||
data: function () {
|
||||
return {}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Try loading settings from localStorage. If null, don't change.
|
||||
this.darkMode = this.getLocalStorageObj('darkMode') || this.darkMode
|
||||
},
|
||||
|
||||
watch: {
|
||||
darkMode(newdarkMode) {
|
||||
console.log("Saving darkmode setting")
|
||||
this.setLocalStorageObj('darkMode', this.darkMode)
|
||||
}
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -34,13 +24,23 @@ export default {
|
|||
return this.$store.state.globalSettings.darkMode;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("changeSetting", ['darkMode', value]);
|
||||
this.$store.commit("changeSetting", ["darkMode", value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
watch: {
|
||||
darkMode() {
|
||||
console.log("Saving darkmode setting");
|
||||
this.setLocalStorageObj("darkMode", this.darkMode);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Try loading settings from localStorage. If null, don't change.
|
||||
this.darkMode = this.getLocalStorageObj("darkMode") || this.darkMode;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
<style lang="less"></style>
|
||||
|
|
|
|||
|
|
@ -1,138 +1,181 @@
|
|||
<template>
|
||||
<div id="cameraSettings">
|
||||
<form @submit.prevent="applyConfigRequest">
|
||||
<div id="cameraSettings">
|
||||
<form @submit.prevent="applyConfigRequest">
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Exposure time</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Exposure time</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-bind:value="displayShutterSpeed" v-on:input="shutterSpeed = $event.target.value" class="uk-input uk-form-small" type="number">
|
||||
<input
|
||||
:value="displayShutterSpeed"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
@input="shutterSpeed = $event.target.value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Analogue gain</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Analogue gain</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-bind:value="displayAnalogGain" v-on:input="analogGain = $event.target.value" class="uk-input uk-form-small" type="number" step="0.1">
|
||||
<input
|
||||
:value="displayAnalogGain"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
step="0.1"
|
||||
@input="analogGain = $event.target.value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Digital gain</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Digital gain</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-bind:value="displayDigitalGain" v-on:input="digitalGain = $event.target.value" class="uk-input uk-form-small" type="number" step="0.1">
|
||||
<input
|
||||
:value="displayDigitalGain"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
step="0.1"
|
||||
@input="digitalGain = $event.target.value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1">Apply Settings</button>
|
||||
|
||||
<!--Show auto calibrate if default plugin is enabled-->
|
||||
<div v-if="this.$store.state.apiState.plugin.includes('default_camera_calibration')">
|
||||
<taskSubmitter
|
||||
v-bind:canTerminate="false"
|
||||
v-bind:requiresConfirmation="true"
|
||||
v-bind:confirmationMessage="'Start recalibration? This may take a while, and the microscope will be locked during this time.'"
|
||||
v-bind:submitURL="recalibrateApiUri"
|
||||
v-bind:submitLabel="'Auto-Calibrate (Task)'"
|
||||
v-on:response="onRecalibrateResponse"
|
||||
v-on:error="onRecalibrateError">
|
||||
</taskSubmitter>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1"
|
||||
>
|
||||
Apply Settings
|
||||
</button>
|
||||
|
||||
<!--Show auto calibrate if default plugin is enabled-->
|
||||
<div
|
||||
v-if="
|
||||
this.$store.state.apiState.plugin.includes(
|
||||
'default_camera_calibration'
|
||||
)
|
||||
"
|
||||
>
|
||||
<taskSubmitter
|
||||
:can-terminate="false"
|
||||
:requires-confirmation="true"
|
||||
:confirmation-message="
|
||||
'Start recalibration? This may take a while, and the microscope will be locked during this time.'
|
||||
"
|
||||
:submit-u-r-l="recalibrateApiUri"
|
||||
:submit-label="'Auto-Calibrate (Task)'"
|
||||
@response="onRecalibrateResponse"
|
||||
@error="onRecalibrateError"
|
||||
>
|
||||
</taskSubmitter>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import taskSubmitter from "../../genericComponents/taskSubmitter"
|
||||
import axios from "axios";
|
||||
import taskSubmitter from "../../genericComponents/taskSubmitter";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'microscopeSettings',
|
||||
name: "MicroscopeSettings",
|
||||
|
||||
components: {
|
||||
taskSubmitter
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
shutterSpeed: this.$store.state.apiConfig.camera_settings.picamera_settings.shutter_speed,
|
||||
analogGain: this.$store.state.apiConfig.camera_settings.picamera_settings.analog_gain,
|
||||
digitalGain: this.$store.state.apiConfig.camera_settings.picamera_settings.digital_gain,
|
||||
shutterSpeed: this.$store.state.apiConfig.camera_settings
|
||||
.picamera_settings.shutter_speed,
|
||||
analogGain: this.$store.state.apiConfig.camera_settings.picamera_settings
|
||||
.analog_gain,
|
||||
digitalGain: this.$store.state.apiConfig.camera_settings.picamera_settings
|
||||
.digital_gain,
|
||||
isCalibrating: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
displayDigitalGain: function() {
|
||||
return Number(this.digitalGain).toFixed(2);
|
||||
},
|
||||
displayAnalogGain: function() {
|
||||
return Number(this.analogGain).toFixed(2);
|
||||
},
|
||||
displayShutterSpeed: function() {
|
||||
return this.shutterSpeed != "0" ? this.shutterSpeed : "auto";
|
||||
},
|
||||
recalibrateApiUri: function() {
|
||||
return (
|
||||
this.$store.getters.uri +
|
||||
"/plugin/default/camera_calibration/recalibrate"
|
||||
);
|
||||
},
|
||||
configApiUri: function() {
|
||||
return this.$store.getters.uri + "/config";
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateInputValues: function () {
|
||||
this.shutterSpeed = this.$store.state.apiConfig.camera_settings.picamera_settings.shutter_speed
|
||||
this.digitalGain = this.$store.state.apiConfig.camera_settings.picamera_settings.digital_gain
|
||||
this.analogGain = this.$store.state.apiConfig.camera_settings.picamera_settings.analog_gain
|
||||
updateInputValues: function() {
|
||||
this.shutterSpeed = this.$store.state.apiConfig.camera_settings.picamera_settings.shutter_speed;
|
||||
this.digitalGain = this.$store.state.apiConfig.camera_settings.picamera_settings.digital_gain;
|
||||
this.analogGain = this.$store.state.apiConfig.camera_settings.picamera_settings.analog_gain;
|
||||
},
|
||||
|
||||
applyConfigRequest: function() {
|
||||
console.log("Applying config to the microscope")
|
||||
console.log("Applying config to the microscope");
|
||||
var payload = {
|
||||
camera_settings: {
|
||||
picamera_settings: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//if (this.shutterSpeed != this.$store.state.apiConfig.picamera_settings.shutter_speed) {
|
||||
payload.camera_settings.picamera_settings.shutter_speed = this.shutterSpeed
|
||||
payload.camera_settings.picamera_settings.analog_gain = this.analogGain
|
||||
payload.camera_settings.picamera_settings.digital_gain = this.digitalGain
|
||||
payload.camera_settings.picamera_settings.shutter_speed = this.shutterSpeed;
|
||||
payload.camera_settings.picamera_settings.analog_gain = this.analogGain;
|
||||
payload.camera_settings.picamera_settings.digital_gain = this.digitalGain;
|
||||
//};
|
||||
|
||||
// Send request
|
||||
axios.post(this.configApiUri, payload)
|
||||
.then(response => { return new Promise(r => setTimeout(r, 500))}) // why is there no built-in for this??!
|
||||
.then(response => {
|
||||
return this.$store.dispatch('updateConfig');
|
||||
axios
|
||||
.post(this.configApiUri, payload)
|
||||
.then(() => {
|
||||
return new Promise(r => setTimeout(r, 500));
|
||||
}) // why is there no built-in for this??!
|
||||
.then(() => {
|
||||
return this.$store.dispatch("updateConfig");
|
||||
})
|
||||
.then(this.updateInputValues)
|
||||
.then(r=>{console.log("Updated Config: ", payload)})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
.then(() => {
|
||||
console.log("Updated Config: ", payload);
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
onRecalibrateResponse: function() {
|
||||
this.modalNotify("Finished recalibration.")
|
||||
return new Promise(r => setTimeout(r, 500)) // wait 500ms before updating config, so it's fresh
|
||||
this.modalNotify("Finished recalibration.");
|
||||
return new Promise(r => setTimeout(r, 500)); // wait 500ms before updating config, so it's fresh
|
||||
},
|
||||
|
||||
onRecalibrateError: function(error) {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
displayDigitalGain: function () {
|
||||
return Number(this.digitalGain).toFixed(2)
|
||||
},
|
||||
displayAnalogGain: function () {
|
||||
return Number(this.analogGain).toFixed(2)
|
||||
},
|
||||
displayShutterSpeed: function () {
|
||||
return (this.shutterSpeed != "0") ? this.shutterSpeed : "auto"
|
||||
},
|
||||
recalibrateApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin/default/camera_calibration/recalibrate"
|
||||
},
|
||||
configApiUri: function () {
|
||||
return this.$store.getters.uri + "/config"
|
||||
this.modalError(error); // Let mixin handle error
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.center-spinner {
|
||||
margin-left: auto;
|
||||
margin-right: auto
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,108 +1,133 @@
|
|||
<template>
|
||||
<div id="microscopeSettings">
|
||||
<form @submit.prevent="applyConfigRequest">
|
||||
<h4>Stage</h4>
|
||||
<div id="microscopeSettings">
|
||||
<form @submit.prevent="applyConfigRequest">
|
||||
<h4>Stage</h4>
|
||||
|
||||
<label class="uk-form-label" for="form-stacked-text">Backlash compensation</label>
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="stageBacklash.x" class="uk-input uk-form-small" type="number">
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Backlash compensation</label
|
||||
>
|
||||
<div class="uk-grid-small uk-child-width-1-3" uk-grid>
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">x</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="stageBacklash.x"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="stageBacklash.y"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
v-model="stageBacklash.z"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">y</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="stageBacklash.y" class="uk-input uk-form-small" type="number">
|
||||
</div>
|
||||
</div>
|
||||
<h4>Microscope</h4>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">z</label>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="stageBacklash.z" class="uk-input uk-form-small" type="number">
|
||||
</div>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Microscope name</label
|
||||
>
|
||||
<input
|
||||
v-model="microscopeName"
|
||||
class="uk-input uk-width-1-1 uk-form-small"
|
||||
name="inputFilename"
|
||||
placeholder="Leave blank for default"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>Microscope</h4>
|
||||
|
||||
<div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Microscope name</label>
|
||||
<input v-model="microscopeName" class="uk-input uk-width-1-1 uk-form-small" name="inputFilename" placeholder="Leave blank for default">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1">Apply Settings</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1"
|
||||
>
|
||||
Apply Settings
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'microscopeSettings',
|
||||
name: "MicroscopeSettings",
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
microscopeName: this.$store.state.apiConfig.name,
|
||||
stageBacklash: this.$store.state.apiConfig.stage_settings.backlash
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
configApiUri: function() {
|
||||
return this.$store.getters.uri + "/config";
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateInputValues: function () {
|
||||
updateInputValues: function() {
|
||||
this.microscopeName = this.$store.state.apiConfig.name;
|
||||
this.stageBacklash = this.$store.state.apiConfig.stage_settings.backlash
|
||||
this.stageBacklash = this.$store.state.apiConfig.stage_settings.backlash;
|
||||
},
|
||||
|
||||
applyConfigRequest: function() {
|
||||
var payload = {
|
||||
stage_settings: {}
|
||||
}
|
||||
|
||||
if (this.microscopeName != this.$store.state.apiConfig.name) {
|
||||
payload.name = this.microscopeName
|
||||
};
|
||||
|
||||
if (this.stageBacklash != this.$store.state.apiConfig.stage_settings.backlash) {
|
||||
payload.stage_settings.backlash = this.stageBacklash
|
||||
if (this.microscopeName != this.$store.state.apiConfig.name) {
|
||||
payload.name = this.microscopeName;
|
||||
}
|
||||
|
||||
console.log(payload)
|
||||
if (
|
||||
this.stageBacklash !=
|
||||
this.$store.state.apiConfig.stage_settings.backlash
|
||||
) {
|
||||
payload.stage_settings.backlash = this.stageBacklash;
|
||||
}
|
||||
|
||||
console.log(payload);
|
||||
|
||||
// Send request to update config
|
||||
axios.post(this.configApiUri, payload)
|
||||
.then(response => {
|
||||
this.$store.dispatch('updateConfig');
|
||||
this.updateInputValues
|
||||
this.modalNotify("Microscope config applied.")
|
||||
axios
|
||||
.post(this.configApiUri, payload)
|
||||
.then(() => {
|
||||
this.$store.dispatch("updateConfig");
|
||||
this.updateInputValues;
|
||||
this.modalNotify("Microscope config applied.");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
configApiUri: function () {
|
||||
return this.$store.getters.uri + "/config"
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.center-spinner {
|
||||
margin-left: auto;
|
||||
margin-right: auto
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,34 +1,49 @@
|
|||
<template>
|
||||
<div id="streamSettings">
|
||||
<div id="streamSettings">
|
||||
<p>
|
||||
<label
|
||||
><input v-model="disableStream" class="uk-checkbox" type="checkbox" />
|
||||
Disable live stream</label
|
||||
>
|
||||
</p>
|
||||
|
||||
<p><label><input v-model="disableStream" class="uk-checkbox" type="checkbox"> Disable live stream</label></p>
|
||||
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
<p><label v-bind:class="[{'uk-disabled': !this.$store.getters.ready}]"><input v-model="autoGpuPreview" class="uk-checkbox" type="checkbox"> GPU preview</label></p>
|
||||
<p><label v-bind:class="[{'uk-disabled': !this.$store.getters.ready}]"><input v-model="trackWindow" class="uk-checkbox" type="checkbox"> Track window</label></p>
|
||||
<div class="uk-child-width-1-2" uk-grid>
|
||||
<p>
|
||||
<label :class="[{ 'uk-disabled': !this.$store.getters.ready }]"
|
||||
><input
|
||||
v-model="autoGpuPreview"
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
/>
|
||||
GPU preview</label
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
<label :class="[{ 'uk-disabled': !this.$store.getters.ready }]"
|
||||
><input v-model="trackWindow" class="uk-checkbox" type="checkbox" />
|
||||
Track window</label
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'streamSettings',
|
||||
name: "StreamSettings",
|
||||
|
||||
data: function () {
|
||||
return {}
|
||||
data: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
disableStream: {
|
||||
get() {
|
||||
return this.$store.state.globalSettings.disableStream;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("changeSetting", ['disableStream', value]);
|
||||
this.$store.commit("changeSetting", ["disableStream", value]);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -37,8 +52,8 @@ export default {
|
|||
return this.$store.state.globalSettings.autoGpuPreview;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("changeSetting", ['autoGpuPreview', value]);
|
||||
this.$root.$emit('globalTogglePreview', value)
|
||||
this.$store.commit("changeSetting", ["autoGpuPreview", value]);
|
||||
this.$root.$emit("globalTogglePreview", value);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -47,13 +62,11 @@ export default {
|
|||
return this.$store.state.globalSettings.trackWindow;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit("changeSetting", ['trackWindow', value]);
|
||||
this.$store.commit("changeSetting", ["trackWindow", value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
</style>
|
||||
<style lang="less"></style>
|
||||
|
|
|
|||
|
|
@ -1,52 +1,66 @@
|
|||
<template>
|
||||
<div>
|
||||
<label>{{label}}</label>
|
||||
<label>{{ label }}</label>
|
||||
|
||||
<div class="uk-form-controls">
|
||||
|
||||
<div v-for="option in options" :key="option">
|
||||
<label>
|
||||
<input class="uk-checkbox" type="checkbox" v-bind:value="option" v-bind:checked="(value && value.includes(option))" @change="updateValue($event.target)">
|
||||
<input
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
:value="option"
|
||||
:checked="value && value.includes(option)"
|
||||
@change="updateValue($event.target)"
|
||||
/>
|
||||
{{ option }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'checkList',
|
||||
name: "CheckList",
|
||||
|
||||
props: [
|
||||
'options',
|
||||
'name',
|
||||
'label',
|
||||
'value'
|
||||
],
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateValue(target) {
|
||||
var newSelected = this.value != null ? [...this.value] : [] // Clone value array
|
||||
var newSelected = this.value != null ? [...this.value] : []; // Clone value array
|
||||
|
||||
if (target.checked) {
|
||||
if (!newSelected.includes(target.value)) {
|
||||
newSelected.push(target.value)
|
||||
newSelected.push(target.value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (newSelected.includes(target.value)) {
|
||||
var newSelected = newSelected.filter(function(value, index, arr){
|
||||
return value != target.value;
|
||||
})
|
||||
newSelected = newSelected.filter(function(value) {
|
||||
return value != target.value;
|
||||
});
|
||||
}
|
||||
}
|
||||
this.$emit('input', newSelected)
|
||||
this.$emit("input", newSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,23 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
name: 'htmlBlock',
|
||||
name: "HtmlBlock",
|
||||
|
||||
props: [
|
||||
'label',
|
||||
'name',
|
||||
'content'
|
||||
]
|
||||
}
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -2,83 +2,117 @@
|
|||
<div>
|
||||
<form @submit.prevent="handleMetadataSubmit">
|
||||
<div class="uk-margin-remove uk-flex uk-flex-middle">
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-grid-small uk-width-expand" uk-grid>
|
||||
<div class="uk-margin-remove uk-width-1-2"><input v-model="newMetadata.key" class="uk-input uk-form-width-small uk-form-small" type="text" name="flavor" placeholder="Key"></div>
|
||||
<div class="uk-margin-remove uk-width-1-2"><input v-model="newMetadata.value" class="uk-input uk-form-width-small uk-form-small" type="text" name="flavor" placeholder="Value"></div>
|
||||
<div
|
||||
class="uk-margin-remove-top uk-padding-remove uk-grid-small uk-width-expand"
|
||||
uk-grid
|
||||
>
|
||||
<div class="uk-margin-remove uk-width-1-2">
|
||||
<input
|
||||
v-model="newMetadata.key"
|
||||
class="uk-input uk-form-width-small uk-form-small"
|
||||
type="text"
|
||||
name="flavor"
|
||||
placeholder="Key"
|
||||
/>
|
||||
</div>
|
||||
<div class="uk-margin-remove uk-width-1-2">
|
||||
<input
|
||||
v-model="newMetadata.value"
|
||||
class="uk-input uk-form-width-small uk-form-small"
|
||||
type="text"
|
||||
name="flavor"
|
||||
placeholder="Value"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" v-on:click="handleMetadataSubmit()" class="uk-icon uk-margin-left"><i class="material-icons">add_circle</i></a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
class="uk-icon uk-margin-left"
|
||||
@click="handleMetadataSubmit()"
|
||||
><i class="material-icons">add_circle</i></a
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div v-for="(val, key) in value" :key="key" class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-flex uk-flex-middle">
|
||||
<div
|
||||
v-for="(val, key) in value"
|
||||
:key="key"
|
||||
class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-flex uk-flex-middle"
|
||||
>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-expand">
|
||||
<labelInput :label="key" :value="value[key]" @input="value[key]=$event"/>
|
||||
<labelInput
|
||||
:label="key"
|
||||
:value="value[key]"
|
||||
@input="value[key] = $event"
|
||||
/>
|
||||
</div>
|
||||
<a href="#" v-on:click="delMetadataKey(key)" class="uk-icon uk-width-auto"><i class="material-icons">delete</i></a>
|
||||
<a href="#" class="uk-icon uk-width-auto" @click="delMetadataKey(key)"
|
||||
><i class="material-icons">delete</i></a
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import labelInput from "../fieldComponents/labelInput"
|
||||
import labelInput from "../fieldComponents/labelInput";
|
||||
|
||||
export default {
|
||||
name: 'keyvalList',
|
||||
name: "KeyvalList",
|
||||
|
||||
components: {
|
||||
labelInput
|
||||
},
|
||||
|
||||
data: function () {
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
newMetadata: {
|
||||
key: "",
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
props: [
|
||||
'value'
|
||||
],
|
||||
|
||||
methods: {
|
||||
handleMetadataSubmit: function () {
|
||||
var newSelected = {}
|
||||
handleMetadataSubmit: function() {
|
||||
var newSelected = {};
|
||||
|
||||
if (this.value != null) {
|
||||
Object.assign(newSelected, this.value)
|
||||
Object.assign(newSelected, this.value);
|
||||
}
|
||||
|
||||
newSelected[this.newMetadata.key] = this.newMetadata.value
|
||||
newSelected[this.newMetadata.key] = this.newMetadata.value;
|
||||
this.newMetadata.key = "";
|
||||
this.newMetadata.value = "";
|
||||
|
||||
this.$emit('input', newSelected)
|
||||
this.$emit("input", newSelected);
|
||||
},
|
||||
|
||||
delMetadataKey: function (key) {
|
||||
var newSelected = {}
|
||||
delMetadataKey: function(key) {
|
||||
var newSelected = {};
|
||||
|
||||
if (this.value != null) {
|
||||
Object.assign(newSelected, this.value)
|
||||
Object.assign(newSelected, this.value);
|
||||
}
|
||||
|
||||
this.$delete(newSelected, key)
|
||||
this.$delete(newSelected, key);
|
||||
|
||||
this.$emit('input', newSelected)
|
||||
this.$emit("input", newSelected);
|
||||
},
|
||||
|
||||
modifyValue: function (e, v) {
|
||||
console.log(e)
|
||||
console.log(v)
|
||||
modifyValue: function(e, v) {
|
||||
console.log(e);
|
||||
console.log(v);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,58 +1,65 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="uk-form-label uk-text-bold">{{label}}</label>
|
||||
|
||||
<div @click="setEditing(true)" uk-tooltip="title: Click to edit value; delay: 250">
|
||||
<label class="uk-form-label uk-text-bold">{{ label }}</label>
|
||||
|
||||
<div
|
||||
uk-tooltip="title: Click to edit value; delay: 250"
|
||||
@click="setEditing(true)"
|
||||
>
|
||||
<div v-show="editing == false">
|
||||
<label> {{value}} </label>
|
||||
<label> {{ value }} </label>
|
||||
</div>
|
||||
|
||||
<input
|
||||
v-show="editing == true"
|
||||
ref="textinput"
|
||||
class="uk-input uk-form-small"
|
||||
type="text"
|
||||
v-bind:name="name"
|
||||
v-bind:value="value"
|
||||
ref="textinput"
|
||||
v-on:blur= "setEditing(false)"
|
||||
@keyup.enter = "setEditing(false)"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
:name="name"
|
||||
:value="value"
|
||||
autofocus
|
||||
>
|
||||
@blur="setEditing(false)"
|
||||
@keyup.enter="setEditing(false)"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'labelInput',
|
||||
name: "LabelInput",
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
editing: false
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
props: [
|
||||
'name',
|
||||
'label',
|
||||
'value'
|
||||
],
|
||||
data: function() {
|
||||
return {
|
||||
editing: false
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
setEditing(editing) {
|
||||
this.editing = editing
|
||||
this.editing = editing;
|
||||
if (editing == true) {
|
||||
this.$nextTick(() => this.$refs.textinput.focus())
|
||||
this.$nextTick(() => this.$refs.textinput.focus());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,41 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="uk-form-label">{{label}}</label>
|
||||
<label class="uk-form-label">{{ label }}</label>
|
||||
|
||||
<input
|
||||
<input
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
:name="name"
|
||||
:value="value"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
:placeholder="placeholder"
|
||||
>
|
||||
|
||||
@input="$emit('input', $event.target.value)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'numberInput',
|
||||
|
||||
props: [
|
||||
'placeholder',
|
||||
'label',
|
||||
'name',
|
||||
'value'
|
||||
]
|
||||
|
||||
}
|
||||
name: "NumberInput",
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
placeholder: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,48 @@
|
|||
<template>
|
||||
<div>
|
||||
<label>{{label}}</label>
|
||||
<label>{{ label }}</label>
|
||||
|
||||
<div class="uk-form-controls">
|
||||
|
||||
<div v-for="option in options" :key="option">
|
||||
<label><input class="uk-radio" type="radio" :name="name" :value="option" :checked="value==option" @input="$emit('input', $event.target.value)"> {{ option }}</label>
|
||||
<label
|
||||
><input
|
||||
class="uk-radio"
|
||||
type="radio"
|
||||
:name="name"
|
||||
:value="option"
|
||||
:checked="value == option"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
/>
|
||||
{{ option }}</label
|
||||
>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'radioList',
|
||||
name: "RadioList",
|
||||
|
||||
props: [
|
||||
'options',
|
||||
'name',
|
||||
'label',
|
||||
'value'
|
||||
]
|
||||
}
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,42 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="uk-form-label">{{label}}</label>
|
||||
<label class="uk-form-label">{{ label }}</label>
|
||||
|
||||
<select
|
||||
class="uk-select uk-form-small"
|
||||
:multiple="multi"
|
||||
:value="value"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
>
|
||||
<option v-for="option in options" :key="option">
|
||||
{{option}}
|
||||
{{ option }}
|
||||
</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'selectList',
|
||||
name: "SelectList",
|
||||
|
||||
props: [
|
||||
'multi',
|
||||
'options',
|
||||
'name',
|
||||
'label',
|
||||
'value'
|
||||
]
|
||||
}
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,63 +1,79 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
<form @submit.prevent="handleTagSubmit">
|
||||
<div class="uk-margin-small uk-flex uk-flex-middle">
|
||||
|
||||
<div class="uk-margin-remove-top uk-width-expand">
|
||||
<div class="uk-inline uk-width-1-1">
|
||||
<span class="uk-form-icon"><i class="material-icons">label</i></span>
|
||||
<input v-model="newTag" class="uk-input uk-form-small" type="text" name="flavor" placeholder="Tag">
|
||||
<span class="uk-form-icon"
|
||||
><i class="material-icons">label</i></span
|
||||
>
|
||||
<input
|
||||
v-model="newTag"
|
||||
class="uk-input uk-form-small"
|
||||
type="text"
|
||||
name="flavor"
|
||||
placeholder="Tag"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" v-on:click="handleTagSubmit()" class="uk-icon uk-margin-left"><i class="material-icons">add_circle</i></a>
|
||||
<a href="#" class="uk-icon uk-margin-left" @click="handleTagSubmit()"
|
||||
><i class="material-icons">add_circle</i></a
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<span v-for="tag in value" :key="tag" v-on:click="delTag(tag)" class="uk-label uk-margin-small-right deletable-label"> {{ tag }} </span>
|
||||
|
||||
<span
|
||||
v-for="tag in value"
|
||||
:key="tag"
|
||||
class="uk-label uk-margin-small-right deletable-label"
|
||||
@click="delTag(tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'tagList',
|
||||
name: "TagList",
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
newTag: ""
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
props: [
|
||||
'value'
|
||||
],
|
||||
data: function() {
|
||||
return {
|
||||
newTag: ""
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleTagSubmit: function () {
|
||||
var newSelected = this.value != null ? [...this.value] : [] // Clone value array
|
||||
handleTagSubmit: function() {
|
||||
var newSelected = this.value != null ? [...this.value] : []; // Clone value array
|
||||
|
||||
newSelected.push(this.newTag)
|
||||
newSelected.push(this.newTag);
|
||||
this.newTag = "";
|
||||
|
||||
this.$emit('input', newSelected)
|
||||
this.$emit("input", newSelected);
|
||||
},
|
||||
|
||||
delTag: function (tag) {
|
||||
var newSelected = this.value != null ? [...this.value] : [] // Clone value array
|
||||
delTag: function(tag) {
|
||||
var newSelected = this.value != null ? [...this.value] : []; // Clone value array
|
||||
|
||||
if (newSelected.includes(tag)) {
|
||||
var newSelected = newSelected.filter(function(value, index, arr){
|
||||
return value != tag;
|
||||
})
|
||||
newSelected = newSelected.filter(function(value) {
|
||||
return value != tag;
|
||||
});
|
||||
}
|
||||
|
||||
this.$emit('input', newSelected)
|
||||
this.$emit("input", newSelected);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,30 +1,41 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="uk-form-label">{{label}}</label>
|
||||
<label class="uk-form-label">{{ label }}</label>
|
||||
|
||||
<input
|
||||
<input
|
||||
class="uk-input uk-form-small"
|
||||
type="text"
|
||||
v-bind:name="name"
|
||||
v-bind:value="value"
|
||||
v-bind:placeholder="placeholder"
|
||||
@input="$emit('input',$event.target.value)"
|
||||
>
|
||||
|
||||
:name="name"
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'textInput',
|
||||
name: "TextInput",
|
||||
|
||||
props: [
|
||||
'placeholder',
|
||||
'label',
|
||||
'name',
|
||||
'value'
|
||||
]
|
||||
}
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,38 +1,37 @@
|
|||
<template>
|
||||
<div class="progress uk-margin-top uk-margin-horizontal-remove uk-padding-remove">
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
<div
|
||||
class="progress uk-margin-top uk-margin-horizontal-remove uk-padding-remove"
|
||||
>
|
||||
<div class="indeterminate"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'progressBar',
|
||||
name: "ProgressBar",
|
||||
|
||||
props: {},
|
||||
|
||||
methods: {
|
||||
setThisTab(event, value) {
|
||||
this.$emit('set-tab', event, this.id);
|
||||
computed: {
|
||||
tooltipOptions: function() {
|
||||
var title = this.id.charAt(0).toUpperCase() + this.id.slice(1);
|
||||
return `pos: right; title: ${title}; delay: 500`;
|
||||
},
|
||||
|
||||
classObject: function() {
|
||||
return {
|
||||
"tabicon-active": this.currentTab == this.id,
|
||||
"uk-disabled": this.requireConnection && !this.$store.getters.ready
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
tooltipOptions: function () {
|
||||
var title = this.id.charAt(0).toUpperCase() + this.id.slice(1);
|
||||
return `pos: right; title: ${title}; delay: 500`
|
||||
},
|
||||
|
||||
classObject: function () {
|
||||
return {
|
||||
'tabicon-active': this.currentTab == this.id,
|
||||
'uk-disabled': (this.requireConnection && !this.$store.getters.ready)
|
||||
}
|
||||
methods: {
|
||||
setThisTab(event) {
|
||||
this.$emit("set-tab", event, this.id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -47,7 +46,7 @@ export default {
|
|||
border-radius: 2px;
|
||||
background-clip: padding-box;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress .determinate {
|
||||
|
|
@ -55,88 +54,104 @@ export default {
|
|||
background-color: inherit;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transition: width .3s linear;
|
||||
transition: width 0.3s linear;
|
||||
}
|
||||
|
||||
.progress .indeterminate, .progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.progress .indeterminate, .progress .determinate{
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
}
|
||||
|
||||
.progress .indeterminate:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
|
||||
infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
}
|
||||
|
||||
.progress .indeterminate:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
-webkit-animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
<template>
|
||||
|
||||
<div
|
||||
<div
|
||||
v-if="!(this.requireConnection && !this.$store.getters.ready)"
|
||||
v-bind:hidden="currentTab!=id"
|
||||
:hidden="currentTab != id"
|
||||
class="uk-width-expand"
|
||||
>
|
||||
<div class="section-heading">{{ id }}</div>
|
||||
<div class="section-content"><slot></slot></div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'tabContent',
|
||||
name: "TabContent",
|
||||
|
||||
props: {
|
||||
id: String,
|
||||
currentTab: String,
|
||||
requireConnection: Boolean,
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
currentTab: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
requireConnection: Boolean
|
||||
},
|
||||
computed: {},
|
||||
|
||||
methods: {},
|
||||
computed: {}
|
||||
}
|
||||
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.section-heading {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
|
|
@ -39,8 +39,8 @@ export default {
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
.section-content, .section-heading {
|
||||
.section-content,
|
||||
.section-heading {
|
||||
padding: 9px 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,48 +1,51 @@
|
|||
<template>
|
||||
<a
|
||||
href="#"
|
||||
<a
|
||||
href="#"
|
||||
class="uk-link"
|
||||
:class="classObject"
|
||||
:class="classObject"
|
||||
:uk-tooltip="tooltipOptions"
|
||||
@click="setThisTab">
|
||||
@click="setThisTab"
|
||||
>
|
||||
<slot></slot>
|
||||
</a>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'tabIcon',
|
||||
name: "TabIcon",
|
||||
|
||||
props: {
|
||||
id: String,
|
||||
currentTab: String,
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
currentTab: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
requireConnection: Boolean
|
||||
},
|
||||
|
||||
methods: {
|
||||
setThisTab(event, value) {
|
||||
this.$emit('set-tab', event, this.id);
|
||||
computed: {
|
||||
tooltipOptions: function() {
|
||||
var title = this.id.charAt(0).toUpperCase() + this.id.slice(1);
|
||||
return `pos: right; title: ${title}; delay: 500`;
|
||||
},
|
||||
|
||||
classObject: function() {
|
||||
return {
|
||||
"tabicon-active": this.currentTab == this.id,
|
||||
"uk-disabled": this.requireConnection && !this.$store.getters.ready
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
tooltipOptions: function () {
|
||||
var title = this.id.charAt(0).toUpperCase() + this.id.slice(1);
|
||||
return `pos: right; title: ${title}; delay: 500`
|
||||
},
|
||||
|
||||
classObject: function () {
|
||||
return {
|
||||
'tabicon-active': this.currentTab == this.id,
|
||||
'uk-disabled': (this.requireConnection && !this.$store.getters.ready)
|
||||
}
|
||||
methods: {
|
||||
setThisTab(event) {
|
||||
this.$emit("set-tab", event, this.id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -54,9 +57,8 @@ export default {
|
|||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.tabicon-active {
|
||||
color: @inverse-primary-muted-color !important;
|
||||
}
|
||||
.tabicon-active {
|
||||
color: @inverse-primary-muted-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,31 @@
|
|||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="progress uk-margin-top uk-margin-horizontal-remove uk-padding-remove"
|
||||
>
|
||||
<div
|
||||
v-if="progress"
|
||||
class="determinate"
|
||||
:style="barWidthFromProgress"
|
||||
></div>
|
||||
<div v-else class="indeterminate"></div>
|
||||
</div>
|
||||
|
||||
<div class="progress uk-margin-top uk-margin-horizontal-remove uk-padding-remove">
|
||||
<div v-if="progress" class="determinate" :style="barWidthFromProgress"></div>
|
||||
<div v-else class="indeterminate"></div>
|
||||
<button
|
||||
type="button"
|
||||
class="uk-button uk-button-danger uk-form-small uk-float-right uk-width-1-1"
|
||||
@click="terminateTask()"
|
||||
>
|
||||
Terminate
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button type="button" v-on:click="terminateTask()" class="uk-button uk-button-danger uk-form-small uk-float-right uk-width-1-1">Terminate</button>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: 'taskProgress',
|
||||
name: "TaskProgress",
|
||||
|
||||
props: {
|
||||
taskId: {
|
||||
|
|
@ -26,54 +36,54 @@ export default {
|
|||
type: Number,
|
||||
required: false,
|
||||
default: 500
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
polling: null,
|
||||
polling: null,
|
||||
progress: null
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
barWidthFromProgress: function() {
|
||||
var progress = this.progress <= 100 ? this.progress : 100;
|
||||
var styleString = `width: ${progress}%`;
|
||||
return styleString;
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.polling = setInterval(() => {
|
||||
this.pollProgress()
|
||||
}, this.pollInterval)
|
||||
this.pollProgress();
|
||||
}, this.pollInterval);
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
clearInterval(this.polling)
|
||||
beforeDestroy() {
|
||||
clearInterval(this.polling);
|
||||
},
|
||||
|
||||
methods: {
|
||||
pollProgress: function() {
|
||||
console.log("Starting progress polling")
|
||||
axios.get(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("PROGRESS RESPONSE: ", response.data.progress)
|
||||
this.progress = response.data.progress
|
||||
})
|
||||
console.log("Starting progress polling");
|
||||
axios
|
||||
.get(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("PROGRESS RESPONSE: ", response.data.progress);
|
||||
this.progress = response.data.progress;
|
||||
});
|
||||
},
|
||||
|
||||
terminateTask: function() {
|
||||
axios.delete(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("TERMINATION RESPONSE: ", response.data)
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
barWidthFromProgress: function () {
|
||||
var progress = ((this.progress <= 100) ? this.progress : 100)
|
||||
var styleString = `width: ${progress}%`
|
||||
return styleString
|
||||
},
|
||||
axios
|
||||
.delete(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("TERMINATION RESPONSE: ", response.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -88,7 +98,7 @@ export default {
|
|||
border-radius: 2px;
|
||||
background-clip: padding-box;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress .determinate {
|
||||
|
|
@ -96,88 +106,104 @@ export default {
|
|||
background-color: inherit;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transition: width .3s linear;
|
||||
transition: width 0.3s linear;
|
||||
}
|
||||
|
||||
.progress .indeterminate, .progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.progress .indeterminate, .progress .determinate{
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
}
|
||||
|
||||
.progress .indeterminate:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
|
||||
infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
}
|
||||
|
||||
.progress .indeterminate:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
-webkit-animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,25 +1,43 @@
|
|||
<template>
|
||||
<div class="uk-margin-horizontal-remove uk-padding-remove">
|
||||
<div
|
||||
class="uk-margin-horizontal-remove uk-margin-small-top uk-padding-remove"
|
||||
>
|
||||
<div v-if="taskRunning" ref="isPollingElement">
|
||||
<div class="progress">
|
||||
<div
|
||||
v-if="progress"
|
||||
class="determinate"
|
||||
:style="barWidthFromProgress"
|
||||
></div>
|
||||
<div v-else class="indeterminate"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="taskRunning" ref="isPollingElement">
|
||||
<div class="progress">
|
||||
<div v-if="progress" class="determinate" :style="barWidthFromProgress"></div>
|
||||
<div v-else class="indeterminate"></div>
|
||||
<button
|
||||
v-if="canTerminate"
|
||||
type="button"
|
||||
class="uk-button uk-button-danger uk-form-small uk-margin uk-float-right uk-width-1-1"
|
||||
@click="terminateTask()"
|
||||
>
|
||||
Terminate
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button v-if="canTerminate" type="button" v-on:click="terminateTask()" class="uk-button uk-button-danger uk-form-small uk-margin uk-float-right uk-width-1-1">Terminate</button>
|
||||
<button
|
||||
type="button"
|
||||
:hidden="taskRunning"
|
||||
class="uk-button uk-button-primary uk-form-small uk-margin uk-float-right uk-width-1-1"
|
||||
@click="bootstrapTask()"
|
||||
>
|
||||
{{ submitLabel }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button type="button" v-on:click="bootstrapTask()" v-bind:hidden="taskRunning" class="uk-button uk-button-primary uk-form-small uk-margin uk-float-right uk-width-1-1">{{ submitLabel }}</button>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: 'taskSubmitter',
|
||||
name: "TaskSubmitter",
|
||||
|
||||
props: {
|
||||
submitURL: {
|
||||
|
|
@ -63,148 +81,152 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
taskId: null,
|
||||
polling: null,
|
||||
polling: null,
|
||||
progress: null,
|
||||
taskRunning: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
barWidthFromProgress: function() {
|
||||
var progress = this.progress <= 100 ? this.progress : 100;
|
||||
var styleString = `width: ${progress}%`;
|
||||
return styleString;
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
},
|
||||
created() {},
|
||||
|
||||
beforeDestroy () {
|
||||
},
|
||||
beforeDestroy() {},
|
||||
|
||||
methods: {
|
||||
bootstrapTask: function() {
|
||||
if (this.requiresConfirmation) {
|
||||
this.modalConfirm(this.confirmationMessage)
|
||||
.then(() => {
|
||||
this.startTask()
|
||||
}, () => {})
|
||||
}
|
||||
else {
|
||||
this.startTask()
|
||||
this.modalConfirm(this.confirmationMessage).then(
|
||||
() => {
|
||||
this.startTask();
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
} else {
|
||||
this.startTask();
|
||||
}
|
||||
},
|
||||
|
||||
startTask: function() {
|
||||
console.log("Task start clicked")
|
||||
this.$emit('submit', this.submitData)
|
||||
console.log("Task start clicked");
|
||||
this.$emit("submit", this.submitData);
|
||||
// Send a request to start a task
|
||||
axios.post(this.submitURL, this.submitData)
|
||||
// Get the returned Task ID
|
||||
.then(response => {
|
||||
// Fetch the task ID
|
||||
console.log("Task ID: " + response.data.id)
|
||||
this.taskId = response.data.id
|
||||
// Start the store polling TaskId for success
|
||||
this.taskRunning = true
|
||||
// Return the poll-task promise (starts polling the task)
|
||||
return this.pollTask(this.taskId, this.pollTimeout, this.pollInterval)
|
||||
})
|
||||
.then(response => {
|
||||
// Do something with the final response
|
||||
console.log("Emitting onResponse: ", response)
|
||||
this.$emit('response', response)
|
||||
})
|
||||
.catch(error => {
|
||||
if (!error) {
|
||||
error = Error("Unknown error")
|
||||
}
|
||||
console.log("Emitting onError: ", error)
|
||||
this.$emit('error', error)
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after task.")
|
||||
// Reset taskRunning and taskId
|
||||
this.taskRunning = false
|
||||
this.taskId = null
|
||||
// Update the form data if we're self-updating
|
||||
if (this.selfUpdate) {
|
||||
this.getFormData()
|
||||
}
|
||||
})
|
||||
axios
|
||||
.post(this.submitURL, this.submitData)
|
||||
// Get the returned Task ID
|
||||
.then(response => {
|
||||
// Fetch the task ID
|
||||
console.log("Task ID: " + response.data.id);
|
||||
this.taskId = response.data.id;
|
||||
// Start the store polling TaskId for success
|
||||
this.taskRunning = true;
|
||||
// Return the poll-task promise (starts polling the task)
|
||||
return this.pollTask(
|
||||
this.taskId,
|
||||
this.pollTimeout,
|
||||
this.pollInterval
|
||||
);
|
||||
})
|
||||
.then(response => {
|
||||
// Do something with the final response
|
||||
console.log("Emitting onResponse: ", response);
|
||||
this.$emit("response", response);
|
||||
})
|
||||
.catch(error => {
|
||||
if (!error) {
|
||||
error = Error("Unknown error");
|
||||
}
|
||||
console.log("Emitting onError: ", error);
|
||||
this.$emit("error", error);
|
||||
})
|
||||
.finally(() => {
|
||||
console.log("Cleaning up after task.");
|
||||
// Reset taskRunning and taskId
|
||||
this.taskRunning = false;
|
||||
this.taskId = null;
|
||||
// Update the form data if we're self-updating
|
||||
if (this.selfUpdate) {
|
||||
this.getFormData();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
pollTask: function(taskId, timeout, interval) {
|
||||
var endTime = Number(new Date()) + (timeout*1000 || 30000);
|
||||
interval = interval*1000 || 500;
|
||||
var endTime = Number(new Date()) + (timeout * 1000 || 30000);
|
||||
interval = interval * 1000 || 500;
|
||||
|
||||
var checkCondition = (resolve, reject) => {
|
||||
// If the condition is met, we're done!
|
||||
axios.get(`${this.$store.getters.uri}/task/${taskId}`)
|
||||
.then(response => {
|
||||
console.log(response.data.status)
|
||||
var result = response.data.status
|
||||
// If the task ends with success
|
||||
if(result == 'success') {
|
||||
resolve(response.data)
|
||||
}
|
||||
// If task ends with an error
|
||||
else if (result == 'error') {
|
||||
// Pass the error string back with reject
|
||||
reject(new Error(response.data.return))
|
||||
}
|
||||
// If task ends with termination
|
||||
else if (result == 'terminated') {
|
||||
// Pass a generic termination error back with reject
|
||||
reject(new Error("Task terminated"))
|
||||
}
|
||||
// If task ends in any other way
|
||||
else if (result != 'running') {
|
||||
// Pass status string as error
|
||||
reject(new Error(result))
|
||||
}
|
||||
// If the condition isn't met but the timeout hasn't elapsed, go again
|
||||
else if (Number(new Date()) < endTime) {
|
||||
// Since the task is still running, we can update the progress bar
|
||||
this.progress = response.data.progress
|
||||
// Check again after timeout
|
||||
setTimeout(checkCondition, interval, resolve, reject)
|
||||
}
|
||||
// Didn't match and too much time, reject!
|
||||
else {
|
||||
reject(new Error('Polling timed out'))
|
||||
}
|
||||
})
|
||||
// If the condition is met, we're done!
|
||||
axios
|
||||
.get(`${this.$store.getters.uri}/task/${taskId}`)
|
||||
.then(response => {
|
||||
console.log(response.data.status);
|
||||
var result = response.data.status;
|
||||
// If the task ends with success
|
||||
if (result == "success") {
|
||||
resolve(response.data);
|
||||
}
|
||||
// If task ends with an error
|
||||
else if (result == "error") {
|
||||
// Pass the error string back with reject
|
||||
reject(new Error(response.data.return));
|
||||
}
|
||||
// If task ends with termination
|
||||
else if (result == "terminated") {
|
||||
// Pass a generic termination error back with reject
|
||||
reject(new Error("Task terminated"));
|
||||
}
|
||||
// If task ends in any other way
|
||||
else if (result != "running") {
|
||||
// Pass status string as error
|
||||
reject(new Error(result));
|
||||
}
|
||||
// If the condition isn't met but the timeout hasn't elapsed, go again
|
||||
else if (Number(new Date()) < endTime) {
|
||||
// Since the task is still running, we can update the progress bar
|
||||
this.progress = response.data.progress;
|
||||
// Check again after timeout
|
||||
setTimeout(checkCondition, interval, resolve, reject);
|
||||
}
|
||||
// Didn't match and too much time, reject!
|
||||
else {
|
||||
reject(new Error("Polling timed out"));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(checkCondition);
|
||||
},
|
||||
|
||||
pollProgress: function() {
|
||||
console.log("Starting progress polling")
|
||||
|
||||
axios.get(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("PROGRESS RESPONSE: ", response.data.progress)
|
||||
this.progress = response.data.progress
|
||||
})
|
||||
console.log("Starting progress polling");
|
||||
|
||||
axios
|
||||
.get(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("PROGRESS RESPONSE: ", response.data.progress);
|
||||
this.progress = response.data.progress;
|
||||
});
|
||||
},
|
||||
|
||||
terminateTask: function() {
|
||||
axios.delete(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("TERMINATION RESPONSE: ", response.data)
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
barWidthFromProgress: function () {
|
||||
var progress = ((this.progress <= 100) ? this.progress : 100)
|
||||
var styleString = `width: ${progress}%`
|
||||
return styleString
|
||||
},
|
||||
axios
|
||||
.delete(`${this.$store.getters.uri}/task/${this.taskId}`)
|
||||
.then(response => {
|
||||
console.log("TERMINATION RESPONSE: ", response.data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -219,7 +241,7 @@ export default {
|
|||
border-radius: 2px;
|
||||
background-clip: padding-box;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress .determinate {
|
||||
|
|
@ -227,88 +249,104 @@ export default {
|
|||
background-color: inherit;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transition: width .3s linear;
|
||||
transition: width 0.3s linear;
|
||||
}
|
||||
|
||||
.progress .indeterminate, .progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @global-primary-background;
|
||||
}
|
||||
|
||||
.hook-inverse() {
|
||||
.progress .indeterminate, .progress .determinate{
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
.progress .indeterminate,
|
||||
.progress .determinate {
|
||||
background-color: @inverse-primary-muted-color;
|
||||
}
|
||||
}
|
||||
|
||||
.progress .indeterminate:before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
|
||||
infinite;
|
||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
||||
}
|
||||
|
||||
.progress .indeterminate:after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite;
|
||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
||||
infinite;
|
||||
-webkit-animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
animation-delay: 1.15s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%; }
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%; }
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%; }
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,95 +1,147 @@
|
|||
<template>
|
||||
<div id="panel-left" class="uk-margin-remove uk-padding-remove uk-height-1-1" uk-grid>
|
||||
|
||||
<div
|
||||
id="panel-left"
|
||||
class="uk-margin-remove uk-padding-remove uk-height-1-1"
|
||||
uk-grid
|
||||
>
|
||||
<!-- Vertical tab bar -->
|
||||
<div id="switcher-left" class="uk-flex uk-flex-column uk-padding-remove uk-width-auto uk-height-1-1">
|
||||
<tabIcon id="status" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab">
|
||||
<div
|
||||
id="switcher-left"
|
||||
class="uk-flex uk-flex-column uk-padding-remove uk-width-auto uk-height-1-1"
|
||||
>
|
||||
<tabIcon
|
||||
id="status"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<i class="material-icons">bug_report</i>
|
||||
</tabIcon>
|
||||
<tabIcon id="navigate" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab">
|
||||
<i class="material-icons">gamepad</i>
|
||||
<tabIcon
|
||||
id="navigate"
|
||||
:require-connection="true"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<i class="material-icons">gamepad</i>
|
||||
</tabIcon>
|
||||
<tabIcon id="capture" :requireConnection="true" :currentTab="currentTab" @set-tab="setTab">
|
||||
<tabIcon
|
||||
id="capture"
|
||||
:require-connection="true"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<i class="material-icons">camera_alt</i>
|
||||
</tabIcon>
|
||||
<tabIcon id="settings" :requireConnection="false" :currentTab="currentTab" @set-tab="setTab">
|
||||
<i class="material-icons">settings</i>
|
||||
<tabIcon
|
||||
id="settings"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<i class="material-icons">settings</i>
|
||||
</tabIcon>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<tabIcon v-for="plugin in $store.state.apiPlugins" @set-tab="setTab"
|
||||
:key="plugin.id"
|
||||
:id="plugin.id"
|
||||
:requireConnection="plugin.requiresConnection"
|
||||
:currentTab="currentTab">
|
||||
<i class="material-icons">{{ plugin.icon || "extension" }}</i>
|
||||
<tabIcon
|
||||
v-for="plugin in $store.state.apiPlugins"
|
||||
:id="plugin.id"
|
||||
:key="plugin.id"
|
||||
:require-connection="plugin.requiresConnection"
|
||||
:current-tab="currentTab"
|
||||
@set-tab="setTab"
|
||||
>
|
||||
<i class="material-icons">{{ plugin.icon || "extension" }}</i>
|
||||
</tabIcon>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Corresponding vertical tab content -->
|
||||
<div v-bind:hidden="!showControlBar" id="container-left" class="uk-padding-remove uk-height-1-1 uk-width-expand">
|
||||
<div id="component-left" class="uk-padding-remove uk-flex uk-flex-1 panel-content">
|
||||
<tabContent id="status" :requireConnection="false" :currentTab="currentTab">
|
||||
<paneStatus/>
|
||||
<div
|
||||
id="container-left"
|
||||
:hidden="!showControlBar"
|
||||
class="uk-padding-remove uk-height-1-1 uk-width-expand"
|
||||
>
|
||||
<div
|
||||
id="component-left"
|
||||
class="uk-padding-remove uk-flex uk-flex-1 panel-content"
|
||||
>
|
||||
<tabContent
|
||||
id="status"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<paneStatus />
|
||||
</tabContent>
|
||||
<tabContent id="navigate" :requireConnection="true" :currentTab="currentTab">
|
||||
<paneNavigate/>
|
||||
<tabContent
|
||||
id="navigate"
|
||||
:require-connection="true"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<paneNavigate />
|
||||
</tabContent>
|
||||
<tabContent id="capture" :requireConnection="true" :currentTab="currentTab">
|
||||
<paneCapture/>
|
||||
<tabContent
|
||||
id="capture"
|
||||
:require-connection="true"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<paneCapture />
|
||||
</tabContent>
|
||||
<tabContent id="settings" :requireConnection="false" :currentTab="currentTab">
|
||||
<paneSettings/>
|
||||
<tabContent
|
||||
id="settings"
|
||||
:require-connection="false"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<paneSettings />
|
||||
</tabContent>
|
||||
|
||||
<tabContent v-for="plugin in $store.state.apiPlugins"
|
||||
:key="plugin.id"
|
||||
:id="plugin.id"
|
||||
:requireConnection="plugin.requiresConnection"
|
||||
:currentTab="currentTab">
|
||||
|
||||
<div class="uk-flex uk-flex-column" v-for="form in plugin.forms" :key="`${form.route}/${form.name}`.replace(/\s+/g, '-').toLowerCase()" >
|
||||
<JsonForm
|
||||
<tabContent
|
||||
v-for="plugin in $store.state.apiPlugins"
|
||||
:id="plugin.id"
|
||||
:key="plugin.id"
|
||||
:require-connection="plugin.requiresConnection"
|
||||
:current-tab="currentTab"
|
||||
>
|
||||
<div
|
||||
v-for="form in plugin.forms"
|
||||
:key="
|
||||
`${form.route}/${form.name}`.replace(/\s+/g, '-').toLowerCase()
|
||||
"
|
||||
class="uk-flex uk-flex-column"
|
||||
>
|
||||
<JsonForm
|
||||
:name="form.name"
|
||||
:route="form.route"
|
||||
:isTask="form.isTask"
|
||||
:submitLabel="form.submitLabel"
|
||||
:selfUpdate="form.selfUpdate"
|
||||
:schema="form.schema"/>
|
||||
<hr>
|
||||
:is-task="form.isTask"
|
||||
:submit-label="form.submitLabel"
|
||||
:self-update="form.selfUpdate"
|
||||
:schema="form.schema"
|
||||
/>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
</tabContent>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Import axios for HTTP requests
|
||||
import axios from 'axios'
|
||||
|
||||
// Import generic components
|
||||
import tabIcon from './genericComponents/tabIcon'
|
||||
import tabContent from './genericComponents/tabContent'
|
||||
import tabIcon from "./genericComponents/tabIcon";
|
||||
import tabContent from "./genericComponents/tabContent";
|
||||
|
||||
// Import pane components
|
||||
import paneStatus from './controlComponents/paneStatus'
|
||||
import paneNavigate from './controlComponents/paneNavigate'
|
||||
import paneCapture from './controlComponents/paneCapture'
|
||||
import paneSettings from './controlComponents/paneSettings'
|
||||
import paneStatus from "./controlComponents/paneStatus";
|
||||
import paneNavigate from "./controlComponents/paneNavigate";
|
||||
import paneCapture from "./controlComponents/paneCapture";
|
||||
import paneSettings from "./controlComponents/paneSettings";
|
||||
|
||||
// Import plugin components
|
||||
import JsonForm from './pluginComponents/JsonForm'
|
||||
import JsonForm from "./pluginComponents/JsonForm";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'panelLeft',
|
||||
name: "PanelLeft",
|
||||
|
||||
components: {
|
||||
tabIcon,
|
||||
|
|
@ -101,38 +153,34 @@ export default {
|
|||
JsonForm
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
currentTab: 'status',
|
||||
currentTab: "status",
|
||||
showControlBar: true
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
pluginApiUri: function() {
|
||||
return this.$store.getters.uri + "/plugin";
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
setTab: function(event, tab) {
|
||||
if (this.currentTab == tab) {
|
||||
this.showControlBar = !this.showControlBar
|
||||
this.currentTab = 'none'
|
||||
this.showControlBar = !this.showControlBar;
|
||||
this.currentTab = "none";
|
||||
} else {
|
||||
this.showControlBar = true;
|
||||
this.currentTab = tab;
|
||||
}
|
||||
else {
|
||||
this.showControlBar = true
|
||||
this.currentTab = tab
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
pluginApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
#component-left {
|
||||
width: 300px;
|
||||
}
|
||||
|
|
@ -142,19 +190,19 @@ export default {
|
|||
background-color: rgba(180, 180, 180, 0.025);
|
||||
}
|
||||
|
||||
#container-left, #switcher-left {
|
||||
#container-left,
|
||||
#switcher-left {
|
||||
border-width: 0 1px 0 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(180, 180, 180, 0.25)
|
||||
border-color: rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
|
||||
#switcher-left a{
|
||||
#switcher-left a {
|
||||
padding: 10px 16px;
|
||||
}
|
||||
|
||||
#switcher-left{
|
||||
#switcher-left {
|
||||
background-color: rgba(180, 180, 180, 0.1);
|
||||
padding-top: 2px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,81 +1,98 @@
|
|||
<template>
|
||||
<!-- Tabbed panel for gallery and live views -->
|
||||
<div id="panel-right" class="uk-flex uk-flex-column uk-margin-remove uk-padding-remove uk-width-expand uk-height-1-1">
|
||||
<ul class="uk-flex-none uk-flex-center uk-margin-remove-bottom uk-text-center" id="tabContainer" uk-tab="swiping: false">
|
||||
<div
|
||||
id="panel-right"
|
||||
class="uk-flex uk-flex-column uk-margin-remove uk-padding-remove uk-width-expand uk-height-1-1"
|
||||
>
|
||||
<ul
|
||||
id="tabContainer"
|
||||
class="uk-flex-none uk-flex-center uk-margin-remove-bottom uk-text-center"
|
||||
uk-tab="swiping: false"
|
||||
>
|
||||
<li><a href="#" uk-switcher-item="connect">Connect</a></li>
|
||||
<li v-bind:class="{'uk-disabled': !this.$store.getters.ready}"><a href="#" uk-switcher-item="preview">Live</a></li>
|
||||
<li v-bind:class="{'uk-disabled': !this.$store.getters.ready}"><a href="#" uk-switcher-item="gallery">Gallery</a></li>
|
||||
<li :class="{ 'uk-disabled': !this.$store.getters.ready }">
|
||||
<a href="#" uk-switcher-item="preview">Live</a>
|
||||
</li>
|
||||
<li :class="{ 'uk-disabled': !this.$store.getters.ready }">
|
||||
<a href="#" uk-switcher-item="gallery">Gallery</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="uk-switcher uk-flex uk-flex-1 uk-overflow-auto">
|
||||
<li class="uk-height-1-1 uk-width-1-1" id="connectDisplayTab"><connectDisplay/></li>
|
||||
<li class="uk-height-1-1 uk-width-1-1 clickableTab" id="streamDisplayTab"><streamDisplay/></li>
|
||||
<li class="uk-height-1-1 uk-width-1-1" id="galleryDisplayTab"><galleryDisplay/></li>
|
||||
<li id="connectDisplayTab" class="uk-height-1-1 uk-width-1-1">
|
||||
<connectDisplay />
|
||||
</li>
|
||||
<li id="streamDisplayTab" class="uk-height-1-1 uk-width-1-1 clickableTab">
|
||||
<streamDisplay />
|
||||
</li>
|
||||
<li id="galleryDisplayTab" class="uk-height-1-1 uk-width-1-1">
|
||||
<galleryDisplay />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Import axios for HTTP requests
|
||||
import axios from 'axios'
|
||||
// Import basic UIkit
|
||||
import UIkit from 'uikit';
|
||||
import UIkit from "uikit";
|
||||
|
||||
// Import components
|
||||
import connectDisplay from './viewComponents/connectDisplay.vue'
|
||||
import streamDisplay from './viewComponents/streamDisplay.vue'
|
||||
import galleryDisplay from './viewComponents/galleryDisplay.vue'
|
||||
import connectDisplay from "./viewComponents/connectDisplay.vue";
|
||||
import streamDisplay from "./viewComponents/streamDisplay.vue";
|
||||
import galleryDisplay from "./viewComponents/galleryDisplay.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'panelRight',
|
||||
name: "PanelRight",
|
||||
|
||||
components: {
|
||||
connectDisplay,
|
||||
streamDisplay,
|
||||
galleryDisplay,
|
||||
galleryDisplay
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Attach methods to UIkit events for tab switching
|
||||
var context = this;
|
||||
// Gallery tab
|
||||
UIkit.util.on('#streamDisplayTab', 'hidden', function(event, area) {
|
||||
console.log("Stream tab hidden")
|
||||
|
||||
// Stream tab leave
|
||||
UIkit.util.on("#streamDisplayTab", "hidden", function() {
|
||||
console.log("Stream tab hidden");
|
||||
if (context.$store.state.globalSettings.trackWindow == true) {
|
||||
context.$root.$emit('globalTogglePreview', false)
|
||||
context.$root.$emit("globalTogglePreview", false);
|
||||
}
|
||||
context.$root.$emit('globalUpdateCaptureList');
|
||||
});
|
||||
|
||||
// Stream tab
|
||||
UIkit.util.on('#streamDisplayTab', 'shown', function(event, area) {
|
||||
console.log("Stream tab entered")
|
||||
UIkit.update()
|
||||
// Stream tab enter
|
||||
UIkit.util.on("#streamDisplayTab", "shown", function() {
|
||||
console.log("Stream tab entered");
|
||||
UIkit.update();
|
||||
if (context.$store.state.globalSettings.trackWindow == true) {
|
||||
context.$root.$emit('globalTogglePreview', true)
|
||||
context.$root.$emit("globalTogglePreview", true);
|
||||
}
|
||||
});
|
||||
|
||||
// Gallery tab enter
|
||||
UIkit.util.on("#galleryDisplayTab", "shown", function() {
|
||||
console.log("Gallery tab entered");
|
||||
UIkit.update();
|
||||
context.$root.$emit("globalUpdateCaptureList");
|
||||
});
|
||||
|
||||
// Create a global event to switch the active tab
|
||||
var switcherObj = UIkit.tab('#tabContainer')
|
||||
console.log(switcherObj)
|
||||
this.$root.$on('globalTogglePanelRightTab', (state) => {
|
||||
console.log(`Toggling panelRight tab to ${state}`)
|
||||
switcherObj.show(1)
|
||||
})
|
||||
|
||||
var switcherObj = UIkit.tab("#tabContainer");
|
||||
console.log(switcherObj);
|
||||
this.$root.$on("globalTogglePanelRightTab", state => {
|
||||
console.log(`Toggling panelRight tab to ${state}`);
|
||||
switcherObj.show(1);
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
}
|
||||
|
||||
}
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
.uk-tab {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,68 +1,86 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
<div class="uk-flex">
|
||||
<div class="uk-text-bold uk-text-uppercase uk-width-expand">{{ name }}</div>
|
||||
<a href="#" v-if="selfUpdate" v-on:click="getFormData()" class="uk-icon uk-width-auto"><i class="material-icons">cached</i></a>
|
||||
<div class="uk-text-bold uk-text-uppercase uk-width-expand">
|
||||
{{ name }}
|
||||
</div>
|
||||
<a
|
||||
v-if="selfUpdate"
|
||||
href="#"
|
||||
class="uk-icon uk-width-auto"
|
||||
@click="getFormData()"
|
||||
><i class="material-icons">cached</i></a
|
||||
>
|
||||
</div>
|
||||
|
||||
<form @submit.prevent="" class="uk-form-stacked" ref="formContainer">
|
||||
|
||||
<div v-for="(field, index) in schema" :key="index">
|
||||
<div v-if="Array.isArray(field)" class="uk-grid-small uk-width-1-1 uk-child-width-expand" uk-grid>
|
||||
<div v-for="(subfield, subindex) in field" :key="subindex">
|
||||
<form ref="formContainer" class="uk-form-stacked" @submit.prevent="">
|
||||
<div v-for="(field, index) in schema" :key="index">
|
||||
<div
|
||||
v-if="Array.isArray(field)"
|
||||
class="uk-grid-small uk-width-1-1 uk-child-width-expand"
|
||||
uk-grid
|
||||
>
|
||||
<div v-for="(subfield, subindex) in field" :key="subindex">
|
||||
<component
|
||||
:is="subfield.fieldType"
|
||||
v-model="formData[subfield.name]"
|
||||
v-bind="subfield">
|
||||
v-bind="subfield"
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<component
|
||||
:is="field.fieldType"
|
||||
v-model="formData[field.name]"
|
||||
v-bind="field">
|
||||
v-bind="field"
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<taskSubmitter v-if="isTask"
|
||||
v-bind:submitURL="submitApiUri"
|
||||
v-bind:submitData="formData"
|
||||
v-bind:submitLabel="submitLabel"
|
||||
v-on:submit="onTaskSubmit"
|
||||
v-on:response="onTaskResponse"
|
||||
v-on:error="onTaskError">
|
||||
<taskSubmitter
|
||||
v-if="isTask"
|
||||
:submit-u-r-l="submitApiUri"
|
||||
:submit-data="formData"
|
||||
:submit-label="submitLabel"
|
||||
@submit="onTaskSubmit"
|
||||
@response="onTaskResponse"
|
||||
@error="onTaskError"
|
||||
>
|
||||
</taskSubmitter>
|
||||
|
||||
<button v-else type="button" v-on:click="newQuickRequest(formData);" class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1">{{ submitLabel }}</button>
|
||||
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin-small uk-width-1-1"
|
||||
@click="newQuickRequest(formData)"
|
||||
>
|
||||
{{ submitLabel }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
import numberInput from "../fieldComponents/numberInput"
|
||||
import selectList from "../fieldComponents/selectList"
|
||||
import textInput from "../fieldComponents/textInput"
|
||||
import htmlBlock from "../fieldComponents/htmlBlock"
|
||||
import radioList from "../fieldComponents/radioList"
|
||||
import checkList from "../fieldComponents/checkList"
|
||||
import tagList from "../fieldComponents/tagList"
|
||||
import keyvalList from "../fieldComponents/keyvalList"
|
||||
import numberInput from "../fieldComponents/numberInput";
|
||||
import selectList from "../fieldComponents/selectList";
|
||||
import textInput from "../fieldComponents/textInput";
|
||||
import htmlBlock from "../fieldComponents/htmlBlock";
|
||||
import radioList from "../fieldComponents/radioList";
|
||||
import checkList from "../fieldComponents/checkList";
|
||||
import tagList from "../fieldComponents/tagList";
|
||||
import keyvalList from "../fieldComponents/keyvalList";
|
||||
|
||||
import taskSubmitter from "../genericComponents/taskSubmitter"
|
||||
import taskSubmitter from "../genericComponents/taskSubmitter";
|
||||
|
||||
export default {
|
||||
name: 'JsonForm',
|
||||
name: "JsonForm",
|
||||
|
||||
components: {
|
||||
numberInput,
|
||||
selectList,
|
||||
components: {
|
||||
numberInput,
|
||||
selectList,
|
||||
textInput,
|
||||
htmlBlock,
|
||||
radioList,
|
||||
|
|
@ -73,47 +91,57 @@ export default {
|
|||
},
|
||||
|
||||
props: {
|
||||
'name': {
|
||||
name: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "Plugin"
|
||||
},
|
||||
'schema': {
|
||||
schema: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
'route': {
|
||||
route: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
'isTask': {
|
||||
isTask: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
'submitLabel': {
|
||||
submitLabel: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: "Submit"
|
||||
},
|
||||
'selfUpdate': {
|
||||
selfUpdate: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
formData: {}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
pluginApiUri: function() {
|
||||
return this.$store.getters.uri + "/plugin";
|
||||
},
|
||||
|
||||
submitApiUri: function() {
|
||||
return this.pluginApiUri + this.route;
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.initialiseFormData()
|
||||
this.initialiseFormData();
|
||||
|
||||
if (this.selfUpdate) {
|
||||
this.getFormData()
|
||||
this.getFormData();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -129,83 +157,67 @@ export default {
|
|||
for (const field of this.schema) {
|
||||
if (Array.isArray(field)) {
|
||||
for (const subfield of field) {
|
||||
console.log(subfield.name)
|
||||
this.$set(this.formData, subfield.name, null)
|
||||
console.log(subfield.name);
|
||||
this.$set(this.formData, subfield.name, null);
|
||||
}
|
||||
} else {
|
||||
console.log(field.name);
|
||||
this.$set(this.formData, field.name, null);
|
||||
}
|
||||
else {
|
||||
console.log(field.name)
|
||||
this.$set(this.formData, field.name, null)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
updateForm(fieldName, value) {
|
||||
this.$set(this.formData, fieldName, value);
|
||||
this.$emit('input', this.formData)
|
||||
this.$emit("input", this.formData);
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
// Send a quick request
|
||||
axios.get(this.submitApiUri)
|
||||
.then(response => {
|
||||
console.log(response.data)
|
||||
Object.assign(this.formData, response.data)
|
||||
axios
|
||||
.get(this.submitApiUri)
|
||||
.then(response => {
|
||||
console.log(response.data);
|
||||
Object.assign(this.formData, response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
newQuickRequest: function(params) {
|
||||
console.log(this.submitApiUri)
|
||||
console.log(params)
|
||||
console.log(this.submitApiUri);
|
||||
console.log(params);
|
||||
// Send a quick request
|
||||
axios.post(this.submitApiUri, params)
|
||||
.then(response => {
|
||||
axios
|
||||
.post(this.submitApiUri, params)
|
||||
.then(response => {
|
||||
// Do something with the response
|
||||
console.log(response)
|
||||
console.log(response);
|
||||
// Update the form data if we're self-updating
|
||||
if (this.selfUpdate) {
|
||||
this.getFormData()
|
||||
this.getFormData();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
onTaskSubmit: function(submitData) {
|
||||
// We don't need to do anything on this event yet
|
||||
console.log("onTaskSubmit event triggered")
|
||||
},
|
||||
onTaskSubmit: function() {},
|
||||
|
||||
onTaskResponse: function(responseData) {
|
||||
console.log("Task finished with response data: ", responseData)
|
||||
console.log("Task finished with response data: ", responseData);
|
||||
if (this.selfUpdate) {
|
||||
this.getFormData()
|
||||
this.getFormData();
|
||||
}
|
||||
},
|
||||
|
||||
onTaskError: function(error) {
|
||||
this.modalError(error)
|
||||
this.modalError(error);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
pluginApiUri: function () {
|
||||
return this.$store.getters.uri + "/plugin"
|
||||
},
|
||||
|
||||
submitApiUri: function () {
|
||||
return this.pluginApiUri + this.route
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
@ -214,6 +226,6 @@ export default {
|
|||
}
|
||||
|
||||
.flex-container > div {
|
||||
flex-basis: 100%
|
||||
flex-basis: 100%;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,40 +1,62 @@
|
|||
<template>
|
||||
<div class="hostCard uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium" v-bind:class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }">
|
||||
|
||||
<div
|
||||
class="hostCard uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium"
|
||||
:class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }"
|
||||
>
|
||||
<div class="uk-card-media-top">
|
||||
<div class="snapshot-container uk-width-1-1 uk-height-auto">
|
||||
<img class="uk-width-1-1" v-bind:data-src="snapshotSrc" width="300" height="225" uk-img>
|
||||
<div v-if="!snapshotAvailable" class="uk-position-cover uk-flex uk-flex-center uk-flex-middle">Snapshot unavailable</div>
|
||||
<img
|
||||
class="uk-width-1-1"
|
||||
:data-src="snapshotSrc"
|
||||
width="300"
|
||||
height="225"
|
||||
uk-img
|
||||
/>
|
||||
<div
|
||||
v-if="!snapshotAvailable"
|
||||
class="uk-position-cover uk-flex uk-flex-center uk-flex-middle"
|
||||
>
|
||||
Snapshot unavailable
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-card-body uk-padding-small">
|
||||
<div class="uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-flex uk-flex-middle">
|
||||
<div
|
||||
class="uk-margin-small uk-margin-remove-left uk-margin-remove-right uk-flex uk-flex-middle"
|
||||
>
|
||||
<div class="uk-width-expand host-description">
|
||||
<div class="host-description"><b>{{ name }}</b></div>
|
||||
<div class="host-description">
|
||||
<b>{{ name }}</b>
|
||||
</div>
|
||||
<div class="host-description">{{ hostname }}:{{ port }}</div>
|
||||
</div>
|
||||
<a href="#" v-on:click="$emit('delete')" class="uk-icon uk-width-auto host-delete"><i class="material-icons">delete</i></a>
|
||||
<a
|
||||
href="#"
|
||||
class="uk-icon uk-width-auto host-delete"
|
||||
@click="$emit('delete')"
|
||||
><i class="material-icons">delete</i></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-card-footer uk-padding-small">
|
||||
<button
|
||||
<button
|
||||
class="uk-button uk-button-default uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1"
|
||||
v-on:click="$emit('connect')"
|
||||
>Connect</button>
|
||||
@click="$emit('connect')"
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UIkit from 'uikit';
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'hostCard',
|
||||
name: "HostCard",
|
||||
|
||||
props: {
|
||||
name: {
|
||||
|
|
@ -51,23 +73,32 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
snapshotSrc: "",
|
||||
snapshotAvailable: false,
|
||||
polling: null
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
routesURL: function() {
|
||||
return `http://${this.hostname}:${this.port}/routes`;
|
||||
},
|
||||
snapshotURL: function() {
|
||||
return `http://${this.hostname}:${this.port}/api/v1/snapshot`;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Try to load the microscope snapshot when mounted
|
||||
this.checkSnapshotAvailable()
|
||||
this.checkSnapshotAvailable();
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
beforeDestroy() {
|
||||
// Clear the polling timer
|
||||
if (this.polling !== null) {
|
||||
clearInterval(this.polling)
|
||||
clearInterval(this.polling);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -77,52 +108,42 @@ export default {
|
|||
// a snapshot timer if the snapshot route is available
|
||||
|
||||
// Send tag request
|
||||
axios.get(this.routesURL)
|
||||
.then((response) => {
|
||||
// If the host has a snapshot route available
|
||||
if ("/api/v1/snapshot" in response.data) {
|
||||
// Tell the view that a snapshot is available
|
||||
this.snapshotAvailable = true
|
||||
// Update the snapshot URL
|
||||
this.updateSnapshotURL()
|
||||
// If not already polling, start polling
|
||||
if (this.polling === null) {
|
||||
this.updateSnapshotPoll()
|
||||
axios
|
||||
.get(this.routesURL)
|
||||
.then(response => {
|
||||
// If the host has a snapshot route available
|
||||
if ("/api/v1/snapshot" in response.data) {
|
||||
// Tell the view that a snapshot is available
|
||||
this.snapshotAvailable = true;
|
||||
// Update the snapshot URL
|
||||
this.updateSnapshotURL();
|
||||
// If not already polling, start polling
|
||||
if (this.polling === null) {
|
||||
this.updateSnapshotPoll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
.catch(error => {
|
||||
// Tell the view that a snapshot is not available, and ignore
|
||||
this.snapshotAvailable = false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
// Tell the view that a snapshot is not available, and ignore
|
||||
this.snapshotAvailable = false;
|
||||
});
|
||||
},
|
||||
|
||||
updateSnapshotURL: function() {
|
||||
// Set the snapshot image src to the snapshot URL,
|
||||
// adding a timestamp argument to act as a cache-breaker
|
||||
this.snapshotSrc = `${this.snapshotURL}?${Date.now()}`
|
||||
console.log(`Updating snapshot URL to ${this.snapshotSrc}`)
|
||||
this.snapshotSrc = `${this.snapshotURL}?${Date.now()}`;
|
||||
console.log(`Updating snapshot URL to ${this.snapshotSrc}`);
|
||||
},
|
||||
|
||||
updateSnapshotPoll: function() {
|
||||
// Start a timer to call updateSnapshotURL periodically
|
||||
this.polling = setInterval(() => {
|
||||
this.updateSnapshotURL()
|
||||
}, 15000)
|
||||
this.updateSnapshotURL();
|
||||
}, 15000);
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
routesURL: function () {
|
||||
return `http://${this.hostname}:${this.port}/routes`
|
||||
},
|
||||
snapshotURL: function () {
|
||||
return `http://${this.hostname}:${this.port}/api/v1/snapshot`
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
@ -135,8 +156,7 @@ export default {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
img[data-src][src*='data:image'] {
|
||||
background: rgba(127,127,127,0.1);
|
||||
img[data-src][src*="data:image"] {
|
||||
background: rgba(127, 127, 127, 0.1);
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,63 @@
|
|||
<template>
|
||||
<div class="connectDisplay uk-padding uk-padding-remove-left">
|
||||
|
||||
<div uk-grid class="uk-height-1-1 uk-margin-remove uk-padding-remove" margin=0>
|
||||
|
||||
<div class="connectDisplay uk-padding uk-padding-remove-left">
|
||||
<div
|
||||
uk-grid
|
||||
class="uk-height-1-1 uk-margin-remove uk-padding-remove"
|
||||
margin="0"
|
||||
>
|
||||
<div class="uk-width-auto">
|
||||
|
||||
<div class="uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium connect-card-align-top">
|
||||
|
||||
<div
|
||||
class="uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium connect-card-align-top"
|
||||
>
|
||||
<div class="uk-card-body uk-padding-small">
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="uk-form-controls uk-margin">
|
||||
<label><input class="uk-radio" type="radio" name="radio_local" v-model="computedLocalMode" v-bind:value="true"> Connect locally</label><br>
|
||||
<label><input class="uk-radio" type="radio" name="radio_local" v-model="computedLocalMode" v-bind:value="false" checked> Connect remotely</label>
|
||||
<label
|
||||
><input
|
||||
v-model="computedLocalMode"
|
||||
class="uk-radio"
|
||||
type="radio"
|
||||
name="radio_local"
|
||||
:value="true"
|
||||
/>
|
||||
Connect locally</label
|
||||
><br />
|
||||
<label
|
||||
><input
|
||||
v-model="computedLocalMode"
|
||||
class="uk-radio"
|
||||
type="radio"
|
||||
name="radio_local"
|
||||
:value="false"
|
||||
checked
|
||||
/>
|
||||
Connect remotely</label
|
||||
>
|
||||
</div>
|
||||
<div v-if="!localMode">
|
||||
<div class="uk-inline uk-width-1-1">
|
||||
<span class="uk-form-icon"><i class="material-icons">dns</i></span>
|
||||
<input v-model="hostname" v-bind:class="IpFormClasses" class="uk-input uk-form-small" type="text" placeholder="Hostname or IP address">
|
||||
<span class="uk-form-icon"
|
||||
><i class="material-icons">dns</i></span
|
||||
>
|
||||
<input
|
||||
v-model="hostname"
|
||||
:class="IpFormClasses"
|
||||
class="uk-input uk-form-small"
|
||||
type="text"
|
||||
placeholder="Hostname or IP address"
|
||||
/>
|
||||
</div>
|
||||
<label class="uk-form-label" for="form-stacked-text">Port</label>
|
||||
<label class="uk-form-label" for="form-stacked-text"
|
||||
>Port</label
|
||||
>
|
||||
<div class="uk-form-controls">
|
||||
<input v-model="computedPort" class="uk-input uk-form-small" id="form-stacked-text" type="number" value=5000>
|
||||
<input
|
||||
id="form-stacked-text"
|
||||
v-model="computedPort"
|
||||
class="uk-input uk-form-small"
|
||||
type="number"
|
||||
value="5000"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
@ -28,102 +65,90 @@
|
|||
|
||||
<div class="uk-card-footer uk-padding-small">
|
||||
<button
|
||||
v-on:click="handleSubmit"
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1">
|
||||
class="uk-button uk-button-primary uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="$store.getters.ready"
|
||||
v-on:click="saveHost()"
|
||||
class="uk-button uk-button-default uk-form-small uk-margin-small uk-width-1-1">
|
||||
<button
|
||||
v-if="$store.getters.ready"
|
||||
class="uk-button uk-button-default uk-form-small uk-margin-small uk-width-1-1"
|
||||
@click="saveHost()"
|
||||
>
|
||||
Save Current
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-if="$store.getters.ready"
|
||||
v-on:click="$store.commit('resetState')"
|
||||
class="uk-button uk-button-danger uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1">
|
||||
<button
|
||||
v-if="$store.getters.ready"
|
||||
class="uk-button uk-button-danger uk-form-small uk-float-right uk-margin uk-margin-remove-top uk-width-1-1"
|
||||
@click="$store.commit('resetState')"
|
||||
>
|
||||
Disconnect
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-width-expand">
|
||||
<ul uk-accordion="multiple: true; animation: false">
|
||||
|
||||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Saved devices</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<div class="uk-grid-medium uk-grid-match uk-margin-top" uk-grid>
|
||||
|
||||
<div v-for="host in savedHosts" :key="host.name">
|
||||
<hostCard
|
||||
:name="host.name"
|
||||
:hostname="host.hostname"
|
||||
<hostCard
|
||||
:name="host.name"
|
||||
:hostname="host.hostname"
|
||||
:port="host.port"
|
||||
v-on:connect="handleConnectButton(host)"
|
||||
v-on:delete="delSavedHost(host)"
|
||||
@connect="handleConnectButton(host)"
|
||||
@delete="delSavedHost(host)"
|
||||
></hostCard>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Nearby devices</a>
|
||||
<div class="uk-accordion-content">
|
||||
|
||||
<div class="uk-grid-medium uk-grid-match uk-margin-top" uk-grid>
|
||||
|
||||
<div v-for="host in foundHostArray" :key="host.name">
|
||||
<hostCard
|
||||
:name="host.name"
|
||||
:hostname="host.hostname"
|
||||
<hostCard
|
||||
:name="host.name"
|
||||
:hostname="host.hostname"
|
||||
:port="host.port"
|
||||
:deletable="false"
|
||||
v-on:connect="handleConnectButton(host)"
|
||||
@connect="handleConnectButton(host)"
|
||||
></hostCard>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { version } from 'punycode';
|
||||
|
||||
// Import mDNS package if running in Electron
|
||||
import isElectron from '../../modules/isElectron';
|
||||
import isElectron from "../../modules/isElectron";
|
||||
if (isElectron()) {
|
||||
var mdns = require('mdns-js');
|
||||
var mdns = require("mdns-js");
|
||||
}
|
||||
|
||||
import hostCard from './connectComponents/hostCard.vue'
|
||||
import hostCard from "./connectComponents/hostCard.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'connectDisplay',
|
||||
name: "ConnectDisplay",
|
||||
|
||||
components: {
|
||||
hostCard
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
localMode: true,
|
||||
hostname: "",
|
||||
|
|
@ -131,161 +156,205 @@ export default {
|
|||
selectedHost: "",
|
||||
savedHosts: [],
|
||||
foundHosts: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
foundHostArray: function() {
|
||||
return Object.values(this.foundHosts);
|
||||
},
|
||||
// Stylises the hostname input box based on connection status
|
||||
IpFormClasses: function() {
|
||||
return {
|
||||
"uk-form-danger": !this.$store.state.available,
|
||||
"uk-form-success": this.$store.getters.ready
|
||||
};
|
||||
},
|
||||
|
||||
computedLocalMode: {
|
||||
get: function() {
|
||||
return this.localMode;
|
||||
},
|
||||
set: function(state) {
|
||||
this.localMode = state;
|
||||
this.setLocalMode(state);
|
||||
}
|
||||
},
|
||||
|
||||
computedPort: {
|
||||
get: function() {
|
||||
if (this.hostname.includes(":")) {
|
||||
var port = parseInt(this.hostname.split(":")[1]);
|
||||
return !isNaN(port) ? port : this.port;
|
||||
} else {
|
||||
return this.port;
|
||||
}
|
||||
},
|
||||
set: function(newPort) {
|
||||
this.port = newPort;
|
||||
if (this.hostname.includes(":")) {
|
||||
this.hostname = this.hostname.split(":")[0] + ":" + this.port;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// When savedHosts changes, serialise to JSON and save to localStorage
|
||||
watch: {
|
||||
savedHosts() {
|
||||
this.setLocalStorageObj("savedHosts", this.savedHosts);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// Propagate localMode settings
|
||||
this.setLocalMode(this.localMode)
|
||||
this.setLocalMode(this.localMode);
|
||||
|
||||
// Try loading savedHosts from localStorage. If null, don't change.
|
||||
this.savedHosts = this.getLocalStorageObj('savedHosts') || this.savedHosts
|
||||
this.savedHosts = this.getLocalStorageObj("savedHosts") || this.savedHosts;
|
||||
|
||||
// Handle mDNS browsing
|
||||
if (mdns) {
|
||||
// TODO: Have this run periodically on a timer
|
||||
|
||||
// Create a browser to search for 'openflexure' type services
|
||||
var browser = mdns.createBrowser(mdns.tcp('openflexure'));
|
||||
var browser = mdns.createBrowser(mdns.tcp("openflexure"));
|
||||
|
||||
// Start discovering services when ready
|
||||
browser.on('ready', function () {
|
||||
browser.discover();
|
||||
browser.on("ready", function() {
|
||||
browser.discover();
|
||||
});
|
||||
|
||||
browser.on('update', (data) => {
|
||||
console.log(data)
|
||||
browser.on("update", data => {
|
||||
console.log(data);
|
||||
|
||||
// We will be checking if it's a valid openflexure device
|
||||
var validDevice = false
|
||||
var validDevice = false;
|
||||
|
||||
// Go through each type of the host, make valid if 'openflexure' appears
|
||||
data.type.forEach((element) => {
|
||||
console.log(element)
|
||||
data.type.forEach(element => {
|
||||
console.log(element);
|
||||
if (element.name === "openflexure") {
|
||||
validDevice = true
|
||||
validDevice = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var hostData = {
|
||||
hostname: data.addresses[0],
|
||||
name: `${data.host} on ${data.networkInterface}`,
|
||||
port: data.port
|
||||
};
|
||||
|
||||
if (typeof data.port !== "undefined" && validDevice === true) {
|
||||
this.$set(this.foundHosts, hostData.hostname, hostData);
|
||||
}
|
||||
|
||||
if ((typeof data.port !== "undefined") && (validDevice === true)) {
|
||||
this.$set(this.foundHosts, hostData.hostname, hostData)
|
||||
}
|
||||
|
||||
console.log(this.foundHosts)
|
||||
console.log(this.foundHosts);
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// When savedHosts changes, serialise to JSON and save to localStorage
|
||||
watch: {
|
||||
savedHosts(newSavedHosts) {
|
||||
this.setLocalStorageObj('savedHosts', this.savedHosts)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
connectToHost: function(host) {
|
||||
console.log(host)
|
||||
console.log(host);
|
||||
// Set the global form values
|
||||
this.hostname = host.hostname
|
||||
this.port = host.port
|
||||
|
||||
this.hostname = host.hostname;
|
||||
this.port = host.port;
|
||||
|
||||
// Commit the hostname and port to store
|
||||
this.$store.commit('changeHost', [
|
||||
host.hostname,
|
||||
host.port
|
||||
]);
|
||||
this.$store.commit("changeHost", [host.hostname, host.port]);
|
||||
// Try to get config and state JSON from the newly submitted host
|
||||
this.$store.dispatch('firstConnect')
|
||||
.then (() => {
|
||||
console.log("Connected!")
|
||||
// Check client and server match
|
||||
this.checkServerVersion()
|
||||
// Switch to live view tab
|
||||
this.$root.$emit('globalTogglePanelRightTab', 'preview')
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
this.$store
|
||||
.dispatch("firstConnect")
|
||||
.then(() => {
|
||||
console.log("Connected!");
|
||||
// Check client and server match
|
||||
this.checkServerVersion();
|
||||
// Switch to live view tab
|
||||
this.$root.$emit("globalTogglePanelRightTab", "preview");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
handleSubmit: function(event) {
|
||||
handleSubmit: function() {
|
||||
// Split host and port if needed
|
||||
if (this.hostname.includes(':')) {
|
||||
if (this.hostname.includes(":")) {
|
||||
this.port = this.computedPort;
|
||||
this.hostname = this.hostname.split(':')[0];
|
||||
this.hostname = this.hostname.split(":")[0];
|
||||
}
|
||||
|
||||
// Handle auto-local-connect
|
||||
var hostname;
|
||||
if (this.localMode) {
|
||||
var hostname = "localhost";
|
||||
}
|
||||
else {
|
||||
var hostname = this.hostname;
|
||||
hostname = "localhost";
|
||||
} else {
|
||||
hostname = this.hostname;
|
||||
}
|
||||
|
||||
var selectedHost = {
|
||||
hostname: hostname,
|
||||
port: this.port
|
||||
}
|
||||
};
|
||||
|
||||
this.connectToHost(selectedHost)
|
||||
this.connectToHost(selectedHost);
|
||||
},
|
||||
|
||||
handleConnectButton: function(host) {
|
||||
this.computedLocalMode = false
|
||||
this.connectToHost(host)
|
||||
this.computedLocalMode = false;
|
||||
this.connectToHost(host);
|
||||
},
|
||||
|
||||
checkServerVersion: function () {
|
||||
this.$store.dispatch('updateState')
|
||||
.then (() => {
|
||||
var clientVersion = process.env.PACKAGE.version
|
||||
var clientVersionMajor = clientVersion.substring(0, 3)
|
||||
console.log(clientVersionMajor)
|
||||
checkServerVersion: function() {
|
||||
this.$store
|
||||
.dispatch("updateState")
|
||||
.then(() => {
|
||||
var clientVersion = process.env.PACKAGE.version;
|
||||
var clientVersionMajor = clientVersion.substring(0, 3);
|
||||
console.log(clientVersionMajor);
|
||||
|
||||
var serverVersion = this.$store.state.apiState.version
|
||||
if (serverVersion != undefined) {
|
||||
var serverVersionMajor = serverVersion.substring(0, 3)
|
||||
}
|
||||
console.log(serverVersionMajor)
|
||||
var serverVersion = this.$store.state.apiState.version;
|
||||
if (serverVersion != undefined) {
|
||||
var serverVersionMajor = serverVersion.substring(0, 3);
|
||||
}
|
||||
console.log(serverVersionMajor);
|
||||
|
||||
if ((serverVersion == undefined) || (serverVersionMajor != clientVersionMajor)) {
|
||||
var versionWarning = `Client and microscope versions do not match.\
|
||||
if (
|
||||
serverVersion == undefined ||
|
||||
serverVersionMajor != clientVersionMajor
|
||||
) {
|
||||
var versionWarning = `Client and microscope versions do not match.\
|
||||
Consider updating your microscope software.\
|
||||
Some functionality may currently be broken.<br><br> \
|
||||
<b>Client version:</b> ${clientVersion}<br> \
|
||||
<b>Server version:</b> ${serverVersion}<br><br>`
|
||||
if (serverVersion < 1.1) {
|
||||
versionWarning = versionWarning + "You may need to install a never server version on a clean SD card."
|
||||
<b>Server version:</b> ${serverVersion}<br><br>`;
|
||||
if (serverVersion < 1.1) {
|
||||
versionWarning =
|
||||
versionWarning +
|
||||
"You may need to install a never server version on a clean SD card.";
|
||||
} else {
|
||||
versionWarning =
|
||||
versionWarning +
|
||||
"Try running 'ofm upgrade' on your microscope.";
|
||||
}
|
||||
this.modalDialog("Version mismatch", versionWarning);
|
||||
}
|
||||
else {
|
||||
versionWarning = versionWarning + "Try running 'ofm upgrade' on your microscope."
|
||||
}
|
||||
this.modalDialog("Version mismatch", versionWarning, status='warning')
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
setLocalMode: function (state) {
|
||||
this.$store.commit("changeSetting", ['trackWindow', state]);
|
||||
this.$store.commit("changeSetting", ['disableStream', state]);
|
||||
this.$store.commit("changeSetting", ['autoGpuPreview', state]);
|
||||
setLocalMode: function(state) {
|
||||
this.$store.commit("changeSetting", ["trackWindow", state]);
|
||||
this.$store.commit("changeSetting", ["disableStream", state]);
|
||||
this.$store.commit("changeSetting", ["autoGpuPreview", state]);
|
||||
//this.$root.$emit('globalTogglePreview', state)
|
||||
},
|
||||
|
||||
delSavedHost: function (host) {
|
||||
console.log(host)
|
||||
delSavedHost: function(host) {
|
||||
console.log(host);
|
||||
var index = this.savedHosts.indexOf(host);
|
||||
if (index > -1) {
|
||||
this.savedHosts.splice(index, 1);
|
||||
|
|
@ -294,67 +363,19 @@ export default {
|
|||
|
||||
saveHost: function() {
|
||||
// We use unshift instead of push to add the entry to the beginning of the array
|
||||
this.savedHosts.unshift(
|
||||
{
|
||||
name: this.$store.state.apiConfig.name,
|
||||
hostname: this.$store.state.host,
|
||||
port: this.$store.state.port
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
foundHostArray: function () {
|
||||
return Object.values(this.foundHosts)
|
||||
},
|
||||
// Stylises the hostname input box based on connection status
|
||||
IpFormClasses: function () {
|
||||
return {
|
||||
'uk-form-danger': !this.$store.state.available,
|
||||
'uk-form-success': this.$store.getters.ready
|
||||
}
|
||||
},
|
||||
|
||||
computedLocalMode: {
|
||||
get: function() {
|
||||
return this.localMode
|
||||
},
|
||||
set: function(state) {
|
||||
this.localMode = state;
|
||||
this.setLocalMode(state)
|
||||
}
|
||||
},
|
||||
|
||||
computedPort: {
|
||||
get: function() {
|
||||
if (this.hostname.includes(':')) {
|
||||
var port = parseInt(this.hostname.split(':')[1]);
|
||||
return !isNaN(port) ? port : this.port
|
||||
}
|
||||
else {
|
||||
return this.port
|
||||
}
|
||||
},
|
||||
set: function(newPort) {
|
||||
this.port = newPort
|
||||
if (this.hostname.includes(':')) {
|
||||
this.hostname = this.hostname.split(':')[0] + ":" + this.port
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
this.savedHosts.unshift({
|
||||
name: this.$store.state.apiConfig.name,
|
||||
hostname: this.$store.state.host,
|
||||
port: this.$store.state.port
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="less">
|
||||
|
||||
.connect-card-align-top {
|
||||
margin-top: 52px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,86 +1,137 @@
|
|||
<template>
|
||||
<div class="captureCard uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium" v-bind:class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }">
|
||||
|
||||
<div
|
||||
class="captureCard uk-card uk-card-default uk-card-hover uk-padding-remove uk-width-medium"
|
||||
:class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }"
|
||||
>
|
||||
<div class="uk-card-media-top">
|
||||
<a class="lightbox-link" v-bind:href="imgURL" v-bind:data-caption="metadata.filename">
|
||||
<img class="uk-width-1-1" v-bind:data-src="thumbURL" v-bind:alt="metadata.id" width="300" height="225" uk-img>
|
||||
<a class="lightbox-link" :href="imgURL" :data-caption="metadata.filename">
|
||||
<img
|
||||
class="uk-width-1-1"
|
||||
:data-src="thumbURL"
|
||||
:alt="metadata.id"
|
||||
width="300"
|
||||
height="225"
|
||||
uk-img
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="uk-card-body uk-padding-small">
|
||||
<div class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right" uk-grid>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-expand">{{ metadata.filename }}</div>
|
||||
<div
|
||||
class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right"
|
||||
uk-grid
|
||||
>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-expand">
|
||||
{{ metadata.filename }}
|
||||
</div>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-auto">
|
||||
<a href="#" v-on:click="delCaptureConfirm()" class="uk-icon">
|
||||
<a href="#" class="uk-icon" @click="delCaptureConfirm()">
|
||||
<i class="material-icons">delete</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand"><time>{{ betterTimestring }}</time></div>
|
||||
<div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto">
|
||||
<a v-bind:href="metadataModalTarget" uk-toggle>More...</a>
|
||||
<div
|
||||
class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand"
|
||||
>
|
||||
<time>{{ betterTimestring }}</time>
|
||||
</div>
|
||||
<div
|
||||
class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto"
|
||||
>
|
||||
<a :href="metadataModalTarget" uk-toggle>More...</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="uk-card-footer uk-padding-small">
|
||||
<div v-for="tag in tags" :key="tag">
|
||||
<span v-if="tag==='temporary'" class="uk-label uk-label-danger uk-margin-small-right" uk-tooltip="title: Capture will be removed automatically; delay: 500">Temporary</span>
|
||||
<span v-else v-on:click="delTagConfirm(tag)" class="uk-label uk-margin-small-right deletable-label"> {{ tag }} </span>
|
||||
<span
|
||||
v-if="tag === 'temporary'"
|
||||
class="uk-label uk-label-danger uk-margin-small-right"
|
||||
uk-tooltip="title: Capture will be removed automatically; delay: 500"
|
||||
>Temporary</span
|
||||
>
|
||||
<span
|
||||
v-else
|
||||
class="uk-label uk-margin-small-right deletable-label"
|
||||
@click="delTagConfirm(tag)"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a v-bind:href="tagModalTarget" uk-toggle>
|
||||
<a :href="tagModalTarget" uk-toggle>
|
||||
<span class="uk-label uk-label-success uk-margin-small-right">Add</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-bind:id="metadataModalID" uk-modal>
|
||||
<div :id="metadataModalID" uk-modal>
|
||||
<div
|
||||
class="uk-modal-dialog uk-modal-body"
|
||||
:class="{
|
||||
'uk-light uk-background-secondary':
|
||||
$store.state.globalSettings.darkMode
|
||||
}"
|
||||
>
|
||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||
<h2 class="uk-modal-title">{{ metadata.filename }}</h2>
|
||||
<p><b>Path: </b>{{ path }}</p>
|
||||
<p><b>Time: </b>{{ betterTimestring }}</p>
|
||||
<p><b>ID: </b>{{ metadata.id }}</p>
|
||||
<p><b>Format: </b>{{ metadata.format }}</p>
|
||||
|
||||
<div class="uk-modal-dialog uk-modal-body" v-bind:class="{ 'uk-light uk-background-secondary': $store.state.globalSettings.darkMode }" >
|
||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||
<h2 class="uk-modal-title">{{ metadata.filename }}</h2>
|
||||
<p><b>Path: </b>{{ path }}</p>
|
||||
<p><b>Time: </b>{{ betterTimestring }}</p>
|
||||
<p><b>ID: </b>{{ metadata.id }}</p>
|
||||
<p><b>Format: </b>{{ metadata.format }}</p>
|
||||
|
||||
<div v-for="(value, key) in metadata.custom" :key="key" >
|
||||
<p><b>{{ key }}: </b>{{ value }}</p>
|
||||
</div>
|
||||
<div v-for="(value, key) in metadata.custom" :key="key">
|
||||
<p>
|
||||
<b>{{ key }}: </b>{{ value }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-bind:id="tagModalID" uk-modal>
|
||||
|
||||
<form class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical" v-bind:class="{ 'uk-light uk-background-secondary': $store.state.globalSettings.darkMode }" @submit.prevent="handleTagSubmit">
|
||||
|
||||
<div class="uk-inline">
|
||||
<span class="uk-form-icon"><i class="material-icons">label</i></span>
|
||||
<input v-model="newtag" class="uk-input uk-form-width-medium uk-form-small" type="text" name="tagname" placeholder="tag">
|
||||
|
||||
<button class="uk-button uk-button-default uk-margin-left uk-form-small uk-modal-close" type="button">Cancel</button>
|
||||
<button type="submit" class="uk-button uk-button-primary uk-margin-left uk-form-small">Save</button>
|
||||
</div>
|
||||
<div :id="tagModalID" uk-modal>
|
||||
<form
|
||||
class="uk-modal-dialog uk-modal-body uk-margin-auto-vertical"
|
||||
:class="{
|
||||
'uk-light uk-background-secondary':
|
||||
$store.state.globalSettings.darkMode
|
||||
}"
|
||||
@submit.prevent="handleTagSubmit"
|
||||
>
|
||||
<div class="uk-inline">
|
||||
<span class="uk-form-icon"><i class="material-icons">label</i></span>
|
||||
<input
|
||||
v-model="newtag"
|
||||
class="uk-input uk-form-width-medium uk-form-small"
|
||||
type="text"
|
||||
name="tagname"
|
||||
placeholder="tag"
|
||||
/>
|
||||
|
||||
<button
|
||||
class="uk-button uk-button-default uk-margin-left uk-form-small uk-modal-close"
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="uk-button uk-button-primary uk-margin-left uk-form-small"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UIkit from 'uikit';
|
||||
import axios from 'axios'
|
||||
import UIkit from "uikit";
|
||||
import axios from "axios";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'captureCard',
|
||||
name: "CaptureCard",
|
||||
|
||||
props: {
|
||||
metadata: {
|
||||
|
|
@ -93,11 +144,48 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
tags: [],
|
||||
newtag: "",
|
||||
}
|
||||
newtag: ""
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
tagModalID: function() {
|
||||
return this.makeModalName("tag-modal-");
|
||||
},
|
||||
tagModalTarget: function() {
|
||||
return "#" + this.tagModalID;
|
||||
},
|
||||
metadataModalID: function() {
|
||||
return this.makeModalName("metadata-modal-");
|
||||
},
|
||||
metadataModalTarget: function() {
|
||||
return "#" + this.metadataModalID;
|
||||
},
|
||||
thumbURL: function() {
|
||||
return this.captureURL + "/download?thumbnail=true";
|
||||
},
|
||||
imgURL: function() {
|
||||
return this.captureURL + "/download/" + this.metadata.filename;
|
||||
},
|
||||
tagURL: function() {
|
||||
return this.captureURL + "/tags";
|
||||
},
|
||||
captureURL: function() {
|
||||
return this.$store.getters.uri + "/camera/capture/" + this.metadata.id;
|
||||
},
|
||||
betterTimestring: function() {
|
||||
var dtSplit = this.metadata.time.split("_");
|
||||
var date = dtSplit[0];
|
||||
var time = dtSplit[1].replace(/-/g, ":");
|
||||
return date + " " + time;
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
this.getTagRequest();
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
@ -106,114 +194,78 @@ export default {
|
|||
console.log(this.newtag);
|
||||
this.newTagRequest(this.newtag);
|
||||
this.newtag = "";
|
||||
UIkit.modal(event.target.parentNode).hide(); // TODO: Remove somehow
|
||||
UIkit.modal(event.target.parentNode).hide(); // TODO: Remove somehow
|
||||
},
|
||||
|
||||
delCaptureConfirm: function(tag_string) {
|
||||
var context = this
|
||||
this.modalConfirm('Permanantly delete capture?')
|
||||
.then(function() {
|
||||
context.delCaptureRequest()
|
||||
delCaptureConfirm: function() {
|
||||
var context = this;
|
||||
this.modalConfirm("Permanantly delete capture?").then(function() {
|
||||
context.delCaptureRequest();
|
||||
});
|
||||
},
|
||||
|
||||
delCaptureRequest: function() {
|
||||
// Send tag DELETE request
|
||||
axios.delete(this.captureURL)
|
||||
.then(response => {
|
||||
// Emit signal to update capture list
|
||||
this.$root.$emit('globalUpdateCaptureList')
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
axios
|
||||
.delete(this.captureURL)
|
||||
.then(() => {
|
||||
// Emit signal to update capture list
|
||||
this.$root.$emit("globalUpdateCaptureList");
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
newTagRequest: function(tag_string) {
|
||||
// Send tag PUT request
|
||||
axios.put(this.tagURL, [tag_string])
|
||||
.then(response => {
|
||||
// Update tag array
|
||||
this.getTagRequest()
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
axios
|
||||
.put(this.tagURL, [tag_string])
|
||||
.then(() => {
|
||||
// Update tag array
|
||||
this.getTagRequest();
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
delTagConfirm: function(tag_string) {
|
||||
var context = this;
|
||||
this.modalConfirm(`Remove tag '${tag_string}'?`).then(function() {
|
||||
context.delTagRequest(tag_string)
|
||||
context.delTagRequest(tag_string);
|
||||
});
|
||||
},
|
||||
|
||||
delTagRequest: function(tag_string) {
|
||||
console.log(tag_string)
|
||||
console.log(tag_string);
|
||||
// Send tag DELETE request
|
||||
axios.delete(this.tagURL, {data: [tag_string]})
|
||||
.then(response => {
|
||||
// Update tag array
|
||||
this.getTagRequest()
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
axios
|
||||
.delete(this.tagURL, { data: [tag_string] })
|
||||
.then(() => {
|
||||
// Update tag array
|
||||
this.getTagRequest();
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
getTagRequest: function() {
|
||||
// Send tag request
|
||||
axios.get(this.tagURL)
|
||||
.then(response => {
|
||||
this.tags = response.data.metadata.tags
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
axios
|
||||
.get(this.tagURL)
|
||||
.then(response => {
|
||||
this.tags = response.data.metadata.tags;
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
makeModalName: function(prefix) {
|
||||
return prefix + this.metadata.id
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this.getTagRequest()
|
||||
},
|
||||
|
||||
computed: {
|
||||
tagModalID: function () {
|
||||
return this.makeModalName("tag-modal-")
|
||||
},
|
||||
tagModalTarget: function () {
|
||||
return "#" + this.tagModalID
|
||||
},
|
||||
metadataModalID: function () {
|
||||
return this.makeModalName("metadata-modal-")
|
||||
},
|
||||
metadataModalTarget: function () {
|
||||
return "#" + this.metadataModalID
|
||||
},
|
||||
thumbURL: function () {
|
||||
return this.captureURL + "/download?thumbnail=true"
|
||||
},
|
||||
imgURL: function () {
|
||||
return this.captureURL + "/download/" + this.metadata.filename
|
||||
},
|
||||
tagURL: function () {
|
||||
return this.captureURL + "/tags"
|
||||
},
|
||||
captureURL: function () {
|
||||
return this.$store.getters.uri + "/camera/capture/" + this.metadata.id
|
||||
},
|
||||
betterTimestring: function () {
|
||||
var dtSplit = this.metadata.time.split("_");
|
||||
var date = dtSplit[0]
|
||||
var time = dtSplit[1].replace(/-/g, ":")
|
||||
return date + " " + time
|
||||
return prefix + this.metadata.id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,54 +1,76 @@
|
|||
<template>
|
||||
<div class="captureCard uk-card uk-card-primary uk-card-hover uk-padding-remove uk-width-medium">
|
||||
|
||||
<div
|
||||
class="captureCard uk-card uk-card-primary uk-card-hover uk-padding-remove uk-width-medium"
|
||||
>
|
||||
<div class="uk-card-media-top">
|
||||
|
||||
<a href="#" >
|
||||
<img class="uk-width-1-1" v-bind:data-src="thumbnail" v-bind:alt="metadata.scan_id" width="300" height="225" v-on:click="$root.$emit('globalUpdateCaptureFolder', metadata.custom.scan_id)" uk-img>
|
||||
<a href="#">
|
||||
<img
|
||||
class="uk-width-1-1"
|
||||
:data-src="thumbnail"
|
||||
:alt="metadata.scan_id"
|
||||
width="300"
|
||||
height="225"
|
||||
uk-img
|
||||
@click="
|
||||
$root.$emit('globalUpdateCaptureFolder', metadata.custom.scan_id)
|
||||
"
|
||||
/>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="uk-card-body uk-padding-small">
|
||||
<div class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right" uk-grid>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-expand"><b>Scan:</b> {{ metadata.custom.basename }}</div>
|
||||
<div
|
||||
class="uk-width-1-1 uk-margin-small uk-margin-remove-left uk-margin-remove-right"
|
||||
uk-grid
|
||||
>
|
||||
<div class="uk-margin-remove-top uk-padding-remove uk-width-expand">
|
||||
<b>Scan:</b> {{ metadata.custom.basename }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand"><time>{{ betterTimestring }}</time></div>
|
||||
<div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto">
|
||||
<a v-bind:href="metadataModalTarget" uk-toggle>More...</a>
|
||||
<div
|
||||
class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand"
|
||||
>
|
||||
<time>{{ betterTimestring }}</time>
|
||||
</div>
|
||||
<div
|
||||
class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto"
|
||||
>
|
||||
<a :href="metadataModalTarget" uk-toggle>More...</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="uk-card-footer uk-padding-small">
|
||||
<span v-for="tag in metadata.tags" :key="tag" class="uk-label uk-margin-small-right deletable-label"> {{ tag }} </span>
|
||||
<span
|
||||
v-for="tag in metadata.tags"
|
||||
:key="tag"
|
||||
class="uk-label uk-margin-small-right deletable-label"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-bind:id="metadataModalID" uk-modal>
|
||||
|
||||
<div :id="metadataModalID" uk-modal>
|
||||
<div class="uk-modal-dialog uk-modal-body">
|
||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||
<h2 class="uk-modal-title">{{ metadata.basename }}</h2>
|
||||
<p><b>Time: </b>{{ betterTimestring }}</p>
|
||||
<p><b>Scan ID: </b>{{ metadata.custom.scan_id }}</p>
|
||||
|
||||
<div v-for="(value, key) in metadata.custom" :key="key" >
|
||||
<p><b>{{ key }}: </b>{{ value }}</p>
|
||||
<div v-for="(value, key) in metadata.custom" :key="key">
|
||||
<p>
|
||||
<b>{{ key }}: </b>{{ value }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'captureCard',
|
||||
name: "CaptureCard",
|
||||
|
||||
props: {
|
||||
metadata: {
|
||||
|
|
@ -61,33 +83,31 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
makeModalName: function(prefix) {
|
||||
return prefix + this.metadata.id
|
||||
computed: {
|
||||
tagModalID: function() {
|
||||
return this.makeModalName("tag-modal-");
|
||||
},
|
||||
tagModalTarget: function() {
|
||||
return "#" + this.tagModalID;
|
||||
},
|
||||
metadataModalID: function() {
|
||||
return this.makeModalName("metadata-modal-");
|
||||
},
|
||||
metadataModalTarget: function() {
|
||||
return "#" + this.metadataModalID;
|
||||
},
|
||||
betterTimestring: function() {
|
||||
var dtSplit = this.metadata.custom.time.split("_");
|
||||
var date = dtSplit[0];
|
||||
var time = dtSplit[1].replace(/-/g, ":");
|
||||
return date + " " + time;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
tagModalID: function () {
|
||||
return this.makeModalName("tag-modal-")
|
||||
},
|
||||
tagModalTarget: function () {
|
||||
return "#" + this.tagModalID
|
||||
},
|
||||
metadataModalID: function () {
|
||||
return this.makeModalName("metadata-modal-")
|
||||
},
|
||||
metadataModalTarget: function () {
|
||||
return "#" + this.metadataModalID
|
||||
},
|
||||
betterTimestring: function () {
|
||||
var dtSplit = this.metadata.custom.time.split("_");
|
||||
var date = dtSplit[0]
|
||||
var time = dtSplit[1].replace(/-/g, ":")
|
||||
return date + " " + time
|
||||
methods: {
|
||||
makeModalName: function(prefix) {
|
||||
return prefix + this.metadata.id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,108 +1,255 @@
|
|||
<template>
|
||||
<div class="galleryDisplay uk-padding uk-padding-remove-top">
|
||||
|
||||
<nav class="uk-navbar-container uk-navbar-transparent navbar" uk-navbar="mode: click">
|
||||
<div class="uk-navbar-left uk-padding-remove-top uk-padding-remove-bottom">
|
||||
<ul class="uk-navbar-nav">
|
||||
<li v-bind:class="[sortDescending ? 'uk-active' : '']"><a v-on:click="sortDescending=true;" class="uk-icon" href="#"><i class="material-icons">keyboard_arrow_down</i></a></li>
|
||||
<li v-bind:class="[!sortDescending ? 'uk-active' : '']"><a v-on:click="sortDescending=false;" class="uk-icon" href="#"><i class="material-icons">keyboard_arrow_up</i></a></li>
|
||||
<li>
|
||||
<a href="#">Filter</a>
|
||||
<div class="uk-navbar-dropdown" v-bind:class="{ 'uk-light uk-background-secondary': $store.state.globalSettings.darkMode }">
|
||||
<ul class="uk-nav uk-navbar-dropdown-nav">
|
||||
<form class="uk-form-stacked">
|
||||
<div v-for="tag in allTags" :key="tag" class="uk-margin-small">
|
||||
<label><input class="uk-checkbox" type="checkbox" v-bind:id="tag" v-bind:value="tag" v-model="checkedTags" checked> {{ tag }}</label>
|
||||
</div>
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="galleryDisplay uk-padding uk-padding-remove-top">
|
||||
<nav
|
||||
class="uk-navbar-container uk-navbar-transparent navbar"
|
||||
uk-navbar="mode: click"
|
||||
>
|
||||
<div
|
||||
class="uk-navbar-left uk-padding-remove-top uk-padding-remove-bottom"
|
||||
>
|
||||
<ul class="uk-navbar-nav">
|
||||
<li :class="[sortDescending ? 'uk-active' : '']">
|
||||
<a class="uk-icon" href="#" @click="sortDescending = true"
|
||||
><i class="material-icons">keyboard_arrow_down</i></a
|
||||
>
|
||||
</li>
|
||||
<li :class="[!sortDescending ? 'uk-active' : '']">
|
||||
<a class="uk-icon" href="#" @click="sortDescending = false"
|
||||
><i class="material-icons">keyboard_arrow_up</i></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Filter</a>
|
||||
<div
|
||||
class="uk-navbar-dropdown"
|
||||
:class="{
|
||||
'uk-light uk-background-secondary':
|
||||
$store.state.globalSettings.darkMode
|
||||
}"
|
||||
>
|
||||
<ul class="uk-nav uk-navbar-dropdown-nav">
|
||||
<form class="uk-form-stacked">
|
||||
<div
|
||||
v-for="tag in allTags"
|
||||
:key="tag"
|
||||
class="uk-margin-small"
|
||||
>
|
||||
<label
|
||||
><input
|
||||
:id="tag"
|
||||
v-model="checkedTags"
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
:value="tag"
|
||||
checked
|
||||
/>
|
||||
{{ tag }}</label
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div v-if="$store.getters.ready" class="uk-padding-remove-top" uk-lightbox="toggle: .lightbox-link">
|
||||
|
||||
<div v-if="(galleryFolder)" class="uk-flex uk-flex-middle uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom">
|
||||
<a href="#" v-on:click="galleryFolder=''" class="uk-icon uk-margin-remove"><i class="material-icons">arrow_back</i></a>
|
||||
<div
|
||||
v-if="$store.getters.ready"
|
||||
class="uk-padding-remove-top"
|
||||
uk-lightbox="toggle: .lightbox-link"
|
||||
>
|
||||
<div
|
||||
v-if="galleryFolder"
|
||||
class="uk-flex uk-flex-middle uk-padding uk-padding-remove-horizontal uk-padding-remove-bottom"
|
||||
>
|
||||
<a href="#" class="uk-icon uk-margin-remove" @click="galleryFolder = ''"
|
||||
><i class="material-icons">arrow_back</i></a
|
||||
>
|
||||
<div class="uk-margin-left">
|
||||
<h3 class="uk-margin-remove uk-margin-left"><b>SCAN</b> {{ allScans[galleryFolder].metadata.filename }}</h3>
|
||||
<h3 class="uk-margin-remove uk-margin-left">
|
||||
<b>SCAN</b> {{ allScans[galleryFolder].metadata.filename }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-grid-medium uk-grid-match uk-margin-top" uk-grid>
|
||||
|
||||
<div v-for="item in sortedItems" :key="item.metadata.id">
|
||||
<scanCard
|
||||
<scanCard
|
||||
v-if="'isScan' in item"
|
||||
:metadata="item.metadata"
|
||||
:thumbnail="item.thumbnail"
|
||||
/>
|
||||
<captureCard
|
||||
<captureCard
|
||||
v-else
|
||||
:metadata="item.metadata"
|
||||
:temporary="item.temporary"
|
||||
:path="item.path"
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import captureCard from './galleryComponents/captureCard.vue'
|
||||
import scanCard from './galleryComponents/scanCard.vue'
|
||||
import axios from "axios";
|
||||
import captureCard from "./galleryComponents/captureCard.vue";
|
||||
import scanCard from "./galleryComponents/scanCard.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'galleryDisplay',
|
||||
name: "GalleryDisplay",
|
||||
|
||||
components: {
|
||||
captureCard,
|
||||
scanCard
|
||||
},
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
captureList: [],
|
||||
checkedTags: [],
|
||||
sortDescending: true,
|
||||
galleryFolder: "",
|
||||
scanTag: 'scan'
|
||||
}
|
||||
scanTag: "scan"
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
captureApiUri: function() {
|
||||
return this.$store.getters.uri + "/camera/capture";
|
||||
},
|
||||
|
||||
allTags: function() {
|
||||
// Return an array of unique tags across all captures
|
||||
var tags = [];
|
||||
for (var capture of this.captureList) {
|
||||
for (var tag of capture.metadata.tags) {
|
||||
if (!tags.includes(tag)) {
|
||||
tags.push(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tags.sort();
|
||||
},
|
||||
|
||||
noScanCaptureList: function() {
|
||||
var captures = [];
|
||||
for (var capture of this.captureList) {
|
||||
// Filter by selected tags
|
||||
var tags = capture.metadata.tags;
|
||||
|
||||
// Add to capture list if matched
|
||||
if (!tags.includes(this.scanTag)) {
|
||||
captures.push(capture);
|
||||
}
|
||||
}
|
||||
|
||||
return captures;
|
||||
},
|
||||
|
||||
allScans: function() {
|
||||
// Return an array of unique tags across all captures
|
||||
var scans = {};
|
||||
|
||||
for (var capture of this.captureList) {
|
||||
var custom = capture.metadata.custom;
|
||||
var tags = capture.metadata.tags;
|
||||
|
||||
if ("scan_id" in custom) {
|
||||
var id = custom["scan_id"];
|
||||
|
||||
// If this scan ID hasn't been seen before
|
||||
if (!(id in scans)) {
|
||||
scans[id] = {};
|
||||
scans[id].isScan = true;
|
||||
scans[id].captureList = [];
|
||||
scans[id].metadata = {
|
||||
filename: custom.basename,
|
||||
time: custom.time,
|
||||
id: custom.scan_id
|
||||
};
|
||||
scans[id].metadata.tags = [];
|
||||
scans[id].metadata.custom = {};
|
||||
}
|
||||
|
||||
// Add the capture object to the scan
|
||||
scans[id].captureList.push(capture);
|
||||
|
||||
// Add missing scan metadata, prioritising first capture
|
||||
for (var key of Object.keys(custom)) {
|
||||
if (!(key in scans[id].metadata.custom)) {
|
||||
scans[id].metadata.custom[key] = custom[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Append missing tags
|
||||
for (var tag of tags) {
|
||||
if (!scans[id].metadata.tags.includes(tag)) {
|
||||
scans[id].metadata.tags.push(tag);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a preview thumbnail
|
||||
if (!("thumbnail" in scans[id])) {
|
||||
scans[id].thumbnail =
|
||||
this.$store.getters.uri +
|
||||
"/camera/capture/" +
|
||||
capture.metadata.id +
|
||||
"/download?thumbnail=true";
|
||||
}
|
||||
}
|
||||
}
|
||||
return scans;
|
||||
},
|
||||
|
||||
scanList: function() {
|
||||
return Object.values(this.allScans);
|
||||
},
|
||||
|
||||
itemList: function() {
|
||||
if (this.galleryFolder) {
|
||||
console.log(this.allScans[this.galleryFolder].captureList);
|
||||
return this.allScans[this.galleryFolder].captureList;
|
||||
} else {
|
||||
return this.noScanCaptureList.concat(this.scanList);
|
||||
}
|
||||
},
|
||||
|
||||
filteredItems: function() {
|
||||
return this.filterCaptureList(this.itemList, this.checkedTags);
|
||||
},
|
||||
|
||||
sortedItems: function() {
|
||||
return this.sortCaptureList(this.filteredItems);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// A global signal listener to perform a gallery refresh
|
||||
this.$root.$on('globalUpdateCaptureList', () => {
|
||||
this.updateCaptureList()
|
||||
})
|
||||
this.$root.$on("globalUpdateCaptureList", () => {
|
||||
this.updateCaptureList();
|
||||
});
|
||||
// A global signal listener to set the gallery folder
|
||||
this.$root.$on('globalUpdateCaptureFolder', (folder) => {
|
||||
this.galleryFolder = folder
|
||||
})
|
||||
this.$root.$on("globalUpdateCaptureFolder", folder => {
|
||||
this.galleryFolder = folder;
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateCaptureList: function() {
|
||||
console.log("Updating capture list...")
|
||||
console.log("Updating capture list...");
|
||||
// Send move request
|
||||
axios.get(this.captureApiUri)
|
||||
.then(response => {
|
||||
this.$store.dispatch('updateState'); // Update store state for good measure
|
||||
this.captureList = response.data; // Update boxes from response
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
axios
|
||||
.get(this.captureApiUri)
|
||||
.then(response => {
|
||||
this.$store.dispatch("updateState"); // Update store state for good measure
|
||||
this.captureList = response.data; // Update boxes from response
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
},
|
||||
|
||||
filterCaptureList: function(list, filterTags) {
|
||||
|
|
@ -120,153 +267,33 @@ export default {
|
|||
// Add to capture list if matched
|
||||
if (includeCapture == true) {
|
||||
result.push(capture);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return result
|
||||
return result;
|
||||
},
|
||||
|
||||
sortCaptureList: function(list) {
|
||||
function compare(a, b) {
|
||||
if (a.metadata.time < b.metadata.time)
|
||||
return -1;
|
||||
if (a.metadata.time > b.metadata.time)
|
||||
return 1;
|
||||
if (a.metadata.time < b.metadata.time) return -1;
|
||||
if (a.metadata.time > b.metadata.time) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.sortDescending == true) {
|
||||
return list.sort(compare).reverse();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return list.sort(compare);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
computed: {
|
||||
captureApiUri: function () {
|
||||
return this.$store.getters.uri + "/camera/capture"
|
||||
},
|
||||
|
||||
allTags: function () {
|
||||
// Return an array of unique tags across all captures
|
||||
var tags = [];
|
||||
for (var capture of this.captureList) {
|
||||
for (var tag of capture.metadata.tags) {
|
||||
if (!tags.includes(tag)) {
|
||||
tags.push(tag);
|
||||
};
|
||||
};
|
||||
};
|
||||
return tags.sort()
|
||||
},
|
||||
|
||||
noScanCaptureList: function () {
|
||||
var captures = [];
|
||||
for (var capture of this.captureList) {
|
||||
// Assume exclusion
|
||||
var includeCapture = false;
|
||||
|
||||
// Filter by selected tags
|
||||
var tags = capture.metadata.tags;
|
||||
|
||||
// Add to capture list if matched
|
||||
if (!tags.includes(this.scanTag)) {
|
||||
captures.push(capture);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
return captures
|
||||
},
|
||||
|
||||
allScans: function () {
|
||||
// Return an array of unique tags across all captures
|
||||
var scans = {};
|
||||
|
||||
for (var capture of this.captureList) {
|
||||
var custom = capture.metadata.custom;
|
||||
var tags = capture.metadata.tags;
|
||||
|
||||
if ('scan_id' in custom) {
|
||||
var id = custom['scan_id']
|
||||
|
||||
// If this scan ID hasn't been seen before
|
||||
if (!(id in scans)) {
|
||||
scans[id] = {}
|
||||
scans[id].isScan = true
|
||||
scans[id].captureList = []
|
||||
scans[id].metadata = {
|
||||
filename: custom.basename,
|
||||
time: custom.time,
|
||||
id: custom.scan_id
|
||||
}
|
||||
scans[id].metadata.tags = []
|
||||
scans[id].metadata.custom = {}
|
||||
};
|
||||
|
||||
// Add the capture object to the scan
|
||||
scans[id].captureList.push(capture)
|
||||
|
||||
// Add missing scan metadata, prioritising first capture
|
||||
for (var key of Object.keys(custom)) {
|
||||
if (!(key in scans[id].metadata.custom)) {
|
||||
scans[id].metadata.custom[key] = custom[key]
|
||||
};
|
||||
};
|
||||
|
||||
// Append missing tags
|
||||
for (var tag of tags) {
|
||||
if (!scans[id].metadata.tags.includes(tag)) {
|
||||
scans[id].metadata.tags.push(tag)
|
||||
};
|
||||
};
|
||||
|
||||
// Create a preview thumbnail
|
||||
if (!('thumbnail' in scans[id])) {
|
||||
scans[id].thumbnail = this.$store.getters.uri + "/camera/capture/" + capture.metadata.id + "/download?thumbnail=true"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
return scans
|
||||
},
|
||||
|
||||
scanList: function () {
|
||||
return Object.values(this.allScans)
|
||||
},
|
||||
|
||||
itemList: function () {
|
||||
if (this.galleryFolder) {
|
||||
console.log(this.allScans[this.galleryFolder].captureList)
|
||||
return this.allScans[this.galleryFolder].captureList
|
||||
}
|
||||
else {
|
||||
return this.noScanCaptureList.concat(this.scanList)
|
||||
}
|
||||
},
|
||||
|
||||
filteredItems: function () {
|
||||
return this.filterCaptureList(this.itemList, this.checkedTags)
|
||||
},
|
||||
|
||||
sortedItems: function () {
|
||||
return this.sortCaptureList(this.filteredItems)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.navbar {
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(180, 180, 180, 0.25)
|
||||
border-color: rgba(180, 180, 180, 0.25);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,221 +1,246 @@
|
|||
<template>
|
||||
<div ref="streamDisplay" class="stream-display uk-width-1-1 uk-height-1-1 scrollTarget" id="stream-display">
|
||||
<div
|
||||
id="stream-display"
|
||||
ref="streamDisplay"
|
||||
class="stream-display uk-width-1-1 uk-height-1-1 scrollTarget"
|
||||
>
|
||||
<img
|
||||
ref="click-frame"
|
||||
class="uk-align-center uk-margin-remove-bottom"
|
||||
:hidden="!showStream"
|
||||
:src="streamImgUri"
|
||||
alt="Stream"
|
||||
@dblclick="clickMonitor"
|
||||
/>
|
||||
|
||||
<img class="uk-align-center uk-margin-remove-bottom" v-on:dblclick="clickMonitor" v-bind:hidden="!showStream" v-bind:src="streamImgUri" alt="Stream" ref="click-frame">
|
||||
<div v-if="!showStream">
|
||||
<div v-if="$store.state.waiting" class="uk-position-center">
|
||||
<div uk-spinner="ratio: 4.5"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="!showStream">
|
||||
<div v-if="$store.state.waiting" class="uk-position-center">
|
||||
<div uk-spinner="ratio: 4.5" ></div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="$store.state.globalSettings.disableStream"
|
||||
class="uk-position-center position-relative text-center"
|
||||
>
|
||||
Stream preview disabled
|
||||
</div>
|
||||
|
||||
<div v-else-if="$store.state.globalSettings.disableStream" class="uk-position-center position-relative text-center">
|
||||
Stream preview disabled
|
||||
</div>
|
||||
|
||||
<div v-else class="uk-position-center position-relative text-center">
|
||||
No active connection
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-else class="uk-position-center position-relative text-center">
|
||||
No active connection
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import axios from "axios";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
name: 'stream-display',
|
||||
name: "StreamDisplay",
|
||||
|
||||
data: function () {
|
||||
data: function() {
|
||||
return {
|
||||
displaySize: [0, 0],
|
||||
displayPosition: [0, 0],
|
||||
GpuPreviewActive: false,
|
||||
resizeTimeoutId: setTimeout(this.doneResizing, 500)
|
||||
displaySize: [0, 0],
|
||||
displayPosition: [0, 0],
|
||||
GpuPreviewActive: false,
|
||||
resizeTimeoutId: setTimeout(this.doneResizing, 500)
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
showStream: function() {
|
||||
return (
|
||||
this.$store.getters.ready &&
|
||||
!this.$store.state.globalSettings.disableStream
|
||||
);
|
||||
},
|
||||
streamImgUri: function() {
|
||||
return this.$store.getters.uri + "/stream";
|
||||
},
|
||||
startPreviewUri: function() {
|
||||
return this.$store.getters.uri + "/camera/preview/start";
|
||||
},
|
||||
stopPreviewUri: function() {
|
||||
return this.$store.getters.uri + "/camera/preview/stop";
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// A global signal listener to change the GPU preview state
|
||||
this.$root.$on('globalTogglePreview', (state) => {
|
||||
console.log(`Toggling preview to ${state}`)
|
||||
this.previewRequest(state)
|
||||
})
|
||||
this.$root.$on("globalTogglePreview", state => {
|
||||
console.log(`Toggling preview to ${state}`);
|
||||
this.previewRequest(state);
|
||||
});
|
||||
// A global signal listener to flash the stream element
|
||||
this.$root.$on('globalFlashStream', (state) => {
|
||||
this.flashStream()
|
||||
})
|
||||
this.$root.$on("globalFlashStream", () => {
|
||||
this.flashStream();
|
||||
});
|
||||
|
||||
// Mutation observer
|
||||
this.sizeObserver = new ResizeObserver(entries => {
|
||||
this.handleResize() // For any element attached to the observer, run handleResize() on change
|
||||
entries.forEach(entry => {}) // Optional: Run something per entry
|
||||
});
|
||||
// Fetch streamDisplay by ref
|
||||
const streamDisplayElement = this.$refs.streamDisplay.parentNode;
|
||||
// Attach streamDisplay to the size observer
|
||||
this.sizeObserver.observe(streamDisplayElement);
|
||||
// Mutation observer
|
||||
this.sizeObserver = new ResizeObserver(() => {
|
||||
this.handleResize(); // For any element attached to the observer, run handleResize() on change
|
||||
});
|
||||
// Fetch streamDisplay by ref
|
||||
const streamDisplayElement = this.$refs.streamDisplay.parentNode;
|
||||
// Attach streamDisplay to the size observer
|
||||
this.sizeObserver.observe(streamDisplayElement);
|
||||
},
|
||||
|
||||
},
|
||||
created: function() {
|
||||
// Watch for host 'ready'
|
||||
this.$store.watch(
|
||||
(state, getters) => {
|
||||
return getters.ready;
|
||||
},
|
||||
(newValue, oldValue) => {
|
||||
// 'ready' changed, so do something
|
||||
console.log(`Updating from ${oldValue} to ${newValue}`);
|
||||
this.previewRequest(this.$store.state.globalSettings.autoGpuPreview);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
created: function () {
|
||||
// Watch for host 'ready'
|
||||
this.$store.watch(
|
||||
(state)=>{
|
||||
return this.$store.getters.ready
|
||||
},
|
||||
(newValue, oldValue)=>{
|
||||
// 'ready' changed, so do something
|
||||
this.previewRequest(this.$store.state.globalSettings.autoGpuPreview)
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
beforeDestroy: function () {
|
||||
// Disconnect the size observer
|
||||
this.sizeObserver.disconnect()
|
||||
},
|
||||
beforeDestroy: function() {
|
||||
// Disconnect the size observer
|
||||
this.sizeObserver.disconnect();
|
||||
},
|
||||
|
||||
methods: {
|
||||
clickMonitor: function(event) {
|
||||
// Calculate steps from event coordinates and store config FOV
|
||||
let xCoordinate = event.offsetX;
|
||||
let yCoordinate = event.offsetY;
|
||||
// Calculate steps from event coordinates and store config FOV
|
||||
let xCoordinate = event.offsetX;
|
||||
let yCoordinate = event.offsetY;
|
||||
|
||||
let xRelative = (0.5*event.target.offsetWidth - xCoordinate)/event.target.offsetWidth;
|
||||
let yRelative = (0.5*event.target.offsetHeight - yCoordinate)/event.target.offsetHeight;
|
||||
let xRelative =
|
||||
(0.5 * event.target.offsetWidth - xCoordinate) /
|
||||
event.target.offsetWidth;
|
||||
let yRelative =
|
||||
(0.5 * event.target.offsetHeight - yCoordinate) /
|
||||
event.target.offsetHeight;
|
||||
|
||||
let xSteps = xRelative * this.$store.state.apiConfig.fov[0];
|
||||
let ySteps = yRelative * this.$store.state.apiConfig.fov[1];
|
||||
let xSteps = xRelative * this.$store.state.apiConfig.fov[0];
|
||||
let ySteps = yRelative * this.$store.state.apiConfig.fov[1];
|
||||
|
||||
// Emit a signal to move, acted on by panelNavigate.vue
|
||||
this.$root.$emit('globalMoveEvent', xSteps, ySteps, 0, false)
|
||||
},
|
||||
|
||||
flashStream: function() {
|
||||
let element = this.$refs.streamDisplay
|
||||
element.classList.remove("uk-animation-fade");
|
||||
element.offsetHeight; /* trigger reflow */
|
||||
element.classList.add("uk-animation-fade");
|
||||
},
|
||||
|
||||
handleResize: function(event) {
|
||||
// Only fires resize event after no resize in 500ms (prevents resize event spam)
|
||||
clearTimeout(this.resizeTimeoutId);
|
||||
this.resizeTimeoutId = setTimeout(this.handleDoneResize, 250)
|
||||
},
|
||||
|
||||
handleDoneResize: function() {
|
||||
// Recalculate size
|
||||
console.log("Recalculating frame size")
|
||||
this.recalculateSize();
|
||||
if (this.$store.state.globalSettings.autoGpuPreview == true && this.GpuPreviewActive == true) {
|
||||
// Reload preview
|
||||
this.$root.$emit('globalTogglePreview', true)
|
||||
}
|
||||
},
|
||||
|
||||
recalculateSize: function () {
|
||||
let element = this.$refs.streamDisplay.parentNode;
|
||||
let bound = element.getBoundingClientRect()
|
||||
|
||||
let elementSize = [bound.width, bound.height]
|
||||
|
||||
let elementPositionOnWindow = [bound.left, bound.top]
|
||||
let windowPositionOnDisplay = [window.screenX, window.screenY]
|
||||
let windowChromeHeight = window.outerHeight - window.innerHeight
|
||||
let elementPositionOnDisplay = [
|
||||
Math.max(0, windowPositionOnDisplay[0] + elementPositionOnWindow[0]),
|
||||
Math.max(0, windowPositionOnDisplay[1] + elementPositionOnWindow[1] + windowChromeHeight)
|
||||
]
|
||||
|
||||
this.displaySize = elementSize
|
||||
this.displayPosition = elementPositionOnDisplay
|
||||
|
||||
console.log(`Size: ${this.displaySize}`)
|
||||
console.log(`Position: ${this.displayPosition}`)
|
||||
},
|
||||
|
||||
previewRequest: function(state) {
|
||||
if (this.$store.getters.ready == true) {
|
||||
// Create URI and set this.GpuPreviewActive depending on if starting or stopping preview
|
||||
if (state == true) {
|
||||
this.GpuPreviewActive = true
|
||||
var requestUri = this.startPreviewUri;
|
||||
}
|
||||
else {
|
||||
this.GpuPreviewActive = false;
|
||||
var requestUri = this.stopPreviewUri;
|
||||
}
|
||||
|
||||
// Generate payload if tracking window position
|
||||
if (this.$store.state.globalSettings.trackWindow == true && state == true) {
|
||||
// Recalculate frame dimensions and position
|
||||
this.recalculateSize()
|
||||
// Copy data into payload array
|
||||
var payload = {
|
||||
window : [
|
||||
this.displayPosition[0],
|
||||
this.displayPosition[1],
|
||||
this.displaySize[0],
|
||||
this.displaySize[1],
|
||||
]
|
||||
}
|
||||
}
|
||||
else {
|
||||
var payload = {}
|
||||
}
|
||||
|
||||
// Send preview request
|
||||
axios.post(requestUri, payload)
|
||||
.then(response => {
|
||||
this.$store.dispatch('updateState'); // Update store state
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error) // Let mixin handle error
|
||||
})
|
||||
}
|
||||
// Emit a signal to move, acted on by panelNavigate.vue
|
||||
this.$root.$emit("globalMoveEvent", xSteps, ySteps, 0, false);
|
||||
},
|
||||
|
||||
},
|
||||
flashStream: function() {
|
||||
let element = this.$refs.streamDisplay;
|
||||
element.classList.remove("uk-animation-fade");
|
||||
element.offsetHeight; /* trigger reflow */
|
||||
element.classList.add("uk-animation-fade");
|
||||
},
|
||||
|
||||
computed: {
|
||||
showStream: function () {
|
||||
return this.$store.getters.ready && !this.$store.state.globalSettings.disableStream
|
||||
},
|
||||
streamImgUri: function () {
|
||||
return this.$store.getters.uri + "/stream"
|
||||
},
|
||||
startPreviewUri: function () {
|
||||
return this.$store.getters.uri + "/camera/preview/start"
|
||||
},
|
||||
stopPreviewUri: function () {
|
||||
return this.$store.getters.uri + "/camera/preview/stop"
|
||||
}
|
||||
}
|
||||
handleResize: function() {
|
||||
// Only fires resize event after no resize in 500ms (prevents resize event spam)
|
||||
clearTimeout(this.resizeTimeoutId);
|
||||
this.resizeTimeoutId = setTimeout(this.handleDoneResize, 250);
|
||||
},
|
||||
|
||||
}
|
||||
handleDoneResize: function() {
|
||||
// Recalculate size
|
||||
console.log("Recalculating frame size");
|
||||
this.recalculateSize();
|
||||
if (
|
||||
this.$store.state.globalSettings.autoGpuPreview == true &&
|
||||
this.GpuPreviewActive == true
|
||||
) {
|
||||
// Reload preview
|
||||
this.$root.$emit("globalTogglePreview", true);
|
||||
}
|
||||
},
|
||||
|
||||
recalculateSize: function() {
|
||||
let element = this.$refs.streamDisplay.parentNode;
|
||||
let bound = element.getBoundingClientRect();
|
||||
|
||||
let elementSize = [bound.width, bound.height];
|
||||
|
||||
let elementPositionOnWindow = [bound.left, bound.top];
|
||||
let windowPositionOnDisplay = [window.screenX, window.screenY];
|
||||
let windowChromeHeight = window.outerHeight - window.innerHeight;
|
||||
let elementPositionOnDisplay = [
|
||||
Math.max(0, windowPositionOnDisplay[0] + elementPositionOnWindow[0]),
|
||||
Math.max(
|
||||
0,
|
||||
windowPositionOnDisplay[1] +
|
||||
elementPositionOnWindow[1] +
|
||||
windowChromeHeight
|
||||
)
|
||||
];
|
||||
|
||||
this.displaySize = elementSize;
|
||||
this.displayPosition = elementPositionOnDisplay;
|
||||
|
||||
console.log(`Size: ${this.displaySize}`);
|
||||
console.log(`Position: ${this.displayPosition}`);
|
||||
},
|
||||
|
||||
previewRequest: function(state) {
|
||||
if (this.$store.getters.ready == true) {
|
||||
var requestUri = null;
|
||||
// Create URI and set this.GpuPreviewActive depending on if starting or stopping preview
|
||||
if (state == true) {
|
||||
this.GpuPreviewActive = true;
|
||||
requestUri = this.startPreviewUri;
|
||||
} else {
|
||||
this.GpuPreviewActive = false;
|
||||
requestUri = this.stopPreviewUri;
|
||||
}
|
||||
|
||||
// Generate payload if tracking window position
|
||||
var payload = {};
|
||||
if (
|
||||
this.$store.state.globalSettings.trackWindow == true &&
|
||||
state == true
|
||||
) {
|
||||
// Recalculate frame dimensions and position
|
||||
this.recalculateSize();
|
||||
// Copy data into payload array
|
||||
payload = {
|
||||
window: [
|
||||
this.displayPosition[0],
|
||||
this.displayPosition[1],
|
||||
this.displaySize[0],
|
||||
this.displaySize[1]
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
// Send preview request
|
||||
axios
|
||||
.post(requestUri, payload)
|
||||
.then(() => {
|
||||
this.$store.dispatch("updateState"); // Update store state
|
||||
})
|
||||
.catch(error => {
|
||||
this.modalError(error); // Let mixin handle error
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.stream-display img {
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
object-fit: contain
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.stream-display {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.position-relative {
|
||||
position: relative !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
// Load settings store from main process
|
||||
const { store } = require('electron').remote.require('./store')
|
||||
const { store } = require("electron").remote.require("./store");
|
||||
|
||||
// Load extra modules we'll be using
|
||||
const { Titlebar, Color } = require('custom-electron-titlebar');
|
||||
const { Titlebar, Color } = require("custom-electron-titlebar");
|
||||
|
||||
// Only show custom menubar if current window has no frame
|
||||
if (store.get('drawCustomTitleBar') == true) {
|
||||
new Titlebar({
|
||||
backgroundColor: Color.fromHex('#c5247f'),
|
||||
icon: './titleicon.svg'
|
||||
});
|
||||
if (store.get("drawCustomTitleBar") == true) {
|
||||
new Titlebar({
|
||||
backgroundColor: Color.fromHex("#c5247f"),
|
||||
icon: "./titleicon.svg"
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Loaded main.app.js for electron-renderer functionality")
|
||||
console.log("Loaded main.app.js for electron-renderer functionality");
|
||||
|
|
|
|||
109
src/main.js
109
src/main.js
|
|
@ -1,43 +1,50 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import store from './store'
|
||||
import Vue from "vue";
|
||||
import App from "./App.vue";
|
||||
import store from "./store";
|
||||
|
||||
import UIkit from 'uikit';
|
||||
import UIkit from "uikit";
|
||||
|
||||
// Import MD icons
|
||||
import 'material-design-icons/iconfont/material-icons.css'
|
||||
import "material-design-icons/iconfont/material-icons.css";
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Vue.mixin({
|
||||
methods: {
|
||||
modalConfirm: function(modalText) {
|
||||
var context = this
|
||||
var context = this;
|
||||
|
||||
// Stop GPU preview to show modal
|
||||
context.$root.$emit('globalTogglePreview', false)
|
||||
|
||||
context.$root.$emit("globalTogglePreview", false);
|
||||
|
||||
var showModal = function(resolve, reject) {
|
||||
UIkit.modal.confirm(modalText)
|
||||
.then(function() {
|
||||
resolve()
|
||||
}, function () {
|
||||
reject()
|
||||
})
|
||||
.finally(function() {
|
||||
// Reenable the GPU preview, if it was active before the modal
|
||||
console.log("Re-enabling GPU preview")
|
||||
if (context.$store.state.globalSettings.autoGpuPreview) {
|
||||
console.log("Re-enabling preview")
|
||||
context.$root.$emit('globalTogglePreview', true)
|
||||
}
|
||||
})
|
||||
}
|
||||
return new Promise(showModal)
|
||||
UIkit.modal
|
||||
.confirm(modalText)
|
||||
.then(
|
||||
function() {
|
||||
resolve();
|
||||
},
|
||||
function() {
|
||||
reject();
|
||||
}
|
||||
)
|
||||
.finally(function() {
|
||||
// Reenable the GPU preview, if it was active before the modal
|
||||
console.log("Re-enabling GPU preview");
|
||||
if (context.$store.state.globalSettings.autoGpuPreview) {
|
||||
console.log("Re-enabling preview");
|
||||
context.$root.$emit("globalTogglePreview", true);
|
||||
}
|
||||
});
|
||||
};
|
||||
return new Promise(showModal);
|
||||
},
|
||||
|
||||
modalNotify: function(message, status = 'success') {
|
||||
UIkit.notification({message: message, status: status})
|
||||
modalNotify: function(message, status = "success") {
|
||||
UIkit.notification({
|
||||
message: message,
|
||||
status: status
|
||||
});
|
||||
},
|
||||
|
||||
modalDialog: function(title, message) {
|
||||
|
|
@ -53,55 +60,57 @@ Vue.mixin({
|
|||
},
|
||||
|
||||
modalError: function(error) {
|
||||
console.log(error)
|
||||
var errormsg = ''
|
||||
console.log(error);
|
||||
var errormsg = "";
|
||||
|
||||
// If a response was obtained
|
||||
if (error.response) {
|
||||
// If the response is a nicely formatted JSON response from the server
|
||||
if (error.response.data.message) {
|
||||
errormsg = `${error.response.status}: ${error.response.data.message}`
|
||||
console.log(errormsg)
|
||||
errormsg = `${error.response.status}: ${error.response.data.message}`;
|
||||
console.log(errormsg);
|
||||
}
|
||||
// If the response is just some generic error response
|
||||
else {
|
||||
errormsg = `${error.response.status}: ${error.response.data}`
|
||||
console.log(errormsg)
|
||||
errormsg = `${error.response.status}: ${error.response.data}`;
|
||||
console.log(errormsg);
|
||||
}
|
||||
// If the error occured during the request
|
||||
// If the error occured during the request
|
||||
} else if (error.request) {
|
||||
errormsg = `${error.message}`
|
||||
console.log(errormsg)
|
||||
// Everything else
|
||||
errormsg = `${error.message}`;
|
||||
console.log(errormsg);
|
||||
// Everything else
|
||||
} else {
|
||||
errormsg = `${error.message}`
|
||||
console.log(errormsg)
|
||||
errormsg = `${error.message}`;
|
||||
console.log(errormsg);
|
||||
}
|
||||
this.$store.commit('setError', errormsg);
|
||||
UIkit.notification({message: `${errormsg}`, status: 'danger'})
|
||||
this.$store.commit("setError", errormsg);
|
||||
UIkit.notification({
|
||||
message: `${errormsg}`,
|
||||
status: "danger"
|
||||
});
|
||||
},
|
||||
|
||||
getLocalStorageObj: function(keyName) {
|
||||
if (localStorage.getItem(keyName)) {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(keyName))
|
||||
} catch(e) {
|
||||
console.log("Malformed entry. Removing from localStorage")
|
||||
localStorage.removeItem(keyName)
|
||||
return null
|
||||
return JSON.parse(localStorage.getItem(keyName));
|
||||
} catch (e) {
|
||||
console.log("Malformed entry. Removing from localStorage");
|
||||
localStorage.removeItem(keyName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setLocalStorageObj: function(keyName, object) {
|
||||
const parsed = JSON.stringify(object)
|
||||
const parsed = JSON.stringify(object);
|
||||
localStorage.setItem(keyName, parsed);
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
new Vue({
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
}).$mount("#app");
|
||||
|
|
|
|||
|
|
@ -1,20 +1,32 @@
|
|||
function isElectron() {
|
||||
// Renderer process
|
||||
if (typeof window !== 'undefined' && typeof window.process === 'object' && window.process.type === 'renderer') {
|
||||
return true;
|
||||
}
|
||||
// Renderer process
|
||||
if (
|
||||
typeof window !== "undefined" &&
|
||||
typeof window.process === "object" &&
|
||||
window.process.type === "renderer"
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Main process
|
||||
if (typeof process !== 'undefined' && typeof process.versions === 'object' && !!process.versions.electron) {
|
||||
return true;
|
||||
}
|
||||
// Main process
|
||||
if (
|
||||
typeof process !== "undefined" &&
|
||||
typeof process.versions === "object" &&
|
||||
!!process.versions.electron
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Detect the user agent when the `nodeIntegration` option is set to true
|
||||
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {
|
||||
return true;
|
||||
}
|
||||
// Detect the user agent when the `nodeIntegration` option is set to true
|
||||
if (
|
||||
typeof navigator === "object" &&
|
||||
typeof navigator.userAgent === "string" &&
|
||||
navigator.userAgent.indexOf("Electron") >= 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
export default isElectron;
|
||||
export default isElectron;
|
||||
|
|
|
|||
218
src/store.js
218
src/store.js
|
|
@ -1,18 +1,17 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import axios from 'axios'
|
||||
import Vue from "vue";
|
||||
import Vuex from "vuex";
|
||||
import axios from "axios";
|
||||
|
||||
Vue.use(Vuex)
|
||||
Vue.use(Vuex);
|
||||
|
||||
export default new Vuex.Store({
|
||||
|
||||
state: {
|
||||
host: '',
|
||||
host: "",
|
||||
port: 5000,
|
||||
apiVer: 'v1',
|
||||
apiVer: "v1",
|
||||
available: true,
|
||||
waiting: false,
|
||||
error: '',
|
||||
error: "",
|
||||
apiConfig: {},
|
||||
apiState: {},
|
||||
apiPlugins: [],
|
||||
|
|
@ -25,13 +24,13 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
mutations: {
|
||||
changeHost(state, [host, port, apiVer='v1']) {
|
||||
changeHost(state, [host, port, apiVer = "v1"]) {
|
||||
state.host = host;
|
||||
state.port = port;
|
||||
state.apiVer = apiVer;
|
||||
},
|
||||
changeWaiting(state, waiting) {
|
||||
state.waiting = waiting
|
||||
state.waiting = waiting;
|
||||
},
|
||||
commitConfig(state, configData) {
|
||||
state.apiConfig = configData;
|
||||
|
|
@ -46,155 +45,158 @@ export default new Vuex.Store({
|
|||
state.globalSettings[key] = value;
|
||||
},
|
||||
resetState(state) {
|
||||
state.waiting = false
|
||||
state.available = true
|
||||
state.error = null
|
||||
state.apiConfig = {}
|
||||
state.apiState = {}
|
||||
state.apiPlugins = []
|
||||
state.waiting = false;
|
||||
state.available = true;
|
||||
state.error = null;
|
||||
state.apiConfig = {};
|
||||
state.apiState = {};
|
||||
state.apiPlugins = [];
|
||||
},
|
||||
setConnected(state) {
|
||||
state.waiting = false
|
||||
state.available = true
|
||||
state.waiting = false;
|
||||
state.available = true;
|
||||
},
|
||||
setError(state, msg) {
|
||||
state.waiting = false
|
||||
state.available = false
|
||||
state.error = msg
|
||||
state.waiting = false;
|
||||
state.available = false;
|
||||
state.error = msg;
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
firstConnect(context) {
|
||||
// Reset the state when reconnecting starts
|
||||
context.commit('resetState')
|
||||
context.commit("resetState");
|
||||
// Mark as loading
|
||||
context.commit('changeWaiting', true)
|
||||
context.commit("changeWaiting", true);
|
||||
|
||||
var sendRequest = function(resolve, reject) {
|
||||
// Do requests
|
||||
context.dispatch('updateConfig')
|
||||
.then (() => context.dispatch('updateState'))
|
||||
.then (() => context.dispatch('updatePlugins'))
|
||||
.then (() => {
|
||||
console.log("Finished first connect")
|
||||
resolve()
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
}
|
||||
return new Promise(sendRequest)
|
||||
context
|
||||
.dispatch("updateConfig")
|
||||
.then(() => context.dispatch("updateState"))
|
||||
.then(() => context.dispatch("updatePlugins"))
|
||||
.then(() => {
|
||||
console.log("Finished first connect");
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
};
|
||||
return new Promise(sendRequest);
|
||||
},
|
||||
|
||||
updateConfig(context, uri=`${context.getters.uri}/config`) {
|
||||
console.log("Updating config")
|
||||
context.commit('changeWaiting', true)
|
||||
|
||||
updateConfig(context, uri = `${context.getters.uri}/config`) {
|
||||
console.log("Updating config");
|
||||
context.commit("changeWaiting", true);
|
||||
|
||||
var sendRequest = function(resolve, reject) {
|
||||
axios.get(uri)
|
||||
.then(response => {
|
||||
context.commit('commitConfig', response.data)
|
||||
context.commit('setConnected')
|
||||
console.log("Updating config finished")
|
||||
resolve()
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error))
|
||||
})
|
||||
}
|
||||
return new Promise(sendRequest)
|
||||
axios
|
||||
.get(uri)
|
||||
.then(response => {
|
||||
context.commit("commitConfig", response.data);
|
||||
context.commit("setConnected");
|
||||
console.log("Updating config finished");
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error));
|
||||
});
|
||||
};
|
||||
return new Promise(sendRequest);
|
||||
},
|
||||
|
||||
updateState(context, uri=`${context.getters.uri}/state`) {
|
||||
console.log("Updating state")
|
||||
context.commit('changeWaiting', true)
|
||||
|
||||
updateState(context, uri = `${context.getters.uri}/state`) {
|
||||
console.log("Updating state");
|
||||
context.commit("changeWaiting", true);
|
||||
|
||||
var sendRequest = function(resolve, reject) {
|
||||
axios.get(uri)
|
||||
.then(response => {
|
||||
context.commit('commitState', response.data)
|
||||
context.commit('setConnected')
|
||||
console.log("Updating state finished")
|
||||
resolve()
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error))
|
||||
})
|
||||
}
|
||||
return new Promise(sendRequest)
|
||||
axios
|
||||
.get(uri)
|
||||
.then(response => {
|
||||
context.commit("commitState", response.data);
|
||||
context.commit("setConnected");
|
||||
console.log("Updating state finished");
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error));
|
||||
});
|
||||
};
|
||||
return new Promise(sendRequest);
|
||||
},
|
||||
|
||||
updatePlugins(context, uri=`${context.getters.uri}/plugin`) {
|
||||
console.log("Updating plugins")
|
||||
context.commit('changeWaiting', true)
|
||||
|
||||
updatePlugins(context, uri = `${context.getters.uri}/plugin`) {
|
||||
console.log("Updating plugins");
|
||||
context.commit("changeWaiting", true);
|
||||
|
||||
var sendRequest = function(resolve, reject) {
|
||||
axios.get(uri)
|
||||
.then(response => {
|
||||
console.log("PLUGINS")
|
||||
console.log(response.data)
|
||||
context.commit('commitPlugins', response.data)
|
||||
context.commit('setConnected')
|
||||
console.log("Updating plugins finished")
|
||||
resolve()
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error))
|
||||
})
|
||||
}
|
||||
return new Promise(sendRequest)
|
||||
axios
|
||||
.get(uri)
|
||||
.then(response => {
|
||||
console.log("PLUGINS");
|
||||
console.log(response.data);
|
||||
context.commit("commitPlugins", response.data);
|
||||
context.commit("setConnected");
|
||||
console.log("Updating plugins finished");
|
||||
resolve();
|
||||
})
|
||||
.catch(error => {
|
||||
reject(new Error(error));
|
||||
});
|
||||
};
|
||||
return new Promise(sendRequest);
|
||||
},
|
||||
|
||||
pollTask(context, [taskId, timeout, interval]) {
|
||||
var endTime = Number(new Date()) + (timeout*1000 || 30000);
|
||||
interval = interval*1000 || 500;
|
||||
var endTime = Number(new Date()) + (timeout * 1000 || 30000);
|
||||
interval = interval * 1000 || 500;
|
||||
|
||||
var checkCondition = function(resolve, reject) {
|
||||
// If the condition is met, we're done!
|
||||
axios.get(`${context.getters.uri}/task/${taskId}`)
|
||||
.then(response => {
|
||||
console.log(response.data.status)
|
||||
var result = response.data.status
|
||||
// If the condition is met, we're done!
|
||||
axios.get(`${context.getters.uri}/task/${taskId}`).then(response => {
|
||||
console.log(response.data.status);
|
||||
var result = response.data.status;
|
||||
// If the task ends with success
|
||||
if(result == 'success') {
|
||||
resolve(response.data)
|
||||
if (result == "success") {
|
||||
resolve(response.data);
|
||||
}
|
||||
// If task ends with an error
|
||||
else if (result == 'error') {
|
||||
else if (result == "error") {
|
||||
// Pass the error string back with reject
|
||||
reject(new Error(response.data.return))
|
||||
reject(new Error(response.data.return));
|
||||
}
|
||||
// If task ends with termination
|
||||
else if (result == 'terminated') {
|
||||
else if (result == "terminated") {
|
||||
// Pass a generic termination error back with reject
|
||||
reject(new Error("Task terminated"))
|
||||
reject(new Error("Task terminated"));
|
||||
}
|
||||
// If task ends in any other way
|
||||
else if (result != 'running') {
|
||||
else if (result != "running") {
|
||||
// Pass status string as error
|
||||
reject(new Error(result))
|
||||
reject(new Error(result));
|
||||
}
|
||||
// If the condition isn't met but the timeout hasn't elapsed, go again
|
||||
else if (Number(new Date()) < endTime) {
|
||||
setTimeout(checkCondition, interval, resolve, reject)
|
||||
setTimeout(checkCondition, interval, resolve, reject);
|
||||
}
|
||||
// Didn't match and too much time, reject!
|
||||
else {
|
||||
reject(new Error('Polling timed out'))
|
||||
reject(new Error("Polling timed out"));
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(checkCondition);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
getters: {
|
||||
uri: state => `http://${state.host}:${state.port}/api/${state.apiVer}`,
|
||||
ready: state => ((state.available) && (Object.keys(state.apiConfig).length !== 0) && (Object.keys(state.apiState).length !== 0))
|
||||
ready: state =>
|
||||
state.available &&
|
||||
Object.keys(state.apiConfig).length !== 0 &&
|
||||
Object.keys(state.apiState).length !== 0
|
||||
}
|
||||
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
// this file is for cases where we need to access the
|
||||
// webpack config as a file when using CLI commands.
|
||||
|
||||
let service = process.VUE_CLI_SERVICE
|
||||
let service = process.VUE_CLI_SERVICE;
|
||||
|
||||
if (!service || process.env.VUE_CLI_API_MODE) {
|
||||
const Service = require('@vue/cli-service/lib/Service')
|
||||
service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
|
||||
service.init(process.env.VUE_CLI_MODE || process.env.NODE_ENV)
|
||||
const Service = require("@vue/cli-service/lib/Service");
|
||||
service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd());
|
||||
service.init(process.env.VUE_CLI_MODE || process.env.NODE_ENV);
|
||||
}
|
||||
|
||||
module.exports = service.resolveWebpackConfig()
|
||||
module.exports = service.resolveWebpackConfig();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue