feat: migration to electron + next complete

This commit is contained in:
Anoop M D 2022-03-07 17:52:35 +05:30
parent 1f2b64c7cc
commit 37d9f75f64
95 changed files with 1990 additions and 21308 deletions

View File

@ -12,8 +12,8 @@ app.on('ready', async () => {
await prepareNext('./renderer');
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
width: 1280,
height: 768,
webPreferences: {
nodeIntegration: false,
preload: join(__dirname, 'preload.js'),

2299
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,6 @@
{
"name": "grafnode",
"private": true,
"workspaces": [
"packages/grafnode-components",
"packages/grafnode-www"
],
"main": "main/index.js",
"scripts": {
"clean": "rimraf dist renderer/.next renderer/out",
@ -20,6 +16,37 @@
"renderer/out"
]
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@tabler/icons": "^1.46.0",
"@tippyjs/react": "^4.2.6",
"classnames": "^2.3.1",
"codemirror": "^5.64.0",
"codemirror-graphql": "^1.2.5",
"electron-is-dev": "^2.0.0",
"electron-next": "^3.1.5",
"escape-html": "^1.0.3",
"formik": "^2.2.9",
"graphiql": "^1.5.9",
"graphql": "^16.2.0",
"graphql-request": "^3.7.0",
"idb": "^7.0.0",
"immer": "^9.0.7",
"lodash": "^4.17.21",
"markdown-it": "^12.2.0",
"mousetrap": "^1.6.5",
"nanoid": "^3.1.30",
"next": "12.0.4",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-tabs": "^3.2.3",
"sass": "^1.46.0",
"styled-components": "^5.3.3",
"tailwindcss": "^2.2.19",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-spread": "^7.16.7",
@ -41,9 +68,5 @@
"style-loader": "^3.3.1",
"webpack": "^5.64.4",
"webpack-cli": "^4.9.1"
},
"dependencies": {
"electron-is-dev": "^2.0.0",
"electron-next": "^3.1.5"
}
}

View File

@ -1,11 +0,0 @@
{
"presets": [
"@babel/preset-env",
["@babel/preset-react", {"runtime": "automatic"}]
],
"plugins": [
["@babel/plugin-transform-spread", {
"loose": true
}]
]
}

View File

@ -1,28 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
/dist
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
{
"name": "@grafnode/components",
"version": "0.0.1",
"description": "",
"main": "dist/index.js",
"scripts": {
"watch:build": "webpack --watch --mode development",
"build": "webpack --mode production",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/grafnode/grafnode.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/grafnode/grafnode/issues"
},
"homepage": "https://github.com/grafnode/grafnode#readme",
"dependencies": {},
"peerDependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@tabler/icons": "^1.46.0",
"classnames": "^2.3.1",
"codemirror": "^5.64.0",
"escape-html": "^1.0.3",
"formik": "^2.2.9",
"markdown-it": "^12.2.0",
"nanoid": "^3.1.30",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-tabs": "^3.2.3",
"styled-components": "^5.3.3",
"tailwindcss": "^2.2.19",
"yup": "^0.32.11"
}
}

View File

@ -1,11 +0,0 @@
import Navbar from './components/Navbar';
import Sidebar from './components/Sidebar';
import RequestTabs from './components/RequestTabs';
import RequestTabPanel from './components/RequestTabPanel';
export {
Navbar,
Sidebar,
RequestTabs,
RequestTabPanel
};

View File

@ -1,59 +0,0 @@
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: "./src/index.js",
output: {
publicPath: '',
globalObject: 'this',
filename: "index.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "umd",
library: "@grafnode/components"
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
}
]
},
externals: {
'react': 'react',
'lodash': 'lodash',
'styled-components': 'styled-components',
'@tippyjs/react': '@tippyjs/react',
'@tabler/icons': '@tabler/icons',
'@fortawesome/free-solid-svg-icons': '@fortawesome/free-solid-svg-icons',
'@fortawesome/react-fontawesome': '@fortawesome/react-fontawesome',
'classnames': 'classnames',
'react-tabs': 'react-tabs',
'codemirror': 'codemirror',
'graphql': 'graphql',
'escape-html': 'escape-html',
'formik': 'formik',
'markdown-it': 'markdown-it',
'nanoid': 'nanoid',
'graphql-request': 'graphql-request',
'yup': 'yup'
},
plugins: [
new MiniCssExtractPlugin()
]
};

View File

@ -1,4 +0,0 @@
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}

View File

@ -1,3 +0,0 @@
{
"extends": "next/core-web-vitals"
}

View File

@ -1,34 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel

View File

@ -1,3 +0,0 @@
module.exports = {
reactStrictMode: true,
}

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +0,0 @@
{
"name": "@grafnode/run",
"version": "0.0.1",
"description": "",
"main": "src/index.js",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"repository": {
"type": "git",
"url": "git+https://github.com/grafnode/grafnode.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/grafnode/grafnode/issues"
},
"homepage": "https://github.com/grafnode/grafnode#readme",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@grafnode/components": "^0.0.1",
"@grafnode/www": "^0.0.1",
"@tabler/icons": "^1.46.0",
"@tippyjs/react": "^4.2.6",
"classnames": "^2.3.1",
"codemirror": "^5.64.0",
"codemirror-graphql": "^1.2.5",
"escape-html": "^1.0.3",
"formik": "^2.2.9",
"graphiql": "^1.5.9",
"graphql": "^16.2.0",
"graphql-request": "^3.7.0",
"idb": "^7.0.0",
"immer": "^9.0.7",
"lodash": "^4.17.21",
"markdown-it": "^12.2.0",
"mousetrap": "^1.6.5",
"nanoid": "^3.1.30",
"next": "12.0.4",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-tabs": "^3.2.3",
"sass": "^1.46.0",
"styled-components": "^5.3.3",
"tailwindcss": "^2.2.19",
"yup": "^0.32.11"
},
"devDependencies": {
"babel-plugin-styled-components": "^2.0.2",
"babel-preset-next": "^1.4.0",
"eslint": "7.32.0",
"eslint-config-next": "12.0.4"
}
}

View File

@ -1,34 +0,0 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@ -1,91 +0,0 @@
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import Mousetrap from 'mousetrap';
import SearchNotebase from 'components/SearchNotebase';
import { useStore } from 'providers/Store';
import actions from 'providers/Store/actions';
import { safeTrim, isStringWithAtleastAChar} from 'utils/text';
export const HotkeysContext = React.createContext();
export const HotkeysProvider = props => {
const router = useRouter();
const [openSearch, setOpenSearch] = useState(false);
const [state, dispatch, saveTransactions] = useStore();
const {
notebaseName
} = state;
const searchNotebase = () => {
if(!openSearch) {
setOpenSearch(true);
}
};
useEffect(() => {
Mousetrap.bind(['command+k', 'ctrl+k', 'shift shift'], (e) => {
if(!openSearch) {
setOpenSearch(true);
}
return false; // this stops the event bubbling
});
Mousetrap.bind(['command+s', 'ctrl+s'], (e) => {
saveTransactions();
return false; // this stops the event bubbling
});
return () => {
Mousetrap.unbind(['command+k', 'ctrl+k', 'shift shift']);
Mousetrap.unbind(['command+s', 'ctrl+s']);
};
}, []);
const closeSearchModal = () => setOpenSearch(false);
// todo: instead of passing router, perhaps have a action to update current page and a useEffect to push url
// https://stackoverflow.com/questions/58633756/is-it-possible-to-put-a-callback-to-usereducers-dispatch-in-react-hooks
const handleSelect = (page) => {
setOpenSearch(false);
if(!page || !isStringWithAtleastAChar(page.title)) {
return;
}
if(page.uid) {
router.push(`/n/${notebaseName}/${page.uid}`);
} else {
dispatch({
type: actions.NEW_PAGE,
title: safeTrim(page.title),
router: router
});
}
};
const value = {
searchNotebase: searchNotebase
};
return (
<HotkeysContext.Provider value={value} {...props}>
{openSearch && (
<SearchNotebase onClose={closeSearchModal} onSelect={handleSelect}/>
)}
{props.children}
</HotkeysContext.Provider>
);
};
export const useHotkeys = () => {
const context = React.useContext(HotkeysContext);
if (!context) {
throw new Error(`useHotkeys must be used within a HotkeysProvider`);
}
return context;
}
export default HotkeysProvider;

View File

@ -1,20 +0,0 @@
import Head from 'next/head';
import Main from 'pageComponents/Main';
import GlobalStyle from '../globalStyles';
export default function Home() {
return (
<div>
<Head>
<title>grafnode</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<GlobalStyle />
<main>
<Main />
</main>
</div>
)
}

View File

@ -4,7 +4,7 @@ const StyledWrapper = styled.div`
div.CodeMirror {
border: solid 1px var(--color-codemirror-border);
/* todo: find a better way */
height: calc(100vh - 230px);
height: calc(100vh - 255px);
}
textarea.cm-editor {

View File

@ -6,12 +6,18 @@
*/
import React from 'react';
import CodeMirror from 'codemirror';
import MD from 'markdown-it';
import StyledWrapper from './StyledWrapper';
import onHasCompletion from './onHasCompletion';
let CodeMirror;
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
if (!SERVER_RENDERED) {
CodeMirror = require('codemirror');
}
const md = new MD();
const AUTO_COMPLETE_AFTER_KEY = /^[a-zA-Z0-9_@(]$/;
@ -202,6 +208,17 @@ export default class QueryEditor extends React.Component {
};
_onBeforeChange(_instance, change) {
const normalizeWhitespace = (line) => {
// Unicode whitespace characters that break the interface.
const invalidCharacters = Array.from({ length: 11 }, (_, i) => {
// \u2000 -> \u200a
return String.fromCharCode(0x2000 + i);
}).concat(['\u2028', '\u2029', '\u202f', '\u00a0']);
const sanitizeRegex = new RegExp('[' + invalidCharacters.join('') + ']', 'g');
return line.replace(sanitizeRegex, ' ');
};
// The update function is only present on non-redo, non-undo events.
if (change.origin === 'paste') {
const text = change.text.map(normalizeWhitespace);

View File

@ -9,9 +9,7 @@ import MD from 'markdown-it';
import {
GraphQLNonNull,
GraphQLList,
GraphQLType,
GraphQLField,
GraphQLList
} from 'graphql';
const md = new MD();

View File

@ -4,7 +4,7 @@ const StyledWrapper = styled.div`
div.CodeMirror {
border: solid 1px var(--color-codemirror-border);
/* todo: find a better way */
height: calc(100vh - 230px);
height: calc(100vh - 255px);
}
textarea.cm-editor {

View File

@ -1,7 +1,13 @@
import React, { useState, useRef, useEffect } from 'react';
import * as CodeMirror from 'codemirror';
import StyledWrapper from './StyledWrapper';
let CodeMirror;
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
if (!SERVER_RENDERED) {
CodeMirror = require('codemirror');
}
const QueryResult = ({data, isLoading, width}) => {
const [cmEditor, setCmEditor] = useState(null);
const editor = useRef();

View File

@ -1,5 +1,5 @@
import React from 'react';
import { IconCode, IconStack, IconGitPullRequest, IconUser, IconUsers, IconSettings, IconLayoutGrid, IconBuilding } from '@tabler/icons';
import { IconCode, IconStack, IconGitPullRequest, IconUser, IconUsers, IconSettings,IconBuilding } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
const MenuBar = () => {
@ -18,9 +18,6 @@ const MenuBar = () => {
<div className="menu-item">
<IconUsers size={28} strokeWidth={1.5}/>
</div>
<div className="menu-item">
<IconLayoutGrid size={28} strokeWidth={1.5}/>
</div>
</div>
<div className="flex flex-col flex-grow justify-end">
{/* Teams Icon */}

View File

@ -1,43 +1,44 @@
import React from 'react';
import dynamic from 'next/dynamic'
import {
RequestTabs,
Sidebar
} from '@grafnode/components';
import RequestTabs from 'components/RequestTabs';
import RequestTabPanel from 'components/RequestTabPanel';
import Sidebar from 'components/Sidebar';
import actions from 'providers/Store/actions';
import { useStore } from '../../providers/Store/index';
import StyledWrapper from './StyledWrapper';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/keymap/sublime';
import 'codemirror/addon/comment/comment';
import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/search/search';
import 'codemirror/addon/search/searchcursor';
import 'codemirror/addon/search/jump-to-line';
import 'codemirror/addon/dialog/dialog';
import 'codemirror-graphql/hint';
import 'codemirror-graphql/lint';
import 'codemirror-graphql/info';
import 'codemirror-graphql/jump';
import 'codemirror-graphql/mode';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/dialog/dialog.css';
import 'codemirror/addon/hint/show-hint.css';
import { IconStack, IconGitFork } from '@tabler/icons';
const RequestTabPanel = dynamic(import('@grafnode/components').then(mod => mod.RequestTabPanel), { ssr: false });
const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true;
if(!SERVER_RENDERED) {
require('codemirror/mode/javascript/javascript');
require('codemirror/mode/javascript/javascript');
require('codemirror/addon/edit/matchbrackets');
require('codemirror/addon/fold/brace-fold');
require('codemirror/addon/fold/foldgutter');
require('codemirror/addon/hint/show-hint');
require('codemirror/keymap/sublime');
require('codemirror/addon/comment/comment');
require('codemirror/addon/edit/closebrackets');
require('codemirror/addon/search/search');
require('codemirror/addon/search/searchcursor');
require('codemirror/addon/search/jump-to-line');
require('codemirror/addon/dialog/dialog');
require('codemirror-graphql/hint');
require('codemirror-graphql/lint');
require('codemirror-graphql/info');
require('codemirror-graphql/jump');
require('codemirror-graphql/mode');
}
export default function Main() {
const [state, dispatch] = useStore();
if (SERVER_RENDERED) {
return null;
}
const {
collections,
requestTabs,
@ -54,7 +55,7 @@ export default function Main() {
activeRequestTabId={activeRequestTabId}
/>
<section className='flex flex-grow flex-col'>
<div className="flex items-center" style={{"padding": "8px", "padding-bottom": "4px"}}>
<div className="flex items-center" style={{padding: "8px", paddingBottom: "4px"}}>
<IconStack size={18} strokeWidth={1.5}/>
<span className="ml-2 mr-4 font-semibold">spacex</span>
<IconGitFork size={16} strokeWidth={1}/>

View File

@ -1,46 +1,20 @@
import { useState, useEffect } from 'react'
const Home = () => {
const [input, setInput] = useState('')
const [message, setMessage] = useState(null)
useEffect(() => {
const handleMessage = (event, message) => setMessage(message)
window.electron.message.on(handleMessage)
return () => {
window.electron.message.off(handleMessage)
}
}, [])
const handleSubmit = (event) => {
event.preventDefault()
window.electron.message.send(input)
setMessage(null)
}
import Head from 'next/head';
import Main from 'pageComponents/Main';
import GlobalStyle from '../globalStyles';
export default function Home() {
return (
<div>
<h1>Hello Electron!</h1>
<Head>
<title>grafnode</title>
<link rel="icon" href="/favicon.ico" />
</Head>
{message && <p>{message}</p>}
<GlobalStyle />
<form onSubmit={handleSubmit}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
</form>
<style jsx>{`
h1 {
color: red;
font-size: 50px;
}
`}</style>
<main>
<Main />
</main>
</div>
)
}
export default Home;

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB