chore: adjust bg and add tests (#971)

* chore: adjust bg and add tests

* chore: add tests files

* chore: temporary fix tests
This commit is contained in:
Tobias Åström
2022-10-21 12:58:28 +02:00
committed by GitHub
parent 520f0537ee
commit 3a8c48d564
4 changed files with 167 additions and 115 deletions

View File

@@ -16,6 +16,7 @@ import useLayout, { useAppLayout } from '../hooks/useLayout';
import InstanceContext from '../contexts/InstanceContext'; import InstanceContext from '../contexts/InstanceContext';
import useObjectSelections from '../hooks/useObjectSelections'; import useObjectSelections from '../hooks/useObjectSelections';
import eventmixin from '../selections/event-mixin'; import eventmixin from '../selections/event-mixin';
import { resolveBgColor, resolveBgImage } from '../utils/background-props';
/** /**
* @interface * @interface
@@ -272,17 +273,6 @@ const loadType = async ({ dispatch, types, visualization, version, model, app, s
return undefined; return undefined;
}; };
const resolveBgColor = (bgComp, theme) => {
const bgColor = bgComp?.bgColor;
if (bgColor && theme) {
if (bgColor.useColorExpression) {
return theme.validateColor(bgColor.colorExpression);
}
return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color) : undefined;
}
return undefined;
};
const Cell = forwardRef( const Cell = forwardRef(
({ halo, model, initialSnOptions, initialSnPlugins, initialError, onMount, currentId }, ref) => { ({ halo, model, initialSnOptions, initialSnPlugins, initialError, onMount, currentId }, ref) => {
const { app, types } = halo; const { app, types } = halo;
@@ -302,6 +292,8 @@ const Cell = forwardRef(
const [hovering, setHover] = useState(false); const [hovering, setHover] = useState(false);
const hoveringDebouncer = useRef({ enter: null, leave: null }); const hoveringDebouncer = useRef({ enter: null, leave: null });
const [bgColor, setBgColor] = useState(undefined); const [bgColor, setBgColor] = useState(undefined);
const [bgImage, setBgImage] = useState(undefined); // {url: "", size: "", pos: ""}
const focusHandler = useRef({ const focusHandler = useRef({
focusToolbarButton(last) { focusToolbarButton(last) {
// eslint-disable-next-line react/no-this-in-sfc // eslint-disable-next-line react/no-this-in-sfc
@@ -314,13 +306,10 @@ const Cell = forwardRef(
}, []); }, []);
useEffect(() => { useEffect(() => {
setBgColor( const bgComp = layout?.components ? layout.components.find((comp) => comp.key === 'general') : null;
resolveBgColor( setBgColor(resolveBgColor(bgComp, halo.public.theme));
layout && layout.components ? layout.components.find((comp) => comp.key === 'general') : null, setBgImage(resolveBgImage(bgComp, halo.app));
halo.public.theme }, [layout, halo.public.theme, halo.app]);
)
);
}, [layout, halo.public.theme]);
focusHandler.current.blurCallback = (resetFocus) => { focusHandler.current.blurCallback = (resetFocus) => {
halo.root.toggleFocusOfCells(); halo.root.toggleFocusOfCells();
@@ -499,7 +488,17 @@ const Cell = forwardRef(
return ( return (
<Paper <Paper
style={{ position: 'relative', width: '100%', height: '100%', overflow: 'hidden' }} style={{
position: 'relative',
width: '100%',
height: '100%',
overflow: 'hidden',
backgroundColor: bgColor,
backgroundImage: bgImage && bgImage.url ? `url(${bgImage.url})` : undefined,
backgroundRepeat: 'no-repeat',
backgroundSize: bgImage && bgImage.size,
backgroundPosition: bgImage && bgImage.pos,
}}
elevation={0} elevation={0}
square square
className={CellElement.className} className={CellElement.className}
@@ -537,7 +536,6 @@ const Cell = forwardRef(
xs xs
style={{ style={{
height: '100%', height: '100%',
backgroundColor: bgColor,
}} }}
ref={contentRef} ref={contentRef}
> >

View File

@@ -19,89 +19,6 @@ const VizElement = {
className: 'njs-viz', className: 'njs-viz',
}; };
const imageSizingToCssProperty = {
originalSize: 'auto auto',
alwaysFit: 'contain',
fitWidth: '100% auto',
fitHeight: 'auto 100%',
stretchFit: '100% 100%',
alwaysFill: 'cover',
};
const positionToCss = {
'top-left': 'top left',
'top-center': 'top center',
'top-right': 'top right',
'center-left': 'center left',
'center-center': 'center center',
'center-right': 'center right',
'bottom-left': 'bottom left',
'bottom-center': 'bottom center',
'bottom-right': 'bottom right',
};
// TODO: this needs some proper verification
function getSenseServerUrl(app) {
let config;
let wsUrl;
let protocol;
let isSecure;
if (app?.session?.config) {
config = app.session.config;
wsUrl = new URL(config.url);
isSecure = wsUrl.protocol === 'wss:';
protocol = isSecure ? 'https://' : 'http://';
return protocol + wsUrl.host;
}
return undefined;
}
function getBackgroundPosition(bgComp) {
let bkgImagePosition = 'center center';
if (bgComp?.bgImage?.position) {
bkgImagePosition = positionToCss[bgComp.bgImage.position];
}
return bkgImagePosition;
}
function getBackgroundSize(bgComp) {
let bkgImageSize = imageSizingToCssProperty.originalSize;
if (bgComp?.bgImage?.sizing) {
bkgImageSize = imageSizingToCssProperty[bgComp.bgImage.sizing];
}
return bkgImageSize;
}
function resolveImageUrl(app, relativeUrl) {
return relativeUrl ? getSenseServerUrl(app) + relativeUrl : undefined;
}
const resolveBgImage = (bgComp, app) => {
const bgImageDef = bgComp?.bgImage;
if (bgImageDef) {
let url = '';
if (bgImageDef.mode === 'media') {
url = bgImageDef?.mediaUrl?.qStaticContentUrl?.qUrl
? decodeURIComponent(bgImageDef.mediaUrl.qStaticContentUrl.qUrl)
: undefined;
url = resolveImageUrl(app, url);
}
if (bgImageDef.mode === 'expression') {
url = bgImageDef.expressionUrl ? decodeURIComponent(bgImageDef.expressionUrl) : undefined;
}
const pos = getBackgroundPosition(bgComp);
const size = getBackgroundSize(bgComp);
// TODO: need to resolve the URL by the WS path
return url ? { url, pos, size } : undefined;
}
return undefined;
};
function Supernova({ sn, snOptions: options, snPlugins: plugins, layout, appLayout, halo }) { function Supernova({ sn, snOptions: options, snPlugins: plugins, layout, appLayout, halo }) {
const { component } = sn; const { component } = sn;
@@ -111,7 +28,6 @@ function Supernova({ sn, snOptions: options, snPlugins: plugins, layout, appLayo
const [renderCnt, setRenderCnt] = useState(0); const [renderCnt, setRenderCnt] = useState(0);
const [containerRef, containerRect, containerNode] = useRect(); const [containerRef, containerRect, containerNode] = useRect();
const [snNode, setSnNode] = useState(null); const [snNode, setSnNode] = useState(null);
const [bgImage, setBgImage] = useState(undefined); // {url: "", size: "", pos: ""}
const snRef = useCallback((ref) => { const snRef = useCallback((ref) => {
if (!ref) { if (!ref) {
@@ -132,13 +48,6 @@ function Supernova({ sn, snOptions: options, snPlugins: plugins, layout, appLayo
}; };
}, [snNode, component]); }, [snNode, component]);
// Resolve Background Image
useEffect(() => {
setBgImage(
resolveBgImage(layout?.components ? layout.components.find((comp) => comp.key === 'general') : null, halo.app)
);
}, [layout, halo.app]);
// Render // Render
useEffect(() => { useEffect(() => {
if (!isMounted || !snNode || !containerRect) { if (!isMounted || !snNode || !containerRect) {
@@ -218,10 +127,6 @@ function Supernova({ sn, snOptions: options, snPlugins: plugins, layout, appLayo
style={{ style={{
position: 'relative', position: 'relative',
height: '100%', height: '100%',
backgroundImage: bgImage && bgImage.url ? `url(${bgImage.url})` : undefined,
backgroundRepeat: 'no-repeat',
backgroundSize: bgImage && bgImage.size,
backgroundPosition: bgImage && bgImage.pos,
}} }}
className={VizElement.className} className={VizElement.className}
> >

View File

@@ -0,0 +1,58 @@
import theme from '@nebula.js/theme';
import { resolveBgColor, resolveBgImage } from '../background-props';
describe('Background property resolver', () => {
let bgCompLayout;
const t = theme().externalAPI;
const app = {
session: {
config: {
url: 'wss://example.com/lots/of/paths',
},
},
};
beforeEach(() => {
bgCompLayout = {
key: 'general',
bgColor: {
useColorExpression: true,
colorExpression: '#ff0000',
color: { index: -1, color: 'aqua' },
},
bgImage: {
mode: 'media',
mediaUrl: {
qStaticContentUrl: {
qUrl: '/media/Tulips.jpg',
},
},
position: 'top-left',
sizing: 'alwaysFit',
},
};
});
it('should resolve background color by expression', () => {
const color = resolveBgColor(bgCompLayout, t);
expect(color).to.equal('rgb(255, 0, 0)');
});
it('should resolve background color by picker', () => {
bgCompLayout.bgColor.useColorExpression = false;
const color = resolveBgColor(bgCompLayout, t);
expect(color).to.equal('aqua');
});
it('should resolve background image https', () => {
const { url, pos } = resolveBgImage(bgCompLayout, app);
expect(url).to.equal('https://example.com/media/Tulips.jpg');
expect(pos).to.equal('top left');
});
it('should resolve background image http', () => {
app.session.config.url = 'ws://example.com/lots/of/paths';
const { url, size } = resolveBgImage(bgCompLayout, app);
expect(url).to.equal('http://example.com/media/Tulips.jpg');
expect(size).to.equal('contain');
});
});

View File

@@ -0,0 +1,91 @@
const imageSizingToCssProperty = {
originalSize: 'auto auto',
alwaysFit: 'contain',
fitWidth: '100% auto',
fitHeight: 'auto 100%',
stretchFit: '100% 100%',
alwaysFill: 'cover',
};
const positionToCss = {
'top-left': 'top left',
'top-center': 'top center',
'top-right': 'top right',
'center-left': 'center left',
'center-center': 'center center',
'center-right': 'center right',
'bottom-left': 'bottom left',
'bottom-center': 'bottom center',
'bottom-right': 'bottom right',
};
// TODO: this needs some proper verification
function getSenseServerUrl(app) {
let config;
let wsUrl;
let protocol;
let isSecure;
if (app?.session?.config) {
config = app.session.config;
wsUrl = new URL(config.url);
isSecure = wsUrl.protocol === 'wss:';
protocol = isSecure ? 'https://' : 'http://';
return protocol + wsUrl.host;
}
return undefined;
}
function getBackgroundPosition(bgComp) {
let bkgImagePosition = 'center center';
if (bgComp?.bgImage?.position) {
bkgImagePosition = positionToCss[bgComp.bgImage.position];
}
return bkgImagePosition;
}
function getBackgroundSize(bgComp) {
let bkgImageSize = imageSizingToCssProperty.originalSize;
if (bgComp?.bgImage?.sizing) {
bkgImageSize = imageSizingToCssProperty[bgComp.bgImage.sizing];
}
return bkgImageSize;
}
function resolveImageUrl(app, relativeUrl) {
return relativeUrl ? getSenseServerUrl(app) + relativeUrl : undefined;
}
export const resolveBgImage = (bgComp, app) => {
const bgImageDef = bgComp?.bgImage;
if (bgImageDef) {
let url = '';
if (bgImageDef.mode === 'media') {
url = bgImageDef?.mediaUrl?.qStaticContentUrl?.qUrl
? decodeURIComponent(bgImageDef.mediaUrl.qStaticContentUrl.qUrl)
: undefined;
url = resolveImageUrl(app, url);
}
if (bgImageDef.mode === 'expression') {
url = bgImageDef.expressionUrl ? decodeURIComponent(bgImageDef.expressionUrl) : undefined;
}
const pos = getBackgroundPosition(bgComp);
const size = getBackgroundSize(bgComp);
return url ? { url, pos, size } : undefined;
}
return undefined;
};
export const resolveBgColor = (bgComp, theme) => {
const bgColor = bgComp?.bgColor;
if (bgColor && theme) {
if (bgColor.useColorExpression) {
return theme.validateColor(bgColor.colorExpression);
}
return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color) : undefined;
}
return undefined;
};