Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom popup for displaying editor schemas #2049

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions electron/app/createWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {BrowserWindow} from 'electron';

import getPort from 'get-port';
import * as http from 'http';

const isDev = process.env.NODE_ENV === 'development';
const localContent: Record<string, string> = {};
let server: http.Server | undefined;

export const createWorker = () => {
let workerWindow = new BrowserWindow({show: false});

if (isDev) {
workerWindow.loadURL('http://localhost:3000/worker.html');
workerWindow.webContents.openDevTools();
} else {
workerWindow.loadURL(`file://${__dirname}/../../worker.html`);
}

workerWindow.webContents.once('did-finish-load', () => {
console.log('Worker initialized..');
});
};

function initServer() {
console.log('Initializing local server');
server = http.createServer((req, res) => {
if (req.url && localContent[req.url]) {
console.log(`Serving content for ${req.url}`);
res.write(localContent[req.url]);
res.end();
} else {
res.end(`Not found - stranger things have happened.`);
}
});

if (server) {
getPort({port: 51038}).then(port => {
if (server) {
server.listen(port);
console.log(`Local server listening on port ${port}`);
}
});
}
}

export const addLocalServerContent = (path: string, schema: string) => {
if (!server) {
initServer();
}

localContent[path] = schema;
};
8 changes: 8 additions & 0 deletions electron/app/ipc/ipcListeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {CommandOptions} from '@utils/commands';
import {ProjectNameChange, StorePropagation} from '@utils/global-electron-store';
import {UPDATE_APPLICATION, trackEvent} from '@utils/telemetry';

import {addLocalServerContent} from '@root/electron/app/createWorker';

import autoUpdater from '../autoUpdater';
import {
checkNewVersion,
Expand Down Expand Up @@ -263,3 +265,9 @@ ipcMain.on('global-electron-store-update', (event, args: any) => {
log.warn(`received invalid event type for global electron store update ${args.eventType}`);
}
});

ipcMain.on('add-local-server-content', (event, args: any) => {
if (args.path && args.content) {
addLocalServerContent(args.path, args.content);
}
});
4 changes: 4 additions & 0 deletions electron/app/openApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import * as path from 'path';

import {logToFile} from '@utils/logToFile';

import {createWorker} from '@root/electron/app/createWorker';

import {createWindow} from './createWindow';
import {getDockMenu} from './menu';

Expand All @@ -30,6 +32,7 @@ export const openApplication = async (givenPath?: string) => {

ElectronStore.initRenderer();
const win = createWindow(givenPath);
createWorker();

if (app.dock) {
const image = nativeImage.createFromPath(path.join(app.getAppPath(), '/public/large-icon-256.png'));
Expand All @@ -42,6 +45,7 @@ export const openApplication = async (givenPath?: string) => {
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow(givenPath);
createWorker();
}
});

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@
"execa": "5.1.1",
"fast-deep-equal": "3.1.3",
"flat": "5.0.2",
"git-url-parse": "12.0.0",
"framer-motion": "6.3.11",
"get-port": "5.1.1",
"git-url-parse": "12.0.0",
"jsonpath-plus": "6.0.1",
"lodash": "4.17.21",
"loglevel": "1.8.0",
Expand Down
13 changes: 13 additions & 0 deletions public/worker.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Monokle Worker</title>
</head>
<body>
<p>This is only shown in dev mode - to give access to DevTools</p>
<script>
// your background code here
</script>
</body>
</html>
24 changes: 22 additions & 2 deletions src/hooks/useResourceYamlSchema.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import {ipcRenderer} from 'electron';

import {useEffect} from 'react';

import {languages} from 'monaco-editor/esm/vs/editor/editor.api';

import {FileMapType} from '@models/appstate';
import {K8sResource} from '@models/k8sresource';
import {ResourceKindHandler} from '@models/resourcekindhandler';

import {isKustomizationPatch} from '@redux/services/kustomize';
import {hasSupportedResourceContent} from '@redux/services/resource';
import {getResourceSchema, getSchemaForPath} from '@redux/services/schema';

import {getResourceKindHandler} from '@src/kindhandlers';

function useResourceYamlSchema(
yaml: typeof languages.yaml,
userDataDir: string,
Expand All @@ -28,16 +33,30 @@ function useResourceYamlSchema(

let resourceSchema;
let validate = true;
let resourceKindHandler: ResourceKindHandler | undefined;

if (resource) {
resourceSchema = getResourceSchema(resource, k8sVersion, userDataDir);
validate = resourceSchema && !isKustomizationPatch(resource) && hasSupportedResourceContent(resource);
resourceKindHandler = getResourceKindHandler(resource.kind);
} else if (selectedPath && fileMap) {
resourceSchema = getSchemaForPath(selectedPath, fileMap);
validate = resourceSchema !== undefined;
}

yaml &&
if (yaml) {
let schemaUri = `https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v${k8sVersion}/${resource?.kind.toLowerCase()}.json`;

// if this is a custom resource then host the schema using the local server
if (resourceKindHandler && resourceKindHandler.isCustom) {
const schemaPath = `/schemas/${resource?.kind.toLowerCase()}.json`;
ipcRenderer.send('add-local-server-content', {
path: schemaPath,
content: JSON.stringify(resourceSchema, null, 2),
});
schemaUri = `http://localhost:51038${schemaPath}`;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

port is hardcoded - need to get the actual port from the server

}

yaml.yamlDefaults.setDiagnosticsOptions({
validate,
enableSchemaRequest: true,
Expand All @@ -47,12 +66,13 @@ function useResourceYamlSchema(
format: true,
schemas: [
{
uri: 'http://monokle/k8s.json', // id of the first schema
uri: schemaUri,
fileMatch: ['*'], // associate with our model
schema: resourceSchema || {},
},
],
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [resource, selectedPath, fileMap, k8sVersion]);
}
Expand Down