tab management

This commit is contained in:
Jan Prochazka 2020-01-20 21:20:53 +01:00
parent 07e2b0f26f
commit 119b30260f
9 changed files with 113 additions and 14 deletions

View File

@ -16,7 +16,8 @@
"react-modal": "^3.11.1",
"react-scripts": "3.3.0",
"socket.io-client": "^2.3.0",
"styled-components": "^4.4.1"
"styled-components": "^4.4.1",
"uuid": "^3.4.0"
},
"scripts": {
"start": "cross-env PORT=5000 react-scripts start",

View File

@ -1,7 +1,7 @@
import React from 'react';
import './index.css';
import Screen from './Screen';
import { CurrentWidgetProvider, CurrentDatabaseProvider } from './utility/globalState';
import { CurrentWidgetProvider, CurrentDatabaseProvider, OpenedFilesProvider } from './utility/globalState';
import { SocketProvider } from './utility/SocketProvider';
function App() {
@ -9,7 +9,9 @@ function App() {
<CurrentWidgetProvider>
<CurrentDatabaseProvider>
<SocketProvider>
<Screen />
<OpenedFilesProvider>
<Screen />
</OpenedFilesProvider>
</SocketProvider>
</CurrentDatabaseProvider>
</CurrentWidgetProvider>

View File

@ -3,12 +3,13 @@ import styled from 'styled-components';
import theme from './theme';
import { TableIcon } from './icons';
import { useOpenedFiles, useSetOpenedFiles } from './utility/globalState';
const files = [
{ name: 'app.js' },
{ name: 'BranchCategory', type: 'table', selected: true },
{ name: 'ApplicationList' },
];
// const files = [
// { name: 'app.js' },
// { name: 'BranchCategory', type: 'table', selected: true },
// { name: 'ApplicationList' },
// ];
const FileTabItem = styled.div`
border-right: 1px solid white;
@ -30,10 +31,31 @@ const FileNameWrapper = styled.span`
`;
export default function FilesTabsPanel() {
const files = useOpenedFiles();
const setOpenedFiles = useSetOpenedFiles();
const handleTabClick = id => {
setOpenedFiles(files =>
files.map(x => ({
...x,
selected: x.id == id,
}))
);
};
const handleMouseUp = (e, id) => {
if (e.button == 1) {
setOpenedFiles(files => files.filter(x => x.id != id));
}
};
return (
<>
{files.map(file => (
<FileTabItem {...file} key={file.name}>
<FileTabItem
{...file}
key={file.id}
onClick={() => handleTabClick(file.id)}
onMouseUp={e => handleMouseUp(e, file.id)}
>
<TableIcon />
<FileNameWrapper>{file.name}</FileNameWrapper>
</FileTabItem>

View File

@ -2,11 +2,14 @@ import React from 'react';
import styled from 'styled-components';
import { showMenu } from '../modals/DropDownMenu';
import { AppObjectCore } from './AppObjects';
import { useSetOpenedFiles } from '../utility/globalState';
export function AppObjectList({ list, makeAppObj, SubItems = undefined, onObjectClick = undefined }) {
const setOpenedFiles = useSetOpenedFiles();
return (list || []).map(x => {
const appobj = makeAppObj(x);
let res = <AppObjectCore key={appobj.key} {...appobj} data={x} makeAppObj={makeAppObj} onClick={onObjectClick} />;
const appobj = makeAppObj(x, { setOpenedFiles });
if (onObjectClick) appobj.onClick = onObjectClick;
let res = <AppObjectCore key={appobj.key} data={x} makeAppObj={makeAppObj} {...appobj} />;
if (SubItems) {
res = (
<>

View File

@ -1,6 +1,7 @@
import React from 'react';
import styled from 'styled-components';
import { showMenu } from '../modals/DropDownMenu';
import { useSetOpenedFiles } from '../utility/globalState';
const AppObjectDiv = styled.div`
padding: 5px;
@ -34,6 +35,7 @@ export function AppObjectCore({ title, Icon, Menu, data, makeAppObj, onClick })
}
export function AppObjectControl({ data, makeAppObj }) {
const appobj = makeAppObj(data);
const setOpenedFiles = useSetOpenedFiles();
const appobj = makeAppObj(data, { setOpenedFiles });
return <AppObjectCore {...appobj} data={data} makeAppObj={makeAppObj} />;
}

View File

@ -1,4 +1,5 @@
import React from 'react';
import uuidv1 from 'uuid/v1';
import { TableIcon } from '../icons';
import { DropDownMenuItem } from '../modals/DropDownMenu';
import showModal from '../modals/showModal';
@ -20,10 +21,14 @@ function Menu({ data, makeAppObj }) {
);
}
export default function tableAppObject({ pureName, schemaName }) {
export default function tableAppObject({ pureName, schemaName }, { setOpenedFiles }) {
const title = schemaName ? `${schemaName}.${pureName}` : pureName;
const key = title;
const Icon = TableIcon;
const onClick = ({ schemaName, pureName }) => {
const id = uuidv1();
setOpenedFiles(files => [...files, { id, name: pureName }]);
};
return { title, key, Icon, Menu };
return { title, key, Icon, Menu, onClick };
}

View File

@ -1,4 +1,5 @@
import React from 'react';
import useStorage from './useStorage';
function createGlobalState(defaultValue) {
const Context = React.createContext(null);
@ -19,8 +20,30 @@ function createGlobalState(defaultValue) {
return [Provider, useValue, useSetValue];
}
function createStorageState(storageKey, defaultValue) {
const Context = React.createContext(null);
function Provider({ children }) {
const [currentvalue, setCurrentValue] = useStorage(storageKey, localStorage, defaultValue);
return <Context.Provider value={[currentvalue, setCurrentValue]}>{children}</Context.Provider>;
}
function useValue() {
return React.useContext(Context)[0];
}
function useSetValue() {
return React.useContext(Context)[1];
}
return [Provider, useValue, useSetValue];
}
const [CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget] = createGlobalState('database');
export { CurrentWidgetProvider, useCurrentWidget, useSetCurrentWidget };
const [CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase] = createGlobalState(null);
export { CurrentDatabaseProvider, useCurrentDatabase, useSetCurrentDatabase };
const [OpenedFilesProvider, useOpenedFiles, useSetOpenedFiles] = createStorageState('openedFiles', []);
export { OpenedFilesProvider, useOpenedFiles, useSetOpenedFiles };

View File

@ -0,0 +1,36 @@
import React from 'react';
export default function useStorage(key, storageObject, initialValue) {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = React.useState(() => {
try {
// Get from local storage by key
const item = storageObject.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error also return initialValue
console.log(error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = value => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore = value instanceof Function ? value(storedValue) : value;
// Save state
setStoredValue(valueToStore);
// Save to local storage
storageObject.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
return [storedValue, setValue];
}

View File

@ -10412,6 +10412,11 @@ uuid@^3.0.1, uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
uuid@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
v8-compile-cache@^2.0.3:
version "2.1.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"