mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
support-page extension -- part 2
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
822d9b4974
commit
ef66f67b39
2
.gitignore
vendored
2
.gitignore
vendored
@ -12,6 +12,6 @@ binaries/client/
|
||||
binaries/server/
|
||||
src/extensions/*/*.js
|
||||
src/extensions/*/*.d.ts
|
||||
src/extensions/example-extension/src/**
|
||||
types/extension-api.d.ts
|
||||
types/extension-renderer-api.d.ts
|
||||
extensions/*/dist
|
||||
|
||||
@ -9,7 +9,7 @@ export default class ExampleExtension extends LensRendererExtension {
|
||||
registerPages(registry: Registry.PageRegistry) {
|
||||
this.disposers.push(
|
||||
registry.add({
|
||||
type: Registry.DynamicPageType.CLUSTER,
|
||||
type: Registry.PageRegistryType.CLUSTER,
|
||||
path: "/extension-example",
|
||||
title: "Example Extension",
|
||||
components: {
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { LensMainExtension } from "@lens/extensions";
|
||||
import { LensMainExtension, Registry } from "@lens/extensions";
|
||||
|
||||
export default class SupportPageMainExtension extends LensMainExtension {
|
||||
async onActivate() {
|
||||
console.log("support page extension activated")
|
||||
}
|
||||
|
||||
async registerAppMenus() {
|
||||
async registerAppMenus(registry: Registry.MenuRegistry) {
|
||||
// TODO: allow to modify global menu item "Help -> Support"
|
||||
}
|
||||
}
|
||||
|
||||
18
extensions/support-page/package-lock.json
generated
18
extensions/support-page/package-lock.json
generated
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "lens-support",
|
||||
"name": "lens-support-page",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
@ -10,6 +10,12 @@
|
||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/history": {
|
||||
"version": "4.7.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz",
|
||||
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.11.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.11.tgz",
|
||||
@ -32,6 +38,16 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"@types/react-router": {
|
||||
"version": "5.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.8.tgz",
|
||||
"integrity": "sha512-HzOyJb+wFmyEhyfp4D4NYrumi+LQgQL/68HvJO+q6XtuHSDvw6Aqov7sCAhjbNq3bUPgPqbdvjXC5HeB2oEAPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/history": "*",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/source-list-map": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.11.11",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-router": "^5.1.8",
|
||||
"@types/webpack": "^4.41.17",
|
||||
"mobx": "^5.15.5",
|
||||
"react": "^16.13.1",
|
||||
|
||||
@ -1,7 +1,22 @@
|
||||
import { LensRendererExtension } from "@lens/ui-extensions";
|
||||
import { LensRendererExtension, Registry } from "@lens/ui-extensions";
|
||||
import { Support } from "./src/support";
|
||||
import { supportPageRoute, supportPageURL } from "./src/support.route";
|
||||
|
||||
export default class SupportPageRendererExtension extends LensRendererExtension {
|
||||
async onActivate() {
|
||||
console.log("support page extension activated")
|
||||
}
|
||||
|
||||
registerPages(registry: Registry.PageRegistry) {
|
||||
this.disposers.push(
|
||||
registry.add({
|
||||
...supportPageRoute,
|
||||
type: Registry.PageRegistryType.GLOBAL,
|
||||
url: supportPageURL(),
|
||||
components: {
|
||||
Page: Support,
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
7
extensions/support-page/src/support.route.ts
Normal file
7
extensions/support-page/src/support.route.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import type { RouteProps } from "react-router";
|
||||
|
||||
export const supportPageRoute: RouteProps = {
|
||||
path: "/support"
|
||||
}
|
||||
|
||||
export const supportPageURL = () => supportPageRoute.path.toString();
|
||||
29
extensions/support-page/src/support.tsx
Normal file
29
extensions/support-page/src/support.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
// TODO: figure out how to consume styles / handle import "./support.scss"
|
||||
// TODO: support localization / figure out how to extract / consume i18n strings
|
||||
|
||||
import React from "react"
|
||||
import { observer } from "mobx-react"
|
||||
import { CommonVars, Component } from "@lens/ui-extensions";
|
||||
|
||||
@observer
|
||||
export class Support extends React.Component {
|
||||
render() {
|
||||
const { PageLayout } = Component;
|
||||
const { slackUrl, issuesTrackerUrl } = CommonVars;
|
||||
return (
|
||||
<PageLayout showOnTop className="Support" header={<h2>Support</h2>}>
|
||||
<h2>Community Slack Channel</h2>
|
||||
<p>
|
||||
Ask a question, see what's being discussed, join the conversation <a href={slackUrl} target="_blank">here</a>
|
||||
</p>
|
||||
|
||||
<h2>Report an Issue</h2>
|
||||
<p>
|
||||
Review existing issues or open a new one <a href={issuesTrackerUrl} target="_blank">here</a>
|
||||
</p>
|
||||
|
||||
{/*<h2><Trans>Commercial Support</Trans></h2>*/}
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
113
extensions/telemetry/package-lock.json
generated
113
extensions/telemetry/package-lock.json
generated
@ -201,6 +201,7 @@
|
||||
"version": "6.12.5",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
|
||||
"integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
@ -274,6 +275,7 @@
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
@ -328,7 +330,8 @@
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
},
|
||||
"assign-symbols": {
|
||||
"version": "1.0.0",
|
||||
@ -346,7 +349,8 @@
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
@ -357,12 +361,14 @@
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"dev": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
|
||||
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA=="
|
||||
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
|
||||
"dev": true
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
@ -435,6 +441,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
@ -671,7 +678,8 @@
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
@ -778,6 +786,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@ -853,7 +862,8 @@
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.4",
|
||||
@ -929,6 +939,7 @@
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
@ -992,7 +1003,8 @@
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"des.js": {
|
||||
"version": "1.0.1",
|
||||
@ -1045,6 +1057,7 @@
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
@ -1201,7 +1214,8 @@
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"dev": true
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "3.0.2",
|
||||
@ -1292,17 +1306,20 @@
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
},
|
||||
"figgy-pudding": {
|
||||
"version": "3.5.2",
|
||||
@ -1365,12 +1382,14 @@
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
@ -1431,6 +1450,7 @@
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
@ -1468,12 +1488,14 @@
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
@ -1592,6 +1614,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
@ -1760,7 +1783,8 @@
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
||||
"dev": true
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "1.0.2",
|
||||
@ -1789,7 +1813,8 @@
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
@ -1800,7 +1825,8 @@
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"dev": true
|
||||
},
|
||||
"json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
@ -1811,17 +1837,20 @@
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"dev": true
|
||||
},
|
||||
"json5": {
|
||||
"version": "1.0.1",
|
||||
@ -1836,6 +1865,7 @@
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
@ -1979,12 +2009,14 @@
|
||||
"mime-db": {
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
@ -2164,7 +2196,8 @@
|
||||
"node-machine-id": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/node-machine-id/-/node-machine-id-1.1.12.tgz",
|
||||
"integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ=="
|
||||
"integrity": "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
@ -2176,7 +2209,8 @@
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -2349,7 +2383,8 @@
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.2.2",
|
||||
@ -2416,7 +2451,8 @@
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.3",
|
||||
@ -2476,12 +2512,14 @@
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
||||
"dev": true
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
@ -2589,6 +2627,7 @@
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
@ -2655,7 +2694,8 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
},
|
||||
"safe-regex": {
|
||||
"version": "1.1.0",
|
||||
@ -2669,7 +2709,8 @@
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "1.0.0",
|
||||
@ -2905,6 +2946,7 @@
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
@ -3124,6 +3166,7 @@
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
@ -3158,6 +3201,7 @@
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
@ -3165,7 +3209,8 @@
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"dev": true
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
@ -3213,6 +3258,7 @@
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz",
|
||||
"integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
"request": "^2.88.2",
|
||||
@ -3223,6 +3269,7 @@
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
|
||||
"integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
@ -3230,7 +3277,8 @@
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3285,6 +3333,7 @@
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
|
||||
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
@ -3345,12 +3394,14 @@
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"dev": true
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
|
||||
@ -9,11 +9,10 @@
|
||||
"styles": []
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"dev": "npm run build --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"build": "webpack -p",
|
||||
"dev": "webpack --watch"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ts-loader": "^8.0.4",
|
||||
"typescript": "^4.0.3",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { AppPreferenceRegistry, LensRendererExtension } from "@lens/ui-extensions";
|
||||
import { Registry, LensRendererExtension } from "@lens/ui-extensions";
|
||||
import { telemetryPreferencesStore } from "./src/telemetry-preferences-store"
|
||||
import { TelemetryPreferenceHint, TelemetryPreferenceInput } from "./src/telemetry-preference"
|
||||
import { tracker } from "./src/tracker"
|
||||
@ -11,7 +11,7 @@ export default class TelemetryRendererExtension extends LensRendererExtension {
|
||||
await telemetryPreferencesStore.load()
|
||||
}
|
||||
|
||||
registerAppPreferences(registry: AppPreferenceRegistry) {
|
||||
registerAppPreferences(registry: Registry.AppPreferenceRegistry) {
|
||||
this.disposers.push(
|
||||
registry.add({
|
||||
title: "Telemetry & Usage Tracking",
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Singleton, appEventBus, AppEvent } from "@lens/extensions"
|
||||
import { EventBus, Util } from "@lens/extensions"
|
||||
import ua from "universal-analytics"
|
||||
import { machineIdSync } from "node-machine-id"
|
||||
import { telemetryPreferencesStore } from "./telemetry-preferences-store"
|
||||
|
||||
export class Tracker extends Singleton {
|
||||
export class Tracker extends Util.Singleton {
|
||||
static readonly GA_ID = "UA-159377374-1"
|
||||
|
||||
protected eventHandlers: Array<(ev: AppEvent ) => void> = []
|
||||
protected eventHandlers: Array<(ev: EventBus.AppEvent ) => void> = []
|
||||
protected started = false
|
||||
protected visitor: ua.Visitor
|
||||
protected machineId: string = null;
|
||||
@ -31,11 +31,11 @@ export class Tracker extends Singleton {
|
||||
|
||||
this.started = true
|
||||
|
||||
const handler = (ev: AppEvent) => {
|
||||
const handler = (ev: EventBus.AppEvent) => {
|
||||
this.event(ev.name, ev.action, ev.params)
|
||||
}
|
||||
this.eventHandlers.push(handler)
|
||||
appEventBus.addListener(handler)
|
||||
EventBus.appEventBus.addListener(handler)
|
||||
}
|
||||
|
||||
stop() {
|
||||
@ -44,7 +44,7 @@ export class Tracker extends Singleton {
|
||||
this.started = false
|
||||
|
||||
for (const handler of this.eventHandlers) {
|
||||
appEventBus.removeListener(handler)
|
||||
EventBus.appEventBus.removeListener(handler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,11 +21,6 @@ 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");
|
||||
|
||||
// Extensions
|
||||
export const extensionsLibName = `${appName}-extensions.api`
|
||||
export const extensionsRendererLibName = `${appName}-extensions-renderer.api`
|
||||
export const extensionsDir = path.join(contextDir, "src/extensions");
|
||||
|
||||
// Special runtime paths
|
||||
defineGlobal("__static", {
|
||||
get() {
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
// Lens-extensions api developer's kit
|
||||
export type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
|
||||
export type { LensExtensionMainRuntimeEnv } from "./lens-runtime";
|
||||
export * from "./lens-main-extension"
|
||||
|
||||
// APIs
|
||||
import * as EventBus from "./main-api/event-bus"
|
||||
import * as Store from "./main-api/stores"
|
||||
import * as Util from "./main-api/utils"
|
||||
import * as Registry from "./main-api/registries"
|
||||
|
||||
export {
|
||||
EventBus,
|
||||
Store,
|
||||
Util
|
||||
Util,
|
||||
Registry,
|
||||
}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import type { ExtensionId, LensExtension, ExtensionManifest, ExtensionModel } from "./lens-extension"
|
||||
import type { LensMainExtension } from "./lens-main-extension"
|
||||
import type { LensRendererExtension } from "./lens-renderer-extension"
|
||||
import { broadcastIpc } from "../common/ipc"
|
||||
import type { LensExtensionRuntimeEnv } from "./lens-runtime"
|
||||
import type { LensExtensionMainRuntimeEnv } from "./lens-runtime"
|
||||
import type { LensExtensionRendererRuntimeEnv } from "./lens-renderer-runtime"
|
||||
import path from "path"
|
||||
import { broadcastIpc } from "../common/ipc"
|
||||
import { observable, reaction, toJS, } from "mobx"
|
||||
import logger from "../main/logger"
|
||||
import { app, remote, ipcRenderer } from "electron"
|
||||
import { pageRegistry } from "./page-registry";
|
||||
import { appPreferenceRegistry } from "./app-preference-registry"
|
||||
import { menuRegistry } from "./menu-registry";
|
||||
import { statusBarRegistry } from "./status-bar-registry";
|
||||
|
||||
export interface InstalledExtension extends ExtensionModel {
|
||||
manifestPath: string;
|
||||
@ -35,14 +39,14 @@ export class ExtensionLoader {
|
||||
}
|
||||
}
|
||||
|
||||
loadOnClusterRenderer(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnClusterRenderer(getLensRuntimeEnv: () => LensExtensionRendererRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on cluster renderer')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMainRenderer(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnMainRenderer(getLensRuntimeEnv: () => LensExtensionRendererRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main renderer')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensRendererExtension) => {
|
||||
instance.registerPages(pageRegistry)
|
||||
@ -50,14 +54,15 @@ export class ExtensionLoader {
|
||||
})
|
||||
}
|
||||
|
||||
loadOnMain(getLensRuntimeEnv: () => LensExtensionRuntimeEnv) {
|
||||
loadOnMain(getLensRuntimeEnv: () => LensExtensionMainRuntimeEnv) {
|
||||
logger.info('[EXTENSIONS-LOADER]: load on main')
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensExtension) => {
|
||||
// todo
|
||||
this.autoloadExtensions(getLensRuntimeEnv, (instance: LensMainExtension) => {
|
||||
instance.registerAppMenus(menuRegistry);
|
||||
instance.registerStatusBarIcon(statusBarRegistry);
|
||||
})
|
||||
}
|
||||
|
||||
protected autoloadExtensions(getLensRuntimeEnv: () => LensExtensionRuntimeEnv, callback: (instance: LensExtension) => void) {
|
||||
protected autoloadExtensions(getLensRuntimeEnv: () => object, callback: (instance: LensExtension) => void) {
|
||||
return reaction(() => this.extensions.toJS(), (installedExtensions) => {
|
||||
for(const [id, ext] of installedExtensions) {
|
||||
let instance = this.instances.get(ext.manifestPath)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Lens-extensions api developer's kit
|
||||
export type { LensExtensionRuntimeEnv } from "./lens-renderer-runtime"
|
||||
export type { LensExtensionRendererRuntimeEnv } from "./lens-renderer-runtime"
|
||||
|
||||
// APIs
|
||||
export * from "./lens-extension"
|
||||
@ -10,11 +10,13 @@ import * as EventBus from "./main-api/event-bus"
|
||||
import * as K8sApi from "./renderer-api/k8s-api"
|
||||
import * as Registry from "./renderer-api/registries"
|
||||
import * as Util from "./main-api/utils"
|
||||
import * as CommonVars from "../common/vars";
|
||||
|
||||
export {
|
||||
Component,
|
||||
EventBus,
|
||||
K8sApi,
|
||||
Registry,
|
||||
Util
|
||||
Util,
|
||||
CommonVars,
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import type { LensExtensionRuntimeEnv } from "./lens-runtime";
|
||||
import { readJsonSync } from "fs-extra";
|
||||
import { action, observable, toJS } from "mobx";
|
||||
import logger from "../main/logger";
|
||||
@ -34,7 +33,7 @@ export class LensExtension implements ExtensionModel {
|
||||
@observable manifest: ExtensionManifest;
|
||||
@observable manifestPath: string;
|
||||
@observable isEnabled = false;
|
||||
@observable.ref runtime: LensExtensionRuntimeEnv;
|
||||
@observable.ref runtime: any;
|
||||
|
||||
constructor(model: ExtensionModel, manifest: ExtensionManifest) {
|
||||
this.importModel(model, manifest);
|
||||
@ -56,7 +55,7 @@ export class LensExtension implements ExtensionModel {
|
||||
// mock
|
||||
}
|
||||
|
||||
async enable(runtime: LensExtensionRuntimeEnv) {
|
||||
async enable(runtime: any) {
|
||||
this.isEnabled = true;
|
||||
this.runtime = runtime;
|
||||
logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`);
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
import { LensExtension } from "./lens-extension"
|
||||
import type { MenuRegistry } from "./menu-registry";
|
||||
import type { StatusBarRegistry } from "./status-bar-registry";
|
||||
|
||||
export class LensMainExtension extends LensExtension {
|
||||
async registerAppMenus() {
|
||||
registerAppMenus(registry: MenuRegistry) {
|
||||
//
|
||||
}
|
||||
|
||||
async registerPrometheusProviders(registry: any) {
|
||||
registerStatusBarIcon(registry: StatusBarRegistry) {
|
||||
//
|
||||
}
|
||||
|
||||
registerPrometheusProviders(registry: any) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
import logger from "../main/logger";
|
||||
import { navigate } from "../renderer/navigation";
|
||||
|
||||
export interface LensExtensionRuntimeEnv {
|
||||
export interface LensExtensionRendererRuntimeEnv {
|
||||
logger: typeof logger;
|
||||
navigate: typeof navigate;
|
||||
}
|
||||
|
||||
export function getLensRuntime(): LensExtensionRuntimeEnv {
|
||||
export function getLensRuntimeRenderer(): LensExtensionRendererRuntimeEnv {
|
||||
return {
|
||||
logger,
|
||||
navigate
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
import logger from "../main/logger";
|
||||
|
||||
export interface LensExtensionRuntimeEnv {
|
||||
export interface LensExtensionMainRuntimeEnv {
|
||||
logger: typeof logger;
|
||||
}
|
||||
|
||||
export function getLensRuntime(): LensExtensionRuntimeEnv {
|
||||
export function getLensRuntime(): LensExtensionMainRuntimeEnv {
|
||||
return {
|
||||
logger
|
||||
}
|
||||
|
||||
1
src/extensions/main-api/registries.ts
Normal file
1
src/extensions/main-api/registries.ts
Normal file
@ -0,0 +1 @@
|
||||
export { MenuRegistry, MenuRegistration } from "../menu-registry";
|
||||
16
src/extensions/menu-registry.ts
Normal file
16
src/extensions/menu-registry.ts
Normal file
@ -0,0 +1,16 @@
|
||||
// Extensions API -> Global menu customize
|
||||
|
||||
import { observable } from "mobx";
|
||||
|
||||
export interface MenuRegistration {
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export class MenuRegistry {
|
||||
items = observable<MenuRegistration>([], { deep: false });
|
||||
|
||||
add(item: MenuRegistration) {
|
||||
}
|
||||
}
|
||||
|
||||
export const menuRegistry = new MenuRegistry();
|
||||
@ -7,38 +7,37 @@ import { IconProps } from "../renderer/components/icon";
|
||||
import { IClassName } from "../renderer/utils";
|
||||
import { TabRoute } from "../renderer/components/layout/tab-layout";
|
||||
|
||||
export enum DynamicPageType {
|
||||
export enum PageRegistryType {
|
||||
GLOBAL = "lens-scope",
|
||||
CLUSTER = "cluster-view-scope",
|
||||
}
|
||||
|
||||
export interface PageRegistration extends RouteProps {
|
||||
type: PageRegistryType;
|
||||
components: PageComponents;
|
||||
className?: IClassName;
|
||||
url?: string; // initial url to be used for building menus and tabs, otherwise "path" applied by default
|
||||
path: string; // route-path
|
||||
title: React.ReactNode; // used in sidebar's & tabs-layout
|
||||
type: DynamicPageType;
|
||||
components: PageComponents;
|
||||
title?: React.ReactNode; // used in sidebar's & tabs-layout if provided
|
||||
subPages?: (PageRegistration & TabRoute)[];
|
||||
}
|
||||
|
||||
export interface PageComponents {
|
||||
Page: React.ComponentType<any>;
|
||||
MenuIcon: React.ComponentType<IconProps>;
|
||||
MenuIcon?: React.ComponentType<IconProps>;
|
||||
}
|
||||
|
||||
export class PageRegistry {
|
||||
protected pages = observable.array<PageRegistration>([], { deep: false });
|
||||
|
||||
@computed get globalPages() {
|
||||
return this.pages.filter(page => page.type === DynamicPageType.GLOBAL);
|
||||
return this.pages.filter(page => page.type === PageRegistryType.GLOBAL);
|
||||
}
|
||||
|
||||
@computed get clusterPages() {
|
||||
return this.pages.filter(page => page.type === DynamicPageType.CLUSTER);
|
||||
return this.pages.filter(page => page.type === PageRegistryType.CLUSTER);
|
||||
}
|
||||
|
||||
// todo: verify paths to avoid collision with existing pages
|
||||
// fixme: validate route paths to avoid collisions
|
||||
add(params: PageRegistration) {
|
||||
this.pages.push(params);
|
||||
return () => {
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
// TODO: add more common re-usable UI components + refactor interfaces (Props -> ComponentProps)
|
||||
|
||||
export * from "../../renderer/components/icon"
|
||||
export * from "../../renderer/components/checkbox"
|
||||
export * from "../../renderer/components/tooltip"
|
||||
export * from "../../renderer/components/button"
|
||||
export * from "../../renderer/components/tabs"
|
||||
export * from "../../renderer/components/badge"
|
||||
export { KubeObjectMeta } from "../../renderer/components/kube-object/kube-object-meta";
|
||||
export { MenuItem, SubMenu } from "../../renderer/components/menu";
|
||||
export { StatusBrick } from "../../renderer/components/status-brick";
|
||||
export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store";
|
||||
export { createPodLogsTab } from "../../renderer/components/dock/pod-logs.store";
|
||||
export * from "../../renderer/components/layout/page-layout"
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export { DynamicPageType, PageRegistry } from "../page-registry"
|
||||
export { AppPreferenceRegistry } from "../app-preference-registry"
|
||||
export { PageRegistryType, PageRegistry, PageRegistration, PageComponents } from "../page-registry"
|
||||
export { AppPreferenceRegistry, AppPreferenceComponents, AppPreferenceRegistration } from "../app-preference-registry"
|
||||
|
||||
15
src/extensions/status-bar-registry.ts
Normal file
15
src/extensions/status-bar-registry.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// Extensions API -> Status bar customizations
|
||||
|
||||
import { observable } from "mobx";
|
||||
|
||||
export interface StatusBarRegistration {
|
||||
}
|
||||
|
||||
export class StatusBarRegistry {
|
||||
items = observable<StatusBarRegistration>([], { deep: false });
|
||||
|
||||
add(item: StatusBarRegistration) {
|
||||
}
|
||||
}
|
||||
|
||||
export const statusBarRegistry = new StatusBarRegistry();
|
||||
@ -1,2 +0,0 @@
|
||||
export * from "./support.route"
|
||||
export * from "./support"
|
||||
@ -1,8 +0,0 @@
|
||||
import { RouteProps } from "react-router";
|
||||
import { buildURL } from "../../navigation";
|
||||
|
||||
export const supportRoute: RouteProps = {
|
||||
path: "/support"
|
||||
}
|
||||
|
||||
export const supportURL = buildURL(supportRoute.path)
|
||||
@ -1,3 +0,0 @@
|
||||
// TODO: figure out how to consume extra styles from extensions
|
||||
.Support {
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
import "./support.scss"
|
||||
|
||||
import React from "react"
|
||||
import { observer } from "mobx-react"
|
||||
import { Trans } from "@lingui/macro"
|
||||
import { issuesTrackerUrl, slackUrl } from "../../../common/vars";
|
||||
import { PageLayout } from "../layout/page-layout";
|
||||
|
||||
@observer
|
||||
export class Support extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<PageLayout showOnTop className="Support" header={<h2>Support</h2>}>
|
||||
<h2><Trans>Community Slack Channel</Trans></h2>
|
||||
<p>
|
||||
<Trans>Ask a question, see what's being discussed, join the conversation <a className="supportLink" href={slackUrl} target="_blank">here</a></Trans>{" "}
|
||||
</p>
|
||||
|
||||
<h2><Trans>Report an Issue</Trans></h2>
|
||||
<p>
|
||||
<Trans>Review existing issues or open a new one <a className="supportLink" href={issuesTrackerUrl} target="_blank">here</a></Trans>
|
||||
</p>
|
||||
|
||||
{/*<h2><Trans>Commercial Support</Trans></h2>*/}
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -38,8 +38,8 @@ import { webFrame } from "electron";
|
||||
import { pageRegistry } from "../../extensions/page-registry";
|
||||
import { DynamicPage } from "../../extensions/dynamic-page";
|
||||
import { extensionLoader } from "../../extensions/extension-loader";
|
||||
import { getLensRuntime } from "../../extensions/lens-runtime";
|
||||
import { appEventBus } from "../../common/event-bus"
|
||||
import { getLensRuntimeRenderer } from "../../extensions/lens-renderer-runtime";
|
||||
import { appEventBus } from "../../common/event-bus"
|
||||
|
||||
@observer
|
||||
export class App extends React.Component {
|
||||
@ -51,7 +51,7 @@ export class App extends React.Component {
|
||||
|
||||
await clusterIpc.setFrameId.invokeFromRenderer(clusterId, frameId);
|
||||
await getHostedCluster().whenReady; // cluster.activate() is done at this point
|
||||
extensionLoader.loadOnClusterRenderer(getLensRuntime)
|
||||
extensionLoader.loadOnClusterRenderer(getLensRuntimeRenderer)
|
||||
appEventBus.emit({name: "cluster", action: "open", params: {
|
||||
clusterId: clusterId
|
||||
}})
|
||||
@ -83,7 +83,7 @@ export class App extends React.Component {
|
||||
<Route component={UserManagement} {...usersManagementRoute}/>
|
||||
<Route component={Apps} {...appsRoute}/>
|
||||
{pageRegistry.clusterPages.map(page => {
|
||||
return <Route {...page} key={page.path} render={() => <DynamicPage page={page}/>}/>
|
||||
return <Route {...page} key={String(page.path)} render={() => <DynamicPage page={page}/>}/>
|
||||
})}
|
||||
<Redirect exact from="/" to={this.startURL}/>
|
||||
<Route component={NotFound}/>
|
||||
|
||||
@ -5,7 +5,6 @@ import { observer } from "mobx-react";
|
||||
import { Icon } from "../icon";
|
||||
import { WorkspaceMenu } from "../+workspaces/workspace-menu";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { supportURL } from "../+support/support.route";
|
||||
import { navigate } from "../../navigation";
|
||||
|
||||
@observer
|
||||
@ -24,7 +23,7 @@ export class BottomBar extends React.Component {
|
||||
material="support"
|
||||
tooltip="Support"
|
||||
className="support-icon box right"
|
||||
onClick={() => navigate(supportURL())}
|
||||
onClick={() => navigate("/support")}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -7,7 +7,6 @@ import { ClustersMenu } from "./clusters-menu";
|
||||
import { BottomBar } from "./bottom-bar";
|
||||
import { LandingPage, landingRoute, landingURL } from "../+landing-page";
|
||||
import { Preferences, preferencesRoute } from "../+preferences";
|
||||
import { Support, supportRoute } from "../+support";
|
||||
import { Workspaces, workspacesRoute } from "../+workspaces";
|
||||
import { AddCluster, addClusterRoute } from "../+add-cluster";
|
||||
import { ClusterView } from "./cluster-view";
|
||||
@ -60,13 +59,12 @@ export class ClusterManager extends React.Component {
|
||||
<Switch>
|
||||
<Route component={LandingPage} {...landingRoute} />
|
||||
<Route component={Preferences} {...preferencesRoute} />
|
||||
<Route component={Support} {...supportRoute} />
|
||||
<Route component={Workspaces} {...workspacesRoute} />
|
||||
<Route component={AddCluster} {...addClusterRoute} />
|
||||
<Route component={ClusterView} {...clusterViewRoute} />
|
||||
<Route component={ClusterSettings} {...clusterSettingsRoute} />
|
||||
{pageRegistry.globalPages.map(({ path, components: { Page } }) => {
|
||||
return <Route key={path} path={path} component={Page}/>
|
||||
{pageRegistry.globalPages.map(({ path, url = String(path), components: { Page } }) => {
|
||||
return <Route key={url} path={path} component={Page}/>
|
||||
})}
|
||||
<Redirect exact to={this.startUrl} />
|
||||
</Switch>
|
||||
|
||||
@ -67,7 +67,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .dynamic-pages {
|
||||
> .extensions {
|
||||
&:not(:empty) {
|
||||
padding-top: $spacing;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import { ClusterId, clusterStore } from "../../../common/cluster-store";
|
||||
import { workspaceStore } from "../../../common/workspace-store";
|
||||
import { ClusterIcon } from "../cluster-icon";
|
||||
import { Icon } from "../icon";
|
||||
import { cssNames, IClassName, autobind } from "../../utils";
|
||||
import { autobind, cssNames, IClassName } from "../../utils";
|
||||
import { Badge } from "../badge";
|
||||
import { navigate } from "../../navigation";
|
||||
import { addClusterURL } from "../+add-cluster";
|
||||
@ -21,7 +21,7 @@ import { Tooltip } from "../tooltip";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import { clusterIpc } from "../../../common/cluster-ipc";
|
||||
import { clusterViewURL } from "./cluster-view.route";
|
||||
import { DragDropContext, Droppable, Draggable, DropResult, DroppableProvided, DraggableProvided } from "react-beautiful-dnd";
|
||||
import { DragDropContext, Draggable, DraggableProvided, Droppable, DroppableProvided, DropResult } from "react-beautiful-dnd";
|
||||
import { pageRegistry } from "../../../extensions/page-registry";
|
||||
|
||||
interface Props {
|
||||
@ -155,9 +155,10 @@ export class ClustersMenu extends React.Component<Props> {
|
||||
<Badge className="counter" label={newContexts.size} tooltip={<Trans>new</Trans>} />
|
||||
)}
|
||||
</div>
|
||||
<div className="dynamic-pages">
|
||||
{pageRegistry.globalPages.map(({ path, components: { MenuIcon } }) => {
|
||||
return <MenuIcon key={path} onClick={() => navigate(path)}/>
|
||||
<div className="extensions">
|
||||
{pageRegistry.globalPages.map(({ path, url = String(path), components: { MenuIcon } }) => {
|
||||
if (!MenuIcon) return;
|
||||
return <MenuIcon key={url} onClick={() => navigate(url)}/>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -80,7 +80,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
<div className={cssNames("Sidebar flex column", className, { pinned: isPinned })}>
|
||||
<div className="header flex align-center">
|
||||
<NavLink exact to="/" className="box grow">
|
||||
<Icon svg="logo-full" className="logo-icon" />
|
||||
<Icon svg="logo-full" className="logo-icon"/>
|
||||
<div className="logo-text">Lens</div>
|
||||
</NavLink>
|
||||
<Icon
|
||||
@ -97,14 +97,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={clusterURL()}
|
||||
text={<Trans>Cluster</Trans>}
|
||||
icon={<Icon svg="kube" />}
|
||||
icon={<Icon svg="kube"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="nodes"
|
||||
isHidden={!isAllowedResource("nodes")}
|
||||
url={nodesURL()}
|
||||
text={<Trans>Nodes</Trans>}
|
||||
icon={<Icon svg="nodes" />}
|
||||
icon={<Icon svg="nodes"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="workloads"
|
||||
@ -113,7 +113,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={workloadsRoute.path}
|
||||
subMenus={Workloads.tabRoutes}
|
||||
text={<Trans>Workloads</Trans>}
|
||||
icon={<Icon svg="workloads" />}
|
||||
icon={<Icon svg="workloads"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="config"
|
||||
@ -122,7 +122,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={configRoute.path}
|
||||
subMenus={Config.tabRoutes}
|
||||
text={<Trans>Configuration</Trans>}
|
||||
icon={<Icon material="list" />}
|
||||
icon={<Icon material="list"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="networks"
|
||||
@ -131,7 +131,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
routePath={networkRoute.path}
|
||||
subMenus={Network.tabRoutes}
|
||||
text={<Trans>Network</Trans>}
|
||||
icon={<Icon material="device_hub" />}
|
||||
icon={<Icon material="device_hub"/>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="storage"
|
||||
@ -139,14 +139,14 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={storageURL({ query })}
|
||||
routePath={storageRoute.path}
|
||||
subMenus={Storage.tabRoutes}
|
||||
icon={<Icon svg="storage" />}
|
||||
icon={<Icon svg="storage"/>}
|
||||
text={<Trans>Storage</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
id="namespaces"
|
||||
isHidden={!isAllowedResource("namespaces")}
|
||||
url={namespacesURL()}
|
||||
icon={<Icon material="layers" />}
|
||||
icon={<Icon material="layers"/>}
|
||||
text={<Trans>Namespaces</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@ -154,7 +154,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
isHidden={!isAllowedResource("events")}
|
||||
url={eventsURL({ query })}
|
||||
routePath={eventRoute.path}
|
||||
icon={<Icon material="access_time" />}
|
||||
icon={<Icon material="access_time"/>}
|
||||
text={<Trans>Events</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@ -162,7 +162,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={appsURL({ query })}
|
||||
subMenus={Apps.tabRoutes}
|
||||
routePath={appsRoute.path}
|
||||
icon={<Icon material="apps" />}
|
||||
icon={<Icon material="apps"/>}
|
||||
text={<Trans>Apps</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@ -170,7 +170,7 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={usersManagementURL({ query })}
|
||||
routePath={usersManagementRoute.path}
|
||||
subMenus={UserManagement.tabRoutes}
|
||||
icon={<Icon material="security" />}
|
||||
icon={<Icon material="security"/>}
|
||||
text={<Trans>Access Control</Trans>}
|
||||
/>
|
||||
<SidebarNavItem
|
||||
@ -179,17 +179,17 @@ export class Sidebar extends React.Component<Props> {
|
||||
url={crdURL()}
|
||||
subMenus={CustomResources.tabRoutes}
|
||||
routePath={crdRoute.path}
|
||||
icon={<Icon material="extension" />}
|
||||
icon={<Icon material="extension"/>}
|
||||
text={<Trans>Custom Resources</Trans>}
|
||||
>
|
||||
{this.renderCustomResources()}
|
||||
</SidebarNavItem>
|
||||
{pageRegistry.clusterPages.map(({ path, title, components: { MenuIcon } }) => {
|
||||
{pageRegistry.clusterPages.map(({ path, title, url = String(path), components: { MenuIcon } }) => {
|
||||
if (!MenuIcon) return;
|
||||
return (
|
||||
<SidebarNavItem
|
||||
key={path}
|
||||
id={`extension-${path}`}
|
||||
url={path}
|
||||
key={url} id={`sidebar_item_${url}`}
|
||||
url={url}
|
||||
routePath={path}
|
||||
text={title}
|
||||
icon={<MenuIcon/>}
|
||||
@ -255,7 +255,7 @@ class SidebarNavItem extends React.Component<SidebarNavItemProps> {
|
||||
<div className={cssNames("nav-item", { active: isActive })} onClick={this.toggleSubMenu}>
|
||||
{icon}
|
||||
<span className="link-text">{text}</span>
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"} />
|
||||
<Icon className="expand-icon" material={this.isExpanded ? "keyboard_arrow_up" : "keyboard_arrow_down"}/>
|
||||
</div>
|
||||
<ul className={cssNames("sub-menu", { active: isActive })}>
|
||||
{subMenus.map(({ title, url }) => (
|
||||
|
||||
@ -12,12 +12,12 @@ import { WhatsNew, whatsNewRoute } from "./components/+whats-new";
|
||||
import { Notifications } from "./components/notifications";
|
||||
import { ConfirmDialog } from "./components/confirm-dialog";
|
||||
import { extensionLoader } from "../extensions/extension-loader";
|
||||
import { getLensRuntime } from "../extensions/lens-runtime";
|
||||
import { getLensRuntimeRenderer } from "../extensions/lens-renderer-runtime";
|
||||
|
||||
@observer
|
||||
export class LensApp extends React.Component {
|
||||
static async init() {
|
||||
extensionLoader.loadOnMainRenderer(getLensRuntime)
|
||||
extensionLoader.loadOnMainRenderer(getLensRuntimeRenderer)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { appName, buildDir, extensionsDir, extensionsLibName, extensionsRendererLibName, htmlTemplate, isDevelopment, isProduction, publicPath, rendererDir, sassCommonVars } from "./src/common/vars";
|
||||
import { appName, buildDir, htmlTemplate, isDevelopment, isProduction, publicPath, rendererDir, sassCommonVars } from "./src/common/vars";
|
||||
import path from "path";
|
||||
import webpack from "webpack";
|
||||
import HtmlWebpackPlugin from "html-webpack-plugin";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user