mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
reverting dashboard rendering to webview, part 1
This commit is contained in:
1 parent
d387ba9004
commit
d413235ed9
23 files changed
+243
-236
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import { isMac, isWindows } from "./vars";
|
||||
|
||||
if (isMac) {
|
||||
console.warn("//FIXME: MAC-CA IMPORT ERROR!");
|
||||
// fixme: mac-ca import error
|
||||
// require("mac-ca");
|
||||
}
|
||||
if (isWindows) {
|
||||
|
||||
@@ -17,7 +17,6 @@ export const mainDir = path.join(contextDir, "src/main");
|
||||
export const rendererDir = path.join(contextDir, "src/renderer");
|
||||
export const htmlTemplate = path.resolve(rendererDir, "template.html");
|
||||
export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss");
|
||||
export const tsConfigFile = path.resolve(contextDir, "tsconfig.json");
|
||||
|
||||
// Apis
|
||||
export const staticProto = "static://"
|
||||
|
||||
@@ -12,6 +12,7 @@ import { promises } from "fs"
|
||||
import { ensureDir } from "fs-extra"
|
||||
import filenamify from "filenamify"
|
||||
import { v4 as uuid } from "uuid"
|
||||
import { apiPrefix } from "../common/vars";
|
||||
|
||||
export type FeatureInstallRequest = {
|
||||
name: string;
|
||||
@@ -261,7 +262,7 @@ export class ClusterManager {
|
||||
cluster = this.clusters.get(clusterId)
|
||||
if (cluster) {
|
||||
// we need to swap path prefix so that request is proxied to kube api
|
||||
req.url = req.url.replace(`/${clusterId}`, "/api-kube")
|
||||
req.url = req.url.replace(`/${clusterId}`, apiPrefix.KUBE_BASE)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+3
-1
@@ -9,6 +9,7 @@ import { Kubectl } from "./kubectl";
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import request from "request-promise-native"
|
||||
import { KubeconfigManager } from "./kubeconfig-manager"
|
||||
import { apiPrefix } from "../common/vars";
|
||||
|
||||
enum ClusterStatus {
|
||||
AccessGranted = 2,
|
||||
@@ -180,7 +181,8 @@ export class Cluster implements ClusterInfo {
|
||||
}
|
||||
|
||||
protected async k8sRequest(path: string, opts: request.RequestPromiseOptions = {}) {
|
||||
const url = `http://127.0.0.1:${this.port}/api-kube${path}`; // fixme: remove hardcoded api prefix
|
||||
const prefix = apiPrefix.KUBE_BASE;
|
||||
const url = `http://127.0.0.1:${this.port}${prefix}${path}`;
|
||||
opts.json = true;
|
||||
opts.timeout = 10000;
|
||||
opts.headers = Object.assign({}, opts.headers, {
|
||||
|
||||
+133
-17
@@ -1,23 +1,139 @@
|
||||
// Main process
|
||||
|
||||
import "../common/system-ca"
|
||||
import { app, BrowserWindow } from "electron"
|
||||
import "../common/prometheus-providers"
|
||||
import { app, dialog, protocol } from "electron"
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import path from "path"
|
||||
import { format as formatUrl } from "url"
|
||||
import logger from "./logger"
|
||||
import initMenu from "./menu"
|
||||
import * as proxy from "./proxy"
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { tracker } from "./tracker"
|
||||
import { ClusterManager } from "./cluster-manager";
|
||||
import AppUpdater from "./app-updater"
|
||||
import { shellSync } from "./shell-sync"
|
||||
import { getFreePort } from "./port"
|
||||
import { mangleProxyEnv } from "./proxy-env"
|
||||
import { findMainWebContents } from "./webcontents"
|
||||
import { registerStaticProtocol } from "../common/register-static";
|
||||
import { isMac } from "../common/vars";
|
||||
|
||||
console.log('MAIN', process.resourcesPath)
|
||||
console.log('userData', app.getPath("userData"))
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||
}
|
||||
|
||||
app.whenReady().then(async function start() {
|
||||
var mainWindow = new BrowserWindow({
|
||||
width: 1024,
|
||||
height: 768,
|
||||
show: false,
|
||||
webPreferences: {
|
||||
devTools: true,
|
||||
nodeIntegration: true,
|
||||
}
|
||||
});
|
||||
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||
let windowManager: WindowManager = null;
|
||||
let clusterManager: ClusterManager = null;
|
||||
|
||||
await mainWindow.loadFile("dist/index.html");
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
});
|
||||
const vmURL = formatUrl({
|
||||
pathname: path.join(__dirname, "dist/index.html"),
|
||||
protocol: "file",
|
||||
slashes: true,
|
||||
})
|
||||
|
||||
async function main() {
|
||||
await shellSync()
|
||||
|
||||
const updater = new AppUpdater()
|
||||
updater.start();
|
||||
|
||||
tracker.event("app", "start");
|
||||
|
||||
registerStaticProtocol();
|
||||
protocol.registerFileProtocol('store', (request, callback) => {
|
||||
const url = request.url.substr(8)
|
||||
callback(path.normalize(`${app.getPath("userData")}/${url}`))
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
|
||||
let port: number = null
|
||||
// find free port
|
||||
try {
|
||||
port = await getFreePort()
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
await dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy")
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// create cluster manager
|
||||
clusterManager = new ClusterManager(clusterStore.getAllClusterObjects(), port)
|
||||
|
||||
// run proxy
|
||||
try {
|
||||
proxy.listen(port, clusterManager)
|
||||
} catch (error) {
|
||||
logger.error(`Could not start proxy (127.0.0:${port}): ${error.message}`)
|
||||
await dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${port}): ${error.message || "unknown error"}`)
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// boot windowmanager
|
||||
windowManager = new WindowManager();
|
||||
windowManager.showMain(vmURL)
|
||||
|
||||
initMenu({
|
||||
logoutHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('logout', findMainWebContents(), {}).then((data: any) => {
|
||||
logger.debug("logout IPC sent");
|
||||
})
|
||||
},
|
||||
showPreferencesHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: 'preferences-page' }).then((data: any) => {
|
||||
logger.debug("navigate: preferences IPC sent");
|
||||
})
|
||||
},
|
||||
addClusterHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "add-cluster-page" }).then((data: any) => {
|
||||
logger.debug("navigate: add-cluster-page IPC sent");
|
||||
})
|
||||
},
|
||||
showWhatsNewHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "whats-new-page" }).then((data: any) => {
|
||||
logger.debug("navigate: whats-new-page IPC sent");
|
||||
})
|
||||
},
|
||||
clusterSettingsHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "cluster-settings-page" }).then((data: any) => {
|
||||
logger.debug("navigate: cluster-settings-page IPC sent");
|
||||
})
|
||||
},
|
||||
}, promiseIpc)
|
||||
}
|
||||
|
||||
app.on("ready", main)
|
||||
app.on('window-all-closed', function () {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (!isMac) {
|
||||
app.quit();
|
||||
} else {
|
||||
windowManager = null
|
||||
if (clusterManager) clusterManager.stop()
|
||||
}
|
||||
})
|
||||
app.on("activate", () => {
|
||||
if (!windowManager) {
|
||||
logger.debug("activate main window")
|
||||
windowManager = new WindowManager(false)
|
||||
windowManager.showMain(vmURL)
|
||||
}
|
||||
})
|
||||
app.on("will-quit", async (event) => {
|
||||
event.preventDefault(); // To allow mixpanel sending to be executed
|
||||
if (clusterManager) clusterManager.stop()
|
||||
app.exit(0);
|
||||
})
|
||||
|
||||
// todo: auto-restart app in dev-mode
|
||||
// if (isDevelopment) {
|
||||
// require('electron-reloader')(module);
|
||||
// }
|
||||
@@ -1,139 +0,0 @@
|
||||
// Main process
|
||||
|
||||
import "../common/system-ca"
|
||||
import "../common/prometheus-providers"
|
||||
import { app, dialog, protocol } from "electron"
|
||||
import { PromiseIpc } from "electron-promise-ipc"
|
||||
import path from "path"
|
||||
import { format as formatUrl } from "url"
|
||||
import logger from "./logger"
|
||||
import initMenu from "./menu"
|
||||
import * as proxy from "./proxy"
|
||||
import { WindowManager } from "./window-manager";
|
||||
import { clusterStore } from "../common/cluster-store"
|
||||
import { tracker } from "./tracker"
|
||||
import { ClusterManager } from "./cluster-manager";
|
||||
import AppUpdater from "./app-updater"
|
||||
import { shellSync } from "./shell-sync"
|
||||
import { getFreePort } from "./port"
|
||||
import { mangleProxyEnv } from "./proxy-env"
|
||||
import { findMainWebContents } from "./webcontents"
|
||||
import { registerStaticProtocol } from "../common/register-static";
|
||||
import { isDevelopment, isMac } from "../common/vars";
|
||||
|
||||
mangleProxyEnv()
|
||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||
}
|
||||
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||
|
||||
let windowManager: WindowManager = null;
|
||||
let clusterManager: ClusterManager = null;
|
||||
const vmURL = isDevelopment ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` : formatUrl({
|
||||
pathname: path.join(__dirname, "index.html"),
|
||||
protocol: "file",
|
||||
slashes: true,
|
||||
})
|
||||
|
||||
async function main() {
|
||||
await shellSync()
|
||||
|
||||
const updater = new AppUpdater()
|
||||
updater.start();
|
||||
|
||||
tracker.event("app", "start");
|
||||
|
||||
registerStaticProtocol();
|
||||
protocol.registerFileProtocol('store', (request, callback) => {
|
||||
const url = request.url.substr(8)
|
||||
callback(path.normalize(`${app.getPath("userData")}/${url}`))
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
})
|
||||
|
||||
let port: number = null
|
||||
// find free port
|
||||
try {
|
||||
port = await getFreePort()
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
await dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy")
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// create cluster manager
|
||||
clusterManager = new ClusterManager(clusterStore.getAllClusterObjects(), port)
|
||||
|
||||
// run proxy
|
||||
try {
|
||||
proxy.listen(port, clusterManager)
|
||||
} catch (error) {
|
||||
logger.error(`Could not start proxy (127.0.0:${port}): ${error.message}`)
|
||||
await dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${port}): ${error.message || "unknown error"}`)
|
||||
app.quit();
|
||||
}
|
||||
|
||||
// boot windowmanager
|
||||
windowManager = new WindowManager();
|
||||
windowManager.showMain(vmURL)
|
||||
|
||||
initMenu({
|
||||
logoutHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('logout', findMainWebContents(), {}).then((data: any) => {
|
||||
logger.debug("logout IPC sent");
|
||||
})
|
||||
},
|
||||
showPreferencesHook: async () => {
|
||||
// IPC send needs webContents as we're sending it to renderer
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: 'preferences-page' }).then((data: any) => {
|
||||
logger.debug("navigate: preferences IPC sent");
|
||||
})
|
||||
},
|
||||
addClusterHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "add-cluster-page" }).then((data: any) => {
|
||||
logger.debug("navigate: add-cluster-page IPC sent");
|
||||
})
|
||||
},
|
||||
showWhatsNewHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "whats-new-page" }).then((data: any) => {
|
||||
logger.debug("navigate: whats-new-page IPC sent");
|
||||
})
|
||||
},
|
||||
clusterSettingsHook: async () => {
|
||||
promiseIpc.send('navigate', findMainWebContents(), { name: "cluster-settings-page" }).then((data: any) => {
|
||||
logger.debug("navigate: cluster-settings-page IPC sent");
|
||||
})
|
||||
},
|
||||
}, promiseIpc)
|
||||
}
|
||||
|
||||
app.on("ready", main)
|
||||
app.on('window-all-closed', function () {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (!isMac) {
|
||||
app.quit();
|
||||
}
|
||||
else {
|
||||
windowManager = null
|
||||
if (clusterManager) clusterManager.stop()
|
||||
}
|
||||
})
|
||||
app.on("activate", () => {
|
||||
if (!windowManager) {
|
||||
logger.debug("activate main window")
|
||||
windowManager = new WindowManager(false)
|
||||
windowManager.showMain(vmURL)
|
||||
}
|
||||
})
|
||||
app.on("will-quit", async (event) => {
|
||||
event.preventDefault(); // To allow mixpanel sending to be executed
|
||||
if (clusterManager) clusterManager.stop()
|
||||
app.exit(0);
|
||||
})
|
||||
|
||||
// todo: check auto-restart app in dev-mode
|
||||
// if (isDevelopment) {
|
||||
// require('electron-reloader')(module);
|
||||
// }
|
||||
+4
-2
@@ -8,6 +8,7 @@ import logger from "./logger"
|
||||
import * as shell from "./node-shell-session"
|
||||
import { ClusterManager } from "./cluster-manager"
|
||||
import { Router } from "./router"
|
||||
import { apiPrefix } from "../common/vars";
|
||||
|
||||
export class LensProxy {
|
||||
public static readonly localShellSessions = true
|
||||
@@ -110,9 +111,10 @@ export class LensProxy {
|
||||
}
|
||||
|
||||
protected async getProxyTarget(req: http.IncomingMessage, contextHandler: ContextHandler): Promise<httpProxy.ServerOptions> {
|
||||
if (req.url.startsWith("/api-kube/")) {
|
||||
const prefix = apiPrefix.KUBE_BASE;
|
||||
if (req.url.startsWith(prefix)) {
|
||||
delete req.headers.authorization
|
||||
req.url = req.url.replace("/api-kube", "")
|
||||
req.url = req.url.replace(prefix, "")
|
||||
const isWatchRequest = req.url.includes("watch=")
|
||||
return await contextHandler.getApiTarget(isWatchRequest)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { LensApiRequest } from "../router"
|
||||
import { LensApi } from "../lens-api"
|
||||
import requestPromise from "request-promise-native"
|
||||
import { PrometheusProviderRegistry, PrometheusProvider, PrometheusNodeQuery, PrometheusClusterQuery, PrometheusPodQuery, PrometheusPvcQuery, PrometheusIngressQuery, PrometheusQueryOpts} from "../prometheus/provider-registry"
|
||||
import { apiPrefix } from "../../common/vars";
|
||||
|
||||
export type IMetricsQuery = string | string[] | {
|
||||
[metricName: string]: string;
|
||||
@@ -12,7 +13,7 @@ class MetricsRoute extends LensApi {
|
||||
public async routeMetrics(request: LensApiRequest) {
|
||||
const { response, cluster} = request
|
||||
const query: IMetricsQuery = request.payload;
|
||||
const serverUrl = `http://127.0.0.1:${cluster.port}/api-kube`
|
||||
const serverUrl = `http://127.0.0.1:${cluster.port}${apiPrefix.KUBE_BASE}`
|
||||
const headers = {
|
||||
"Host": `${cluster.id}.localhost:${cluster.port}`,
|
||||
"Content-type": "application/json",
|
||||
|
||||
@@ -1,29 +1,33 @@
|
||||
<template>
|
||||
<div class="draggable-top" />
|
||||
<div class="main-view" :class="{ 'menu-visible': isMenuVisible }">
|
||||
<main-menu v-if="isMenuVisible" />
|
||||
<router-view />
|
||||
<div id="app_vue">
|
||||
<div id="lens-container" />
|
||||
<div class="draggable-top"/>
|
||||
<div class="main-view" :class="{ 'menu-visible': isMenuVisible }">
|
||||
<main-menu v-if="isMenuVisible"/>
|
||||
<router-view/>
|
||||
</div>
|
||||
<bottom-bar v-if="isMenuVisible"/>
|
||||
</div>
|
||||
<bottom-bar v-if="isMenuVisible" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MainMenu from "@/_vue/components/MainMenu/MainMenu";
|
||||
import BottomBar from "@/_vue/components/BottomBar/BottomBar";
|
||||
|
||||
export default {
|
||||
name: 'Lens',
|
||||
components: {
|
||||
BottomBar,
|
||||
MainMenu
|
||||
},
|
||||
computed:{
|
||||
isMenuVisible: function(){ return this.$store.getters.isMenuVisible }
|
||||
computed: {
|
||||
isMenuVisible: function () { return this.$store.getters.isMenuVisible }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.draggable-top{
|
||||
.draggable-top {
|
||||
-webkit-app-region: drag;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
@@ -25,18 +25,7 @@ pre {
|
||||
color: $lens-text-color-light;
|
||||
}
|
||||
|
||||
// react-app container (dashboard)
|
||||
#app {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 70px;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#app_vue {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
& > .main-view{
|
||||
@@ -161,7 +150,7 @@ h1, h2, h3, h4, h5, h6{
|
||||
|
||||
// Force BS modals to use main app font etc.
|
||||
.modal-open{
|
||||
@extend #app_vue
|
||||
@extend #app
|
||||
}
|
||||
|
||||
.popover {
|
||||
@@ -204,4 +193,14 @@ h1, h2, h3, h4, h5, h6{
|
||||
top: 3px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#lens-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 70px;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
display: none;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#app_vue > .main-view > .content {
|
||||
#app > .main-view > .content {
|
||||
left: 70px;
|
||||
right: 70px;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#app_vue > .main-view > .content {
|
||||
#app > .main-view > .content {
|
||||
left: 70px;
|
||||
right: 70px;
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#app_vue > .main-view > .content {
|
||||
#app > .main-view > .content {
|
||||
left: 70px;
|
||||
}
|
||||
.lens-preferences {
|
||||
|
||||
@@ -98,7 +98,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#app_vue > .main-view > .content {
|
||||
#app > .main-view > .content {
|
||||
left: 70px;
|
||||
right: 70px;
|
||||
}
|
||||
|
||||
+13
-12
@@ -1,3 +1,4 @@
|
||||
import "../../common/system-ca"
|
||||
import "./assets/css/app.scss"
|
||||
import "prismjs";
|
||||
import "prismjs/components/prism-yaml"
|
||||
@@ -29,19 +30,19 @@ Vue.mixin({
|
||||
}
|
||||
})
|
||||
|
||||
// run
|
||||
setTimeout(main, 250);
|
||||
|
||||
export async function main() {
|
||||
try {
|
||||
await store.dispatch('init');
|
||||
// any initialization we want to do for app state
|
||||
setTimeout(() => {
|
||||
store.dispatch('init', ).catch((error) => {
|
||||
console.error(error)
|
||||
}).finally(() => {
|
||||
/* eslint-disable no-new */
|
||||
console.log("start vue")
|
||||
new Vue({
|
||||
components: {App},
|
||||
components: { App },
|
||||
persist,
|
||||
store,
|
||||
router,
|
||||
template: '<App/>'
|
||||
}).$mount('#app_vue')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
}).$mount('#app')
|
||||
})
|
||||
}, 0)
|
||||
@@ -166,7 +166,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
},
|
||||
|
||||
attachWebview({commit}, lens: LensWebview) {
|
||||
const container: any = document.getElementById("app");
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container || !lens.webview) {
|
||||
return
|
||||
}
|
||||
@@ -190,7 +190,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
promiseIpc.send("enableClusterSettingsMenuItem", lens.id)
|
||||
},
|
||||
detachWebview({commit}, lens: LensWebview) {
|
||||
const container: any = document.getElementById("app");
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container) { return }
|
||||
container.childNodes.forEach((child: any) => {
|
||||
if (child === lens.webview) {
|
||||
@@ -203,7 +203,7 @@ const actions: ActionTree<ClusterState, any> = {
|
||||
promiseIpc.send("disableClusterSettingsMenuItem")
|
||||
},
|
||||
hideWebviews({commit}) {
|
||||
const container: any = document.getElementById("app");
|
||||
const container: any = document.getElementById("lens-container");
|
||||
if (!container) { return }
|
||||
container.style = "display: none;"
|
||||
container.childNodes.forEach((child: any) => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../../common/system-ca"
|
||||
import "./app.scss";
|
||||
|
||||
import React from "react";
|
||||
|
||||
@@ -7,15 +7,11 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
We are using node <script>document.write(process.versions.node)</script>,
|
||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
||||
and Electron <script>document.write(process.versions.electron)</script>.
|
||||
|
||||
<div id="app"></div>
|
||||
<div id="app_vue"></div>
|
||||
|
||||
<script src="dll.js"></script>
|
||||
<script src="renderer_vue.js"></script>
|
||||
<!--<div id="app_vue"></div>-->
|
||||
<!--<script src="dll.js"></script>-->
|
||||
<!--<script src="renderer_vue.js"></script>-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user