Added support to specify the background fill color to the table nodes in the ERD tool. #4392

This commit is contained in:
Aditya Toshniwal
2022-10-12 10:07:30 +05:30
committed by GitHub
parent 5b09122676
commit 794cbed57c
17 changed files with 302 additions and 141 deletions

View File

@@ -15,3 +15,5 @@
@import 'node_modules/jsoneditor/dist/jsoneditor.min.css';
@import 'node_modules/react-checkbox-tree/lib/react-checkbox-tree.css';
@import 'node_modules/@simonwep/pickr/dist/themes/monolith.min.css';

View File

@@ -20,6 +20,7 @@ import getStandardTheme from './standard';
import getDarkTheme from './dark';
import getHightContrastTheme from './high_contrast';
import { CssBaseline } from '@material-ui/core';
import pickrOverride from './overrides/pickr.override';
/* Common settings across all themes */
let basicSettings = createMuiTheme();
@@ -309,7 +310,8 @@ function getFinalTheme(baseTheme) {
listStyle: 'none',
margin: 0,
padding: 0,
}
},
...pickrOverride(baseTheme),
},
},
MuiOutlinedInput: {

View File

@@ -0,0 +1,31 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
export default function pickrOverride(theme) {
return {
'.pickr, .pcr-app': {
fontFamily: theme.typography.fontFamily,
'& *:focus': {
outline: 'none !important',
},
'& .pcr-save': {
backgroundColor: theme.palette.primary.main + '!important',
borderRadius: theme.shape.borderRadius + 'px !important',
color: theme.palette.primary.contrastText + '!important',
border: '1px solid '+theme.palette.primary.main,
},
'& .pcr-clear': {
backgroundColor: theme.palette.default.main + '!important',
borderRadius: theme.shape.borderRadius + 'px !important',
color: theme.palette.default.contrastText + '!important',
border: '1px solid '+theme.palette.default.borderColor,
},
}
};
}

View File

@@ -25,7 +25,6 @@ import DescriptionIcon from '@material-ui/icons/Description';
import AssignmentTurnedIn from '@material-ui/icons/AssignmentTurnedIn';
import Select, { components as RSComponents } from 'react-select';
import CreatableSelect from 'react-select/creatable';
import Pickr from '@simonwep/pickr';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import HTMLReactParse from 'html-react-parser';
@@ -42,6 +41,7 @@ import KeyboardShortcuts from './KeyboardShortcuts';
import QueryThresholds from './QueryThresholds';
import SelectThemes from './SelectThemes';
import { showFileManager } from '../helpers/showFileManager';
import { withColorPicker } from '../helpers/withColorPicker';
const useStyles = makeStyles((theme) => ({
@@ -980,120 +980,17 @@ FormInputSelect.propTypes = {
inputRef: CustomPropTypes.ref
};
/* React wrapper on color pickr */
const ColorButton = withColorPicker(PgIconButton);
export function InputColor({ value, controlProps, disabled, onChange, currObj }) {
const pickrOptions = {
showPalette: true,
allowEmpty: true,
colorFormat: 'HEX',
defaultColor: null,
position: 'right-middle',
clearText: gettext('No color'),
...controlProps,
disabled: disabled,
};
const eleRef = useRef();
const pickrObj = useRef();
const classes = useStyles();
const setColor = (newVal) => {
pickrObj.current &&
pickrObj.current.setColor((_.isUndefined(newVal) || newVal == '') ? pickrOptions.defaultColor : newVal);
};
const destroyPickr = () => {
if (pickrObj.current) {
pickrObj.current.destroy();
pickrObj.current = null;
}
};
const initPickr = () => {
/* pickr does not have way to update options, need to
destroy and recreate pickr to reflect options */
destroyPickr();
pickrObj.current = new Pickr({
el: eleRef.current,
useAsButton: true,
theme: 'monolith',
swatches: [
'#000', '#666', '#ccc', '#fff', '#f90', '#ff0', '#0f0',
'#f0f', '#f4cccc', '#fce5cd', '#d0e0e3', '#cfe2f3', '#ead1dc', '#ea9999',
'#b6d7a8', '#a2c4c9', '#d5a6bd', '#e06666', '#93c47d', '#76a5af', '#c27ba0',
'#f1c232', '#6aa84f', '#45818e', '#a64d79', '#bf9000', '#0c343d', '#4c1130',
],
position: pickrOptions.position,
strings: {
clear: pickrOptions.clearText,
},
components: {
palette: pickrOptions.showPalette,
preview: true,
hue: pickrOptions.showPalette,
interaction: {
clear: pickrOptions.allowEmpty,
defaultRepresentation: pickrOptions.colorFormat,
disabled: pickrOptions.disabled,
},
},
}).on('init', instance => {
setColor(value);
disabled && instance.disable();
const { lastColor } = instance.getRoot().preview;
const { clear } = instance.getRoot().interaction;
/* Cycle the keyboard navigation within the color picker */
clear.addEventListener('keydown', (e) => {
if (e.keyCode === 9) {
e.preventDefault();
e.stopPropagation();
lastColor.focus();
}
});
lastColor.addEventListener('keydown', (e) => {
if (e.keyCode === 9 && e.shiftKey) {
e.preventDefault();
e.stopPropagation();
clear.focus();
}
});
}).on('clear', () => {
onChange && onChange('');
}).on('change', (color) => {
onChange && onChange(color.toHEXA().toString());
}).on('show', (color, instance) => {
const { palette } = instance.getRoot().palette;
palette.focus();
}).on('hide', (instance) => {
const button = instance.getRoot().button;
button.focus();
});
if (currObj) {
currObj(pickrObj.current);
}
};
useEffect(() => {
initPickr();
return () => {
destroyPickr();
};
}, [...Object.values(pickrOptions)]);
useEffect(() => {
if (pickrObj.current) {
setColor(value);
}
}, [value]);
let btnStyles = { backgroundColor: value };
return (
<PgIconButton ref={eleRef} title={gettext('Select the color')} className={classes.colorBtn} style={btnStyles} disabled={pickrOptions.disabled}
icon={(_.isUndefined(value) || _.isNull(value) || value === '') && <CloseIcon />}
<ColorButton title={gettext('Select the color')} className={classes.colorBtn} style={btnStyles} disabled={disabled}
icon={(_.isUndefined(value) || _.isNull(value) || value === '') && <CloseIcon />} options={{
...controlProps,
disabled: disabled
}} onChange={onChange} value={value} currObj={currObj}
/>
);
}

View File

@@ -0,0 +1,146 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
/* React HOC on color pickr */
import Pickr from '@simonwep/pickr';
import React, { useEffect, useRef } from 'react';
import gettext from 'sources/gettext';
import PropTypes from 'prop-types';
import { fullHexColor } from '../utils';
export function withColorPicker(Component) {
// eslint-disable-next-line react/display-name
const HOCComponent = ({value, currObj, onChange, onSave, options, ...props})=>{
const pickrOptions = {
showPalette: true,
allowEmpty: true,
allowSave: false,
colorFormat: 'HEX',
defaultColor: null,
position: 'right-middle',
clearText: gettext('Clear'),
...options,
};
const eleRef = useRef();
const pickrObj = useRef();
const setColor = (newVal) => {
pickrObj.current?.setColor((_.isUndefined(newVal) || newVal == '') ? pickrOptions.defaultColor : newVal);
};
const destroyPickr = () => {
if (pickrObj.current) {
pickrObj.current.destroy();
pickrObj.current = null;
}
};
const initPickr = () => {
/* pickr does not have way to update options, need to
destroy and recreate pickr to reflect options */
destroyPickr();
pickrObj.current = new Pickr({
el: eleRef.current,
useAsButton: true,
theme: 'monolith',
swatches: [
'#000', '#666', '#ccc', '#fff', '#f90', '#ff0', '#0f0',
'#f0f', '#f4cccc', '#fce5cd', '#d0e0e3', '#cfe2f3', '#ead1dc', '#ea9999',
'#b6d7a8', '#a2c4c9', '#d5a6bd', '#e06666', '#93c47d', '#76a5af', '#c27ba0',
'#f1c232', '#6aa84f', '#45818e', '#a64d79', '#bf9000', '#0c343d', '#4c1130',
],
position: pickrOptions.position,
strings: {
clear: pickrOptions.clearText,
},
components: {
palette: pickrOptions.showPalette,
preview: true,
hue: pickrOptions.showPalette,
interaction: {
clear: pickrOptions.allowEmpty,
defaultRepresentation: pickrOptions.colorFormat,
disabled: pickrOptions.disabled,
save: pickrOptions.allowSave,
},
},
}).on('init', instance => {
setColor(value);
pickrOptions.disabled && instance.disable();
const { lastColor } = instance.getRoot().preview;
const { clear } = instance.getRoot().interaction;
/* Cycle the keyboard navigation within the color picker */
clear.addEventListener('keydown', (e) => {
if (e.keyCode === 9) {
e.preventDefault();
e.stopPropagation();
lastColor.focus();
}
});
lastColor.addEventListener('keydown', (e) => {
if (e.keyCode === 9 && e.shiftKey) {
e.preventDefault();
e.stopPropagation();
clear.focus();
}
});
}).on('clear', () => {
onChange?.('');
}).on('change', (color) => {
onChange?.(color.toHEXA().toString());
}).on('show', (color, instance) => {
const { palette } = instance.getRoot().palette;
palette.focus();
}).on('hide', (instance) => {
const button = instance.getRoot().button;
button.focus();
}).on('save', (color, instance) => {
if(color) {
color.toHEXA().toString() != fullHexColor(value) && onSave?.(color.toHEXA().toString());
instance?.hide();
} else {
onSave?.('');
}
});
if (currObj) {
currObj(pickrObj.current);
}
};
useEffect(() => {
initPickr();
return () => {
destroyPickr();
};
}, [...Object.values(pickrOptions)]);
useEffect(() => {
if (pickrObj.current && !pickrOptions.allowSave) {
setColor(value);
}
}, [value, pickrOptions.allowSave]);
return <Component ref={eleRef} {...props}/>;
};
HOCComponent.propTypes = {
value: PropTypes.string,
currObj: PropTypes.func,
onChange: PropTypes.func,
onSave: PropTypes.func,
options: PropTypes.object,
};
return HOCComponent;
}

View File

@@ -658,3 +658,10 @@ export function pgHandleItemError(xhr, args) {
}
return false;
}
export function fullHexColor(shortHex) {
if(shortHex?.length == 4) {
return shortHex.replace(RegExp('#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])'), '#$1$1$2$2$3$3').toUpperCase();
}
return shortHex;
}

View File

@@ -1,19 +0,0 @@
$palette-soft-red: $color-ternary;
$border-radius-mid: $btn-border-radius;
$font-family: $font-family-base;
$box-shadow-app: $popover-box-shadow;
@import "node_modules/@simonwep/pickr/src/scss/themes/monolith.scss";
.pickr, .pcr-app {
*:focus {
outline: none !important;
}
}
.pickr .pcr-button{
border: $input-border-width solid $input-border-color;
&:focus {
box-shadow: $input-btn-focus-box-shadow !important;
}
}

View File

@@ -27,7 +27,6 @@ $theme-colors: (
@import 'pgadmin.grid';
@import 'pgadmin.style';
@import 'bootstrap4-toggle.overrides';
@import 'pickr.overrides';
@import 'jsoneditor.overrides';
@import 'pgadmin4-tree.overrides';
@import 'pgadmin4-tree/src/css/styles';